import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.WorkDuration;
import org.sonar.batch.components.Period;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.debt.IssueChangelogDebtCalculator;
context.saveMeasure(measure);
}
- private Double calculateNewTechnicalDebtValue(Collection<Issue> issues, @Nullable Date periodDate) {
- WorkDuration duration = null;
+ private long calculateNewTechnicalDebtValue(Collection<Issue> issues, @Nullable Date periodDate) {
+ long result = 0;
for (Issue issue : issues) {
- WorkDuration debt = issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, periodDate);
+ Long debt = issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, periodDate);
if (debt != null) {
- duration = duration != null ? duration.add(debt) : debt;
+ result += debt;
}
}
- return duration != null ? duration.toWorkingDays() : 0d;
+ return result;
}
private boolean shouldSaveNewMetrics(DecoratorContext context) {
if @dashboard_configuration.selected_period?
technical_debt_variation = variation_value(technical_debt)
new_technical_debt_variation = variation_value(new_technical_debt)
- estimated_cleared_technical_debt = (new_technical_debt_variation - technical_debt_variation).to_f if technical_debt_variation && new_technical_debt_variation
+ estimated_cleared_technical_debt = (new_technical_debt_variation - technical_debt_variation).to_i if technical_debt_variation && new_technical_debt_variation
%>
<% if new_technical_debt_variation && new_technical_debt_variation > 0 %>
<br/>
<br/>
<span style="font-weight: bold">
<%= message('widget.rules.removed') -%>
- <span class="varb"><%= number_with_precision(estimated_cleared_technical_debt, :precision => 1) -%></span>
+ <span class="varb"><%= Internal.work_duration_formatter.abbreviation(estimated_cleared_technical_debt) -%></span>
</span>
<% end %>
<% end %>
private static final int HOURS_IN_DAY = 8;
- long oneDay = 1 * HOURS_IN_DAY * 60 * 60L;
- long twoDays = 2 * HOURS_IN_DAY * 60 * 60L;
- long fiveDays = 5 * HOURS_IN_DAY * 60 * 60L;
+ Long oneDay = 1 * HOURS_IN_DAY * 60 * 60L;
+ Long twoDays = 2 * HOURS_IN_DAY * 60 * 60L;
+ Long fiveDays = 5 * HOURS_IN_DAY * 60 * 60L;
@Before
public void setup() {
when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, fiveDaysAgo), new Period(2, tenDaysAgo)));
WorkDurationFactory workDurationFactory = new WorkDurationFactory(settings);
- decorator = new NewTechnicalDebtDecorator(perspectives, timeMachineConfiguration, new IssueChangelogDebtCalculator(workDurationFactory));
+ decorator = new NewTechnicalDebtDecorator(perspectives, timeMachineConfiguration, new IssueChangelogDebtCalculator());
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 1.0, 1.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 1.0 * oneDay, 1.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0, 4.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * oneDay, 4.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0, 5.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * oneDay, 5.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0, 5.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * oneDay, 5.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0, 4.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * oneDay, 4.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0, 7.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * oneDay, 7.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 5.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 5.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is null, period2 is null
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0, 5.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * oneDay, 5.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 7.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 7.0 * oneDay)));
}
@Test
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0, 14.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * oneDay, 14.0 * oneDay)));
}
@Test
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.utils.WorkDuration;
-import org.sonar.api.utils.WorkDurationFactory;
import org.sonar.core.issue.IssueUpdater;
import javax.annotation.CheckForNull;
public class IssueChangelogDebtCalculator implements BatchComponent {
- private final WorkDurationFactory workDurationFactory;
-
- public IssueChangelogDebtCalculator(WorkDurationFactory workDurationFactory) {
- this.workDurationFactory = workDurationFactory;
- }
-
@CheckForNull
- public WorkDuration calculateNewTechnicalDebt(Issue issue, @Nullable Date periodDate) {
+ public Long calculateNewTechnicalDebt(Issue issue, @Nullable Date periodDate) {
Long debt = ((DefaultIssue) issue).debt();
- WorkDuration currentTechnicalDebt = debt != null ? workDurationFactory.createFromSeconds(debt) : null;
Date periodDatePlusOneSecond = periodDate != null ? DateUtils.addSeconds(periodDate, 1) : null;
if (isAfter(issue.creationDate(), periodDatePlusOneSecond)) {
- return currentTechnicalDebt;
+ return debt;
} else {
- return calculateNewTechnicalDebtValueFromChangelog(currentTechnicalDebt, issue, periodDate);
+ return calculateNewTechnicalDebtValueFromChangelog(debt, issue, periodDate);
}
}
@CheckForNull
- private WorkDuration calculateNewTechnicalDebtValueFromChangelog(@Nullable WorkDuration currentTechnicalDebtValue, Issue issue, Date periodDate) {
+ private Long calculateNewTechnicalDebtValueFromChangelog(@Nullable Long 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();
- WorkDuration newValue = newValue(diff);
- WorkDuration oldValue = oldValue(diff);
if (isLesserOrEqual(date, periodDate)) {
// return new value from the change that is just before the period date
- return subtractNeverNegative(currentTechnicalDebtValue, newValue);
+ return subtractNeverNegative(currentTechnicalDebtValue, newValue(diff));
}
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 subtractNeverNegative(currentTechnicalDebtValue, oldValue);
+ return subtractNeverNegative(currentTechnicalDebtValue, oldValue(diff));
}
}
// Return null when no changelog
* SONAR-5059
*/
@CheckForNull
- private WorkDuration subtractNeverNegative(@Nullable WorkDuration workDuration, WorkDuration toSubtractWith) {
- if (workDuration != null) {
- WorkDuration result = workDuration.subtract(toSubtractWith);
- if (result.toSeconds() > 0) {
- return result;
- }
- }
- return null;
+ private Long subtractNeverNegative(@Nullable Long value, Long with) {
+ Long result = (value != null ? value : 0) - (with != null ? with : 0);
+ return result > 0 ? result : null;
}
private List<FieldDiffs> technicalDebtHistory(Issue issue) {
}
@CheckForNull
- private WorkDuration newValue(FieldDiffs fieldDiffs) {
+ private Long 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();
- if (newValue != null) {
- return workDurationFactory.createFromSeconds(newValue);
- }
+ return entry.getValue().newValueLong();
}
}
return null;
}
@CheckForNull
- private WorkDuration oldValue(FieldDiffs fieldDiffs) {
+ private Long 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();
- if (value != null) {
- return workDurationFactory.createFromSeconds(value);
- }
+ return entry.getValue().oldValueLong();
}
}
return null;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.utils.WorkDuration;
-import org.sonar.api.utils.WorkDurationFactory;
import java.util.Date;
Settings settings = new Settings();
settings.setProperty(CoreProperties.HOURS_IN_DAY, Integer.toString(HOURS_IN_DAY));
- issueChangelogDebtCalculator = new IssueChangelogDebtCalculator(new WorkDurationFactory(settings));
+ issueChangelogDebtCalculator = new IssueChangelogDebtCalculator();
}
@Test
)
);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(
- WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(
- WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(oneDay);
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(oneDay);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(
- WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(twoDays);
}
@Test
)
);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(
- WorkDuration.createFromValueAndUnit(3, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(
- WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(
- WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(3 * oneDay);
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay);
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay);
}
@Test
)
);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(
- WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(
- WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay);
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay);
}
@Test
)
);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, null)).isEqualTo(
- WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY));
+ assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, null)).isEqualTo(2 * oneDay);
}
@Test
/**
* @since 4.1
*/
- public static final Metric NEW_TECHNICAL_DEBT = new Metric.Builder(NEW_TECHNICAL_DEBT_KEY, "Technical Debt on new code", Metric.ValueType.FLOAT)
+ public static final Metric NEW_TECHNICAL_DEBT = new Metric.Builder(NEW_TECHNICAL_DEBT_KEY, "Technical Debt on new code", Metric.ValueType.WORK_DUR)
.setDescription("Technical Debt of new code")
.setDomain(DOMAIN_TECHNICAL_DEBT)
.setDirection(Metric.DIRECTION_WORST)