aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecorator.java46
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewTechnicalDebtDecoratorTest.java73
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDto.java19
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml9
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql1
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl1
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java4
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDtoTest.java3
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeMapperTest.java1
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java6
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete-result.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml7
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml (renamed from sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_created_date.xml)3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/shared.xml5
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update-result.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_comment-result.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_diff-result.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml4
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml10
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml10
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml10
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml10
-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/FieldDiffs.java20
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/db/migrate/467_add_issue_change_creation_date.rb32
29 files changed, 194 insertions, 110 deletions
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 eee453e9560..641d659c25e 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
@@ -47,7 +47,6 @@ import javax.annotation.Nullable;
import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newLinkedHashMap;
/**
* Decorator that computes the technical debt metric
@@ -114,37 +113,36 @@ public final class NewTechnicalDebtDecorator implements Decorator {
private double calculateNewTechnicalDebtValueFromChangelog(WorkDayDuration currentTechnicalDebt, Issue issue, Date periodDate) {
double currentTechnicalDebtValue = technicalDebtConverter.toDays(currentTechnicalDebt);
- for (Map.Entry<Date, WorkDayDuration> history : technicalDebtHistory(issue).entrySet()) {
- if (isAfterOrEqual(history.getKey(), periodDate)) {
- WorkDayDuration pastTechnicalDebt = history.getValue();
- double pastTechnicalDebtValue = technicalDebtConverter.toDays(pastTechnicalDebt);
- return currentTechnicalDebtValue - pastTechnicalDebtValue;
+ 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));
+ }
+ 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 0 when no changelog
return 0d;
}
- private Map<Date, WorkDayDuration> technicalDebtHistory(Issue issue) {
- Map<Date, WorkDayDuration> technicalDebtHistory = newLinkedHashMap();
+ private List<FieldDiffs> technicalDebtHistory(Issue issue) {
List<FieldDiffs> technicalDebtChangelog = changesOnField(((DefaultIssue) issue).changes());
-
if (!technicalDebtChangelog.isEmpty()) {
- // Changelog have to be sorted from oldest to newest to catch oldest value just before the period date. Null date should be the latest as this happen
- // when technical debt has changed since previous analysis.
- Ordering<FieldDiffs> ordering = Ordering.natural().nullsLast().onResultOf(new Function<FieldDiffs, Date>() {
+ // Changelog have to be sorted from newest to oldest.
+ // Null date should be the latest as this happen when technical debt has changed since previous analysis.
+ Ordering<FieldDiffs> ordering = Ordering.natural().reverse().nullsFirst().onResultOf(new Function<FieldDiffs, Date>() {
public Date apply(FieldDiffs diff) {
- return diff.createdAt();
+ return diff.creationDate();
}
});
- List<FieldDiffs> technicalDebtChangelogSorted = ordering.immutableSortedCopy(technicalDebtChangelog);
-
- technicalDebtHistory.put(issue.creationDate(), oldValue(technicalDebtChangelogSorted.iterator().next()));
- for (FieldDiffs fieldDiffs : technicalDebtChangelogSorted) {
- technicalDebtHistory.put(fieldDiffs.createdAt(), newValue(fieldDiffs));
- }
-
+ return ordering.immutableSortedCopy(technicalDebtChangelog);
}
- return technicalDebtHistory;
+ return Collections.emptyList();
}
private List<FieldDiffs> changesOnField(Collection<FieldDiffs> fieldDiffs) {
@@ -178,11 +176,11 @@ public final class NewTechnicalDebtDecorator implements Decorator {
}
private boolean isAfter(@Nullable Date currentDate, @Nullable Date pastDate) {
- return pastDate == null || (currentDate!= null && DateUtils.truncatedCompareTo(currentDate, pastDate, Calendar.SECOND) > 0);
+ return pastDate == null || (currentDate != null && DateUtils.truncatedCompareTo(currentDate, pastDate, Calendar.SECOND) > 0);
}
- private boolean isAfterOrEqual(@Nullable Date currentDate, @Nullable Date pastDate) {
- return currentDate == null || pastDate == null || (DateUtils.truncatedCompareTo(currentDate, pastDate, Calendar.SECOND) >= 0);
+ private boolean isLesserOrEqual(@Nullable Date currentDate, @Nullable Date pastDate) {
+ return (currentDate != null) && (pastDate == null || (DateUtils.truncatedCompareTo(currentDate, pastDate, Calendar.SECOND) <= 0));
}
private boolean shouldSaveNewMetrics(DecoratorContext context) {
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 f985fa7fbec..7880c222538 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
@@ -43,7 +43,6 @@ import org.sonar.batch.components.Period;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.core.technicaldebt.TechnicalDebtConverter;
-import java.util.Calendar;
import java.util.Date;
import static com.google.common.collect.Lists.newArrayList;
@@ -77,7 +76,6 @@ public class NewTechnicalDebtDecoratorTest {
Date nineDaysAgo;
Date fiveDaysAgo;
Date fourDaysAgo;
- Date sameSecond;
WorkDayDuration oneDaysDebt = WorkDayDuration.of(0, 0, 1);
WorkDayDuration twoDaysDebt = WorkDayDuration.of(0, 0, 2);
@@ -98,7 +96,6 @@ public class NewTechnicalDebtDecoratorTest {
nineDaysAgo = org.apache.commons.lang.time.DateUtils.addDays(rightNow, -9);
fiveDaysAgo = org.apache.commons.lang.time.DateUtils.addDays(rightNow, -5);
fourDaysAgo = org.apache.commons.lang.time.DateUtils.addDays(rightNow, -4);
- sameSecond = org.apache.commons.lang.time.DateUtils.truncate(rightNow, Calendar.SECOND);
when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, fiveDaysAgo, fiveDaysAgo), new Period(2, tenDaysAgo, tenDaysAgo)));
@@ -120,7 +117,7 @@ public class NewTechnicalDebtDecoratorTest {
Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(twoDaysDebt).setChanges(
newArrayList(
// changelog created at is null because it has just been created on the current analysis
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(null)
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(null)
)
);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -128,15 +125,15 @@ public class NewTechnicalDebtDecoratorTest {
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 1.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 1.0, 1.0)));
}
@Test
public void save_on_one_issue_with_changelog() {
Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(fiveDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(fiveDaysDebt)).setCreatedAt(null),
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(fourDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(fiveDaysDebt)).setCreationDate(null),
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(fourDaysAgo)
)
);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -144,16 +141,32 @@ public class NewTechnicalDebtDecoratorTest {
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0, 4.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0, 4.0)));
+ }
+
+ @Test
+ public void save_on_one_issue_with_changelog_only_in_the_past() {
+ Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(oneDaysDebt).setChanges(
+ newArrayList(
+ // Change before all periods
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(elevenDaysAgo)
+ )
+ );
+ when(issuable.issues()).thenReturn(newArrayList(issue));
+
+ decorator.decorate(resource, context);
+
+ // remember : period1 is 5daysAgo, period2 is 10daysAgo
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
}
@Test
public void save_on_one_issue_with_changelog_having_null_value() {
Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(fiveDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(fiveDaysDebt)).setCreatedAt(null),
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), null).setCreatedAt(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreatedAt(nineDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(fiveDaysDebt)).setCreationDate(null),
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), null).setCreationDate(fourDaysAgo),
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(nineDaysAgo)
)
);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -161,7 +174,7 @@ public class NewTechnicalDebtDecoratorTest {
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, 4.0, 5.0)));
}
@Test
@@ -170,9 +183,9 @@ public class NewTechnicalDebtDecoratorTest {
Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(fiveDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(fiveDaysDebt)).setCreatedAt(null),
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), null).setCreatedAt(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreatedAt(nineDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(fiveDaysDebt)).setCreationDate(null),
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), null).setCreationDate(fourDaysAgo),
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(nineDaysAgo)
)
);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -188,8 +201,8 @@ public class NewTechnicalDebtDecoratorTest {
Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(fiveDaysDebt).setChanges(
newArrayList(
new FieldDiffs()
- .setDiff("actionPlan", "1.0", "1.1").setCreatedAt(fourDaysAgo)
- .setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(fourDaysAgo)
+ .setDiff("actionPlan", "1.0", "1.1").setCreationDate(fourDaysAgo)
+ .setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(fourDaysAgo)
)
);
when(issuable.issues()).thenReturn(newArrayList(issue));
@@ -197,22 +210,22 @@ public class NewTechnicalDebtDecoratorTest {
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0, 4.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0, 4.0)));
}
@Test
public void save_on_issues_with_changelog() {
Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(fiveDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(fiveDaysDebt)).setCreatedAt(rightNow),
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreatedAt(nineDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(fiveDaysDebt)).setCreationDate(rightNow),
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(fourDaysAgo),
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(nineDaysAgo)
)
);
Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setTechnicalDebt(twoDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(rightNow),
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreatedAt(nineDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(rightNow),
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(nineDaysAgo)
)
);
when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
@@ -220,7 +233,7 @@ public class NewTechnicalDebtDecoratorTest {
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0, 7.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0, 7.0)));
}
@Test
@@ -279,15 +292,15 @@ public class NewTechnicalDebtDecoratorTest {
// issue1 and issue2 have changelog
Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setTechnicalDebt(fiveDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(fiveDaysDebt)).setCreatedAt(rightNow),
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreatedAt(nineDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(twoDaysDebt), fromWorkDayDuration(fiveDaysDebt)).setCreationDate(rightNow),
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(fourDaysAgo),
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(nineDaysAgo)
)
);
Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setTechnicalDebt(twoDaysDebt).setChanges(
newArrayList(
- new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreatedAt(rightNow),
- new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreatedAt(nineDaysAgo)
+ new FieldDiffs().setDiff("technicalDebt", fromWorkDayDuration(oneDaysDebt), fromWorkDayDuration(twoDaysDebt)).setCreationDate(rightNow),
+ new FieldDiffs().setDiff("technicalDebt", null, fromWorkDayDuration(oneDaysDebt)).setCreationDate(nineDaysAgo)
)
);
@@ -299,7 +312,7 @@ public class NewTechnicalDebtDecoratorTest {
decorator.decorate(resource, context);
// remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 3.0, 14.0)));
+ verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0, 14.0)));
}
@Test
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 6ed33ddc704..9cbd6c92045 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
@@ -204,7 +204,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent {
WorkDayDuration oldValue = issue.technicalDebt();
if (!Objects.equal(value, oldValue)) {
issue.setTechnicalDebt(value);
- issue.setFieldChange(context, TECHNICAL_DEBT, oldValue != null ? oldValue.toLong() : oldValue, value != null ? value.toLong() : null);
+ issue.setFieldChange(context, TECHNICAL_DEBT, oldValue != null ? oldValue.toLong() : null, value != null ? value.toLong() : null);
issue.setUpdateDate(context.date());
issue.setChanged(true);
return true;
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDto.java
index 646fb02b330..d57efd142fc 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDto.java
@@ -44,9 +44,14 @@ public final class IssueChangeDto implements Serializable {
private String userLogin;
private String changeType;
private String changeData;
+
+ // technical dates
private Date createdAt;
private Date updatedAt;
+ // functional date
+ private Date issueChangeCreationDate;
+
public Long getId() {
return id;
}
@@ -120,6 +125,15 @@ public final class IssueChangeDto implements Serializable {
return this;
}
+ public Date getIssueChangeCreationDate() {
+ return issueChangeCreationDate;
+ }
+
+ public IssueChangeDto setIssueChangeCreationDate(Date issueChangeCreationDate) {
+ this.issueChangeCreationDate = issueChangeCreationDate;
+ return this;
+ }
+
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
@@ -131,6 +145,7 @@ public final class IssueChangeDto implements Serializable {
dto.setChangeType(IssueChangeDto.TYPE_COMMENT);
dto.setChangeData(comment.markdownText());
dto.setUserLogin(comment.userLogin());
+ dto.setIssueChangeCreationDate(comment.createdAt());
return dto;
}
@@ -139,6 +154,7 @@ public final class IssueChangeDto implements Serializable {
dto.setChangeType(IssueChangeDto.TYPE_FIELD_CHANGE);
dto.setChangeData(diffs.toString());
dto.setUserLogin(diffs.userLogin());
+ dto.setIssueChangeCreationDate(diffs.creationDate());
return dto;
}
@@ -167,8 +183,7 @@ public final class IssueChangeDto implements Serializable {
public FieldDiffs toFieldDiffs() {
return FieldDiffs.parse(changeData)
.setUserLogin(userLogin)
- .setCreatedAt(createdAt)
- .setUpdatedAt(updatedAt)
+ .setCreationDate(issueChangeCreationDate)
.setIssueKey(issueKey);
}
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml
index ce9cb26ce66..c17d5f04f4b 100644
--- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml
@@ -12,12 +12,13 @@
c.change_type as changeType,
c.change_data as changeData,
c.created_at as createdAt,
- c.updated_at as updatedAt
+ c.updated_at as updatedAt,
+ c.issue_change_creation_date as issueChangeCreationDate
</sql>
<insert id="insert" parameterType="IssueChange" useGeneratedKeys="false" keyProperty="id">
- INSERT INTO issue_changes (kee, issue_key, user_login, change_type, change_data, created_at, updated_at)
- VALUES (#{kee}, #{issueKey}, #{userLogin}, #{changeType}, #{changeData}, #{createdAt}, #{updatedAt})
+ INSERT INTO issue_changes (kee, issue_key, user_login, change_type, change_data, created_at, updated_at, issue_change_creation_date)
+ VALUES (#{kee}, #{issueKey}, #{userLogin}, #{changeType}, #{changeData}, #{createdAt}, #{updatedAt}, #{issueChangeCreationDate})
</insert>
<delete id="delete" parameterType="string">
@@ -49,7 +50,7 @@
and c.change_type=#{changeType}
and i.status &lt;&gt; 'CLOSED'
</where>
- order by c.created_at asc
+ order by c.issue_change_creation_date asc
</select>
<select id="selectByKeyAndType" parameterType="map" resultType="IssueChange">
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
index e0ce7afbee1..9736e8a4bfd 100644
--- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
+++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
@@ -190,6 +190,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('463');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('464');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('465');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('466');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('467');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('480');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('481');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('482');
diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
index 1ef71efa658..cef8abb9bf6 100644
--- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
+++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl
@@ -499,6 +499,7 @@ CREATE TABLE "ISSUE_CHANGES" (
"CHANGE_DATA" VARCHAR(16777215),
"CREATED_AT" TIMESTAMP,
"UPDATED_AT" TIMESTAMP,
+ "ISSUE_CHANGE_CREATION_DATE" TIMESTAMP,
);
CREATE TABLE "ISSUE_FILTERS" (
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java
index 7ab6b396071..31ed53f11bf 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java
@@ -137,8 +137,8 @@ public class IssueChangeDaoTest extends AbstractDaoTestCase {
}
@Test
- public void select_issue_changelog_by_module_should_be_sorted_by_created_date() {
- setupData("select_issue_changelog_by_module_are_sorted_by_created_date");
+ public void select_issue_changelog_by_module_should_be_sorted_by_creation_date() {
+ setupData("select_issue_changelog_by_module_are_sorted_by_creation_date");
DefaultResultHandler handler = new DefaultResultHandler();
dao.selectChangelogOnNonClosedIssuesByModuleAndType(399, handler);
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDtoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDtoTest.java
index 036db2a7cfe..5b9ba0c15cb 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDtoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDtoTest.java
@@ -22,6 +22,7 @@ package org.sonar.core.issue.db;
import org.junit.Test;
import org.sonar.api.issue.internal.DefaultIssueComment;
import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.utils.DateUtils;
import static org.fest.assertions.Assertions.assertThat;
@@ -45,6 +46,7 @@ public class IssueChangeDtoTest {
FieldDiffs diffs = new FieldDiffs();
diffs.setDiff("severity", "INFO", "BLOCKER");
diffs.setUserLogin("emmerik");
+ diffs.setCreationDate(DateUtils.parseDate("2014-01-03"));
IssueChangeDto dto = IssueChangeDto.of("ABCDE", diffs);
@@ -52,6 +54,7 @@ public class IssueChangeDtoTest {
assertThat(dto.getChangeType()).isEqualTo("diff");
assertThat(dto.getCreatedAt()).isNotNull();
assertThat(dto.getUpdatedAt()).isNotNull();
+ assertThat(dto.getIssueChangeCreationDate()).isEqualTo(DateUtils.parseDate("2014-01-03"));
assertThat(dto.getIssueKey()).isEqualTo("ABCDE");
assertThat(dto.getUserLogin()).isEqualTo("emmerik");
}
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeMapperTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeMapperTest.java
index 5a38ae37236..609fe26719f 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeMapperTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeMapperTest.java
@@ -55,6 +55,7 @@ public class IssueChangeMapperTest extends AbstractDaoTestCase {
Date d = DateUtils.parseDate("2013-05-18");
dto.setCreatedAt(d);
dto.setUpdatedAt(d);
+ dto.setIssueChangeCreationDate(d);
mapper.insert(dto);
session.commit();
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 d79500de476..1c6281c837a 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
@@ -67,7 +67,7 @@ public class IssueStorageTest extends AbstractDaoTestCase {
saver.save(issue);
- checkTables("should_insert_new_issues", new String[]{"id", "created_at", "updated_at"}, "issues", "issue_changes");
+ checkTables("should_insert_new_issues", new String[]{"id", "created_at", "updated_at", "issue_change_creation_date"}, "issues", "issue_changes");
}
@Test
@@ -109,7 +109,7 @@ public class IssueStorageTest extends AbstractDaoTestCase {
saver.save(issue);
- checkTables("should_update_issues", new String[]{"id", "created_at", "updated_at"}, "issues", "issue_changes");
+ checkTables("should_update_issues", new String[]{"id", "created_at", "updated_at", "issue_change_creation_date"}, "issues", "issue_changes");
}
@Test
@@ -144,7 +144,7 @@ public class IssueStorageTest extends AbstractDaoTestCase {
saver.save(issue);
- checkTables("should_resolve_conflicts_on_updates", new String[]{"id", "created_at", "updated_at"}, "issues");
+ checkTables("should_resolve_conflicts_on_updates", new String[]{"id", "created_at", "updated_at", "issue_change_creation_date"}, "issues");
}
static class FakeSaver extends IssueStorage {
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete-result.xml
index 38915608de0..43980b2e35e 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete-result.xml
@@ -9,6 +9,7 @@
change_data="old comment"
created_at="2013-01-01"
updated_at="2013-01-01"
+ issue_change_creation_date="[null]"
/>
<issue_changes
@@ -20,6 +21,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-02-02"
updated_at="2013-02-02"
+ issue_change_creation_date="2013-02-02"
/>
<!--
@@ -34,6 +36,7 @@
change_data="recent comment"
created_at="2013-05-05"
updated_at="2013-05-05"
+ issue_change_creation_date="2013-05-05"
/>
-->
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete.xml
index 91b53b495ee..ffc07f03686 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/delete.xml
@@ -9,6 +9,7 @@
change_data="old comment"
created_at="2013-01-01"
updated_at="2013-01-01"
+ issue_change_creation_date="[null]"
/>
<issue_changes
@@ -20,6 +21,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-02-02"
updated_at="2013-02-02"
+ issue_change_creation_date="2013-02-02"
/>
<issue_changes
@@ -31,5 +33,6 @@
change_data="recent comment"
created_at="2013-05-05"
updated_at="2013-05-05"
+ issue_change_creation_date="2013-05-05"
/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml
index 85d5f5b37db..205133a30f7 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml
@@ -40,6 +40,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
<issue_changes
@@ -51,6 +52,7 @@
change_data="actionPlan=1.0|1.1"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
<issue_changes
@@ -62,6 +64,7 @@
change_data="recent comment"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="[null]"
/>
<!-- Open Issue on a file -->
@@ -99,6 +102,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
<!-- Closed Issue on a file -->
@@ -136,6 +140,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
<!-- Open Issue on a sub module -->
@@ -173,6 +178,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
<!-- Open Issue on a root module -->
@@ -210,6 +216,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_created_date.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml
index 11ad40bcd2f..330555cd7fd 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_created_date.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml
@@ -37,6 +37,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-18"
updated_at="2013-04-18"
+ issue_change_creation_date="2013-04-18"
/>
<issue_changes
@@ -48,6 +49,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-04-16"
updated_at="2013-04-16"
+ issue_change_creation_date="2013-04-16"
/>
<issue_changes
@@ -59,6 +61,7 @@
change_data="actionPlan=1.0|1.1"
created_at="2013-04-17"
updated_at="2013-04-17"
+ issue_change_creation_date="2013-04-17"
/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/shared.xml
index 6f960b43d3c..48f09145b63 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/shared.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/shared.xml
@@ -9,6 +9,7 @@
change_data="old comment"
created_at="2013-01-01"
updated_at="2013-01-01"
+ issue_change_creation_date="[null]"
/>
<issue_changes
@@ -20,6 +21,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-02-02"
updated_at="2013-02-02"
+ issue_change_creation_date="2013-02-02"
/>
<issue_changes
@@ -31,6 +33,7 @@
change_data="recent comment"
created_at="2013-05-05"
updated_at="2013-05-05"
+ issue_change_creation_date="[null]"
/>
<issue_changes
@@ -42,6 +45,7 @@
change_data="actionPlan=1.0|1.1"
created_at="2013-02-02"
updated_at="2013-02-02"
+ issue_change_creation_date="2013-02-02"
/>
<issue_changes
@@ -53,6 +57,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-02-01"
updated_at="2013-02-01"
+ issue_change_creation_date="2013-02-01"
/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update-result.xml
index 02577e213df..31a5056c859 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update-result.xml
@@ -9,6 +9,7 @@
change_data="old comment"
created_at="2013-01-01"
updated_at="2013-01-01"
+ issue_change_creation_date="[null]"
/>
<issue_changes
@@ -20,6 +21,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-02-02"
updated_at="2013-02-02"
+ issue_change_creation_date="2013-02-02"
/>
<issue_changes
@@ -31,5 +33,6 @@
change_data="new comment"
created_at="2013-05-05"
updated_at="2013-06-30"
+ issue_change_creation_date="[null]"
/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update.xml
index f7dfdc84832..94e2ec53877 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/update.xml
@@ -9,6 +9,7 @@
change_data="old comment"
created_at="2013-01-01"
updated_at="2013-01-01"
+ issue_change_creation_date="[null]"
/>
<issue_changes
@@ -20,6 +21,7 @@
change_data="severity=MAJOR|BLOCKER"
created_at="2013-02-02"
updated_at="2013-02-02"
+ issue_change_creation_date="2013-02-02"
/>
<issue_changes
@@ -31,5 +33,6 @@
change_data="old value"
created_at="2013-05-05"
updated_at="2013-05-05"
+ issue_change_creation_date="[null]"
/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_comment-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_comment-result.xml
index c1f10296b62..67122e49373 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_comment-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_comment-result.xml
@@ -8,5 +8,6 @@
change_data="the comment"
created_at="2013-05-18"
updated_at="2013-05-18"
+ issue_change_creation_date="[null]"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_diff-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_diff-result.xml
index 4d7045179e9..164a9d22dd4 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_diff-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeMapperTest/insert_diff-result.xml
@@ -8,5 +8,6 @@
change_data="severity=INFO|BLOCKER"
created_at="2013-05-18"
updated_at="2013-05-18"
+ issue_change_creation_date="2013-05-18"
/>
-</dataset> \ No newline at end of file
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml
index 7d211f38c01..59d288be419 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_insert_new_issues-result.xml
@@ -20,6 +20,7 @@
issue_close_date="2013-05-18"
/>
- <issue_changes id="1" kee="FGHIJ" issue_key="ABCDE" change_type="comment" user_login="emmerik" change_data="the comment" created_at="[null]" updated_at="[null]" />
+ <issue_changes id="1" kee="FGHIJ" issue_key="ABCDE" change_type="comment" user_login="emmerik" change_data="the comment"
+ created_at="[null]" updated_at="[null]" issue_change_creation_date="[null]" />
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml
index d3b9baa9d07..82db8eecb31 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueStorageTest/should_update_issues-result.xml
@@ -26,7 +26,7 @@
/>
<issue_changes id="1" kee="FGHIJ" issue_key="ABCDE" change_type="comment" user_login="emmerik"
- change_data="the comment" created_at="[null]" updated_at="[null]"/>
+ change_data="the comment" created_at="[null]" updated_at="[null]" issue_change_creation_date="[null]"/>
<issue_changes id="2" kee="[null]" issue_key="ABCDE" change_type="diff" user_login="emmerik"
- change_data="severity=INFO|BLOCKER" created_at="[null]" updated_at="[null]"/>
+ change_data="severity=INFO|BLOCKER" created_at="[null]" updated_at="[null]" issue_change_creation_date="[null]"/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml
index 43ff5c4d598..9eb87fb10c9 100644
--- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml
@@ -20,7 +20,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="2" kee="ISSUE-2"
component_id="1"
@@ -30,7 +30,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
-->
<!-- old open issues -->
@@ -42,7 +42,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -->
<issues id="4" kee="ISSUE-4"
@@ -53,7 +53,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!--
<issues id="5" kee="ISSUE-5"
@@ -64,6 +64,6 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
-->
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml
index 2bb55c7d6c4..c725ed53d9c 100644
--- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml
@@ -14,7 +14,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="2" kee="ISSUE-2"
component_id="1"
@@ -24,7 +24,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- old open issues -->
@@ -36,7 +36,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -->
<issues id="4" kee="ISSUE-4"
@@ -47,7 +47,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="5" kee="ISSUE-5"
component_id="100"
@@ -57,6 +57,6 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml
index 65bd0a71c55..775d6c17fe6 100644
--- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml
@@ -15,7 +15,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="2" kee="ISSUE-2"
component_id="1"
@@ -25,7 +25,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
-->
<!-- old open issues -> do not purge -->
@@ -37,7 +37,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -> do not purge -->
<issues id="4" kee="ISSUE-4"
@@ -48,7 +48,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="5" kee="ISSUE-5"
component_id="100"
@@ -58,6 +58,6 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml
index 127261b47f3..083dd7af08f 100644
--- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml
@@ -14,7 +14,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="2" kee="ISSUE-2"
component_id="1"
@@ -24,7 +24,7 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- old open issues -> do not purge -->
@@ -36,7 +36,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -> do not purge -->
<issues id="4" kee="ISSUE-4"
@@ -47,7 +47,7 @@
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="5" kee="ISSUE-5"
component_id="100"
@@ -57,6 +57,6 @@
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
- <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
</dataset>
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 2c9263e2642..10155076963 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
@@ -38,11 +38,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import java.io.Serializable;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
@@ -398,6 +394,7 @@ public class DefaultIssue implements Issue {
if (currentChange == null) {
currentChange = new FieldDiffs();
currentChange.setUserLogin(context.login());
+ currentChange.setCreationDate(context.date());
}
currentChange.setDiff(field, oldValue, newValue);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java
index 6329f703443..d1c60789d94 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/FieldDiffs.java
@@ -41,7 +41,8 @@ public class FieldDiffs implements Serializable {
private String issueKey;
private String userLogin;
- private Date createdAt, updatedAt;
+ private Date creationDate;
+
private final Map<String, Diff> diffs = Maps.newLinkedHashMap();
public Map<String, Diff> diffs() {
@@ -62,21 +63,12 @@ public class FieldDiffs implements Serializable {
return this;
}
- public Date createdAt() {
- return createdAt;
- }
-
- public FieldDiffs setCreatedAt(Date d) {
- this.createdAt = d;
- return this;
- }
-
- public Date updatedAt() {
- return updatedAt;
+ public Date creationDate() {
+ return creationDate;
}
- public FieldDiffs setUpdatedAt(Date d) {
- this.updatedAt = d;
+ public FieldDiffs setCreationDate(Date creationDate) {
+ this.creationDate = creationDate;
return this;
}
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/467_add_issue_change_creation_date.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/467_add_issue_change_creation_date.rb
new file mode 100644
index 00000000000..ea6938e7ce6
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/467_add_issue_change_creation_date.rb
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+#
+# SonarQube 4.1
+# SONAR-4776
+#
+
+class AddIssueChangeCreationDate < ActiveRecord::Migration
+
+ def self.up
+ add_column 'issue_changes', 'issue_change_creation_date', :datetime, :null => true
+ end
+
+end