From: Simon Brandhof Date: Mon, 20 May 2013 21:37:48 +0000 (+0200) Subject: SONAR-4310 set updated_at only on changes X-Git-Tag: 3.6~330 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=0ce0039711aa15183348c3f1a1ea7dff434fd36c;p=sonarqube.git SONAR-4310 set updated_at only on changes --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java index 36b88fd29c4..035f0d05958 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java @@ -97,7 +97,7 @@ public class IssueHandlers implements BatchExtension { @Override public IssueHandler.Context setAuthorLogin(@Nullable String login) { - updater.setAuthorLogin(issue, login); + updater.setAuthorLogin(issue, login, changeContext); return this; } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java index 0738bd5ca1f..1a02b7fe800 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java @@ -42,16 +42,6 @@ import java.util.*; public class IssueTracking implements BatchExtension { - private static final Comparator LINE_PAIR_COMPARATOR = new Comparator() { - public int compare(LinePair o1, LinePair o2) { - int weightDiff = o2.weight - o1.weight; - if (weightDiff != 0) { - return weightDiff; - } else { - return Math.abs(o1.lineA - o1.lineB) - Math.abs(o2.lineA - o2.lineB); - } - } - }; private final LastSnapshots lastSnapshots; private final SonarIndex index; @@ -60,9 +50,6 @@ public class IssueTracking implements BatchExtension { this.index = index; } - /** - * @return untracked issues - */ public IssueTrackingResult track(Resource resource, Collection dbIssues, Collection newIssues) { IssueTrackingResult result = new IssueTrackingResult(); @@ -334,7 +321,7 @@ public class IssueTracking implements BatchExtension { return getClass().getSimpleName(); } - static class LinePair { + private static class LinePair { int lineA; int lineB; int weight; @@ -346,11 +333,22 @@ public class IssueTracking implements BatchExtension { } } - static class HashOccurrence { + private static class HashOccurrence { int lineA; int lineB; int countA; int countB; } + private static final Comparator LINE_PAIR_COMPARATOR = new Comparator() { + public int compare(LinePair o1, LinePair o2) { + int weightDiff = o2.weight - o1.weight; + if (weightDiff != 0) { + return weightDiff; + } else { + return Math.abs(o1.lineA - o1.lineB) - Math.abs(o2.lineA - o2.lineB); + } + } + }; + } 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 0bc6875731f..08ad1dd65e9 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 @@ -20,7 +20,6 @@ package org.sonar.plugins.core.issue; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Objects; import com.google.common.base.Strings; import com.google.common.collect.Lists; import org.sonar.api.batch.Decorator; @@ -39,6 +38,7 @@ import org.sonar.api.utils.KeyValueFormat; import org.sonar.batch.issue.IssueCache; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.IssueChangeContext; +import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueDto; import org.sonar.core.issue.workflow.IssueWorkflow; @@ -53,12 +53,14 @@ public class IssueTrackingDecorator implements Decorator { private final IssueFilters filters; private final IssueHandlers handlers; private final IssueWorkflow workflow; + private final IssueUpdater updater; private final IssueChangeContext changeContext; private final ResourcePerspectives perspectives; private final RuleFinder ruleFinder; public IssueTrackingDecorator(IssueCache issueCache, InitialOpenIssuesStack initialOpenIssues, IssueTracking tracking, IssueFilters filters, IssueHandlers handlers, IssueWorkflow workflow, + IssueUpdater updater, Project project, ResourcePerspectives perspectives, RuleFinder ruleFinder) { this.issueCache = issueCache; @@ -67,6 +69,7 @@ public class IssueTrackingDecorator implements Decorator { this.filters = filters; this.handlers = handlers; this.workflow = workflow; + this.updater = updater; this.changeContext = IssueChangeContext.createScan(project.getAnalysisDate()); this.perspectives = perspectives; this.ruleFinder = ruleFinder; @@ -122,12 +125,6 @@ public class IssueTrackingDecorator implements Decorator { IssueDto ref = result.matching(issue); issue.setKey(ref.getKee()); - if (ref.isManualSeverity()) { - issue.setManualSeverity(true); - issue.setSeverity(ref.getSeverity()); - } else if (!Objects.equal(ref.getSeverity(), issue.severity())) { - // TODO register diff - } issue.setResolution(ref.getResolution()); issue.setStatus(ref.getStatus()); issue.setNew(false); @@ -136,16 +133,25 @@ public class IssueTrackingDecorator implements Decorator { issue.setAuthorLogin(ref.getAuthorLogin()); issue.setAssignee(ref.getAssignee()); if (ref.getAttributes() != null) { - //FIXME do not override new attributes issue.setAttributes(KeyValueFormat.parse(ref.getAttributes())); } - issue.setTechnicalCreationDate(ref.getCreatedAt()); - issue.setTechnicalUpdateDate(ref.getUpdatedAt()); issue.setCreationDate(ref.getIssueCreationDate()); - // FIXME issue.setUpdateDate(project.getAnalysisDate()); + + // must be done before the change of severity + issue.setUpdateDate(ref.getIssueUpdateDate()); // should be null issue.setCloseDate(ref.getIssueCloseDate()); + + if (ref.isManualSeverity()) { + issue.setManualSeverity(true); + issue.setSeverity(ref.getSeverity()); + } else { + // Emulate change of severity in the current scan. + String severity = issue.severity(); + issue.setSeverity(ref.getSeverity()); + updater.setSeverity(issue, severity, changeContext); + } } } @@ -156,7 +162,7 @@ public class IssueTrackingDecorator implements Decorator { Rule rule = ruleFinder.findByKey(unmatched.ruleKey()); boolean manualIssue = !Strings.isNullOrEmpty(unmatched.reporter()); - boolean onExistingRule = rule != null && !Rule.STATUS_REMOVED.equals(rule.getStatus()); + boolean onExistingRule = (rule != null && !Rule.STATUS_REMOVED.equals(rule.getStatus())); unmatched.setAlive(manualIssue && onExistingRule); issues.add(unmatched); 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 dba4a9c6133..8df79fd5c3a 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 @@ -31,6 +31,7 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.batch.issue.IssueCache; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.IssueChangeContext; +import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueDto; import org.sonar.core.issue.workflow.IssueWorkflow; import org.sonar.core.persistence.AbstractDaoTestCase; @@ -50,6 +51,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase { IssueFilters filters = mock(IssueFilters.class); IssueHandlers handlers = mock(IssueHandlers.class); IssueWorkflow workflow = mock(IssueWorkflow.class); + IssueUpdater updater = mock(IssueUpdater.class); ResourcePerspectives perspectives = mock(ResourcePerspectives.class); Date loadedDate = new Date(); RuleFinder ruleFinder = mock(RuleFinder.class); @@ -61,7 +63,9 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase { issueCache, initialOpenIssues, tracking, - filters, handlers, workflow, + filters, handlers, + workflow, + updater, mock(Project.class), perspectives, ruleFinder); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java index a2f64c12efb..5f2ba2f22f8 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java @@ -35,7 +35,6 @@ import org.sonar.api.rule.Severity; import javax.annotation.CheckForNull; import javax.annotation.Nullable; - import java.io.Serializable; import java.util.Collections; import java.util.Date; @@ -57,8 +56,6 @@ public class DefaultIssue implements Issue { private String reporter; private String assignee; private String checksum; - private boolean isNew = true; - private boolean isAlive = true; private Map attributes = null; private String authorLogin = null; private FieldDiffs diffs = null; @@ -70,9 +67,17 @@ public class DefaultIssue implements Issue { private Date updateDate; private Date closeDate; - // technical dates - private Date technicalCreationDate; - private Date technicalUpdateDate; + // The following states are used only during scan. + + // true if the the issue did not exist in the previous scan. + private boolean isNew = true; + + // true if the the issue did exist in the previous scan but not in the current one. That means + // that this issue should be closed. + private boolean isAlive = true; + + // true if some fields have been changed since the previous scan + private boolean isChanged = false; public String key() { return key; @@ -222,33 +227,6 @@ public class DefaultIssue implements Issue { } - /** - * The date when issue was physically created - */ - public DefaultIssue setTechnicalCreationDate(@Nullable Date d) { - this.technicalCreationDate = d; - return this; - } - - @CheckForNull - public Date technicalCreationDate() { - return technicalCreationDate; - } - - /** - * The date when issue was physically updated for the last time - */ - - public DefaultIssue setTechnicalUpdateDate(@Nullable Date d) { - this.technicalUpdateDate = d; - return this; - } - - @CheckForNull - public Date technicalUpdateDate() { - return technicalUpdateDate; - } - @CheckForNull public String getChecksum() { return checksum; @@ -277,6 +255,15 @@ public class DefaultIssue implements Issue { return this; } + public boolean isChanged() { + return isChanged; + } + + public DefaultIssue setChanged(boolean b) { + isChanged = b; + return this; + } + @CheckForNull public String attribute(String key) { return attributes == null ? null : attributes.get(key); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java index 95d62e0d048..88847d97804 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java @@ -116,8 +116,6 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder { Date now = new Date(); Date date = Objects.firstNonNull(createdDate, now); - issue.setTechnicalCreationDate(now); - issue.setTechnicalUpdateDate(now); issue.setCreationDate(date); issue.setUpdateDate(date); issue.setComponentKey(componentKey); @@ -129,8 +127,6 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder { issue.setManualSeverity(false); issue.setReporter(reporter); issue.setAttributes(attributes); - issue.setNew(true); - issue.setAlive(true); issue.setResolution(null); issue.setStatus(Issue.STATUS_OPEN); return issue; 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 d01c8f5ffb1..0c9daf6538b 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 @@ -23,10 +23,8 @@ import com.google.common.base.Objects; import org.apache.commons.lang.StringUtils; import org.sonar.api.BatchComponent; import org.sonar.api.ServerComponent; -import org.sonar.api.issue.IssueComment; import javax.annotation.Nullable; - import java.util.Date; /** @@ -42,6 +40,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setFieldDiff(context, "severity", issue.severity(), severity); issue.setSeverity(severity); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; @@ -53,6 +52,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setSeverity(severity); issue.setManualSeverity(true); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; @@ -64,6 +64,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setFieldDiff(context, "assignee", issue.assignee(), sanitizedAssignee); issue.setAssignee(sanitizedAssignee); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; @@ -72,6 +73,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { public boolean setLine(DefaultIssue issue, @Nullable Integer line) { if (!Objects.equal(line, issue.line())) { issue.setLine(line); + issue.setChanged(true); return true; } return false; @@ -82,6 +84,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setFieldDiff(context, "resolution", issue.resolution(), resolution); issue.setResolution(resolution); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; @@ -92,32 +95,50 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setFieldDiff(context, "status", issue.status(), status); issue.setStatus(status); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; } - public void setAuthorLogin(DefaultIssue issue, @Nullable String authorLogin) { - issue.setAuthorLogin(authorLogin); + public void setAuthorLogin(DefaultIssue issue, @Nullable String authorLogin, IssueChangeContext context) { + if (!Objects.equal(authorLogin, issue.authorLogin())) { + issue.setFieldDiff(context, "author", issue.authorLogin(), authorLogin); + issue.setAuthorLogin(authorLogin); + issue.setUpdateDate(context.date()); + issue.setChanged(true); + } } public void setMessage(DefaultIssue issue, @Nullable String s, IssueChangeContext context) { - issue.setMessage(s); - issue.setUpdateDate(context.date()); + if (!Objects.equal(s, issue.message())) { + issue.setFieldDiff(context, "message", issue.message(), s); + issue.setMessage(s); + issue.setUpdateDate(context.date()); + issue.setChanged(true); + } } public void addComment(DefaultIssue issue, String text, IssueChangeContext context) { issue.addComment(DefaultIssueComment.create(issue.key(), context.login(), text)); issue.setUpdateDate(context.date()); + issue.setChanged(true); } - public void setCloseDate(DefaultIssue issue, @Nullable Date d) { - issue.setCloseDate(d); + public void setCloseDate(DefaultIssue issue, @Nullable Date d, IssueChangeContext context) { + if (!Objects.equal(d, issue.closeDate())) { + issue.setCloseDate(d); + issue.setUpdateDate(context.date()); + issue.setChanged(true); + } } public void setEffortToFix(DefaultIssue issue, @Nullable Double d, IssueChangeContext context) { - issue.setEffortToFix(d); - issue.setUpdateDate(context.date()); + if (!Objects.equal(d, issue.closeDate())) { + issue.setEffortToFix(d); + issue.setUpdateDate(context.date()); + issue.setChanged(true); + } } public boolean setAttribute(DefaultIssue issue, String key, @Nullable String value, IssueChangeContext context) { @@ -126,6 +147,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setFieldDiff(context, key, oldValue, value); issue.setAttribute(key, value); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; @@ -137,6 +159,7 @@ public class IssueUpdater implements BatchComponent, ServerComponent { issue.setFieldDiff(context, "actionPlanKey", issue.actionPlanKey(), sanitizedActionPlanKey); issue.setActionPlanKey(sanitizedActionPlanKey); issue.setUpdateDate(context.date()); + issue.setChanged(true); return true; } return false; 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 e7bf13f7e5a..de545172be5 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 @@ -310,7 +310,7 @@ public final class IssueDto { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } - public static IssueDto toDtoForInsert(DefaultIssue issue, Integer componentId, Integer ruleId) { + public static IssueDto toDtoForInsert(DefaultIssue issue, Integer componentId, Integer ruleId, Date now) { return new IssueDto() .setKee(issue.key()) .setLine(issue.line()) @@ -328,14 +328,15 @@ public final class IssueDto { .setActionPlanKey(issue.actionPlanKey()) .setAttributes(issue.attributes() != null ? KeyValueFormat.format(issue.attributes()) : "") .setAuthorLogin(issue.authorLogin()) - .setCreatedAt(issue.technicalCreationDate()) - .setUpdatedAt(issue.technicalUpdateDate()) .setIssueCreationDate(issue.creationDate()) .setIssueCloseDate(issue.closeDate()) - .setIssueUpdateDate(issue.updateDate()); + .setIssueUpdateDate(issue.updateDate()) + + .setCreatedAt(now) + .setUpdatedAt(now); } - public static IssueDto toDtoForUpdate(DefaultIssue issue) { + public static IssueDto toDtoForUpdate(DefaultIssue issue, Date now) { // Invariant fields, like key and rule, can't be updated return new IssueDto() .setKee(issue.key()) @@ -352,10 +353,10 @@ public final class IssueDto { .setActionPlanKey(issue.actionPlanKey()) .setAttributes(issue.attributes() != null ? KeyValueFormat.format(issue.attributes()) : "") .setAuthorLogin(issue.authorLogin()) - .setUpdatedAt(issue.technicalUpdateDate()) .setIssueCreationDate(issue.creationDate()) .setIssueCloseDate(issue.closeDate()) - .setIssueUpdateDate(issue.updateDate()); + .setIssueUpdateDate(issue.updateDate()) + .setUpdatedAt(now); } public DefaultIssue toDefaultIssue() { @@ -376,8 +377,6 @@ public final class IssueDto { issue.setActionPlanKey(actionPlanKey); issue.setAuthorLogin(authorLogin); issue.setNew(false); - issue.setTechnicalCreationDate(createdAt); - issue.setTechnicalUpdateDate(updatedAt); issue.setCreationDate(issueCreationDate); issue.setCloseDate(issueCloseDate); issue.setUpdateDate(issueUpdateDate); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java index 8064e7502c3..1b2af6e383e 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java @@ -30,6 +30,7 @@ import org.sonar.core.issue.DefaultIssueComment; import org.sonar.core.persistence.MyBatis; import java.util.Arrays; +import java.util.Date; import java.util.List; public abstract class IssueStorage { @@ -50,19 +51,18 @@ public abstract class IssueStorage { SqlSession session = mybatis.openBatchSession(); IssueMapper issueMapper = session.getMapper(IssueMapper.class); IssueChangeMapper issueChangeMapper = session.getMapper(IssueChangeMapper.class); + Date now = new Date(); try { List conflicts = Lists.newArrayList(); - for (DefaultIssue issue : issues) { if (issue.isNew()) { int componentId = componentId(issue); int ruleId = ruleId(issue); - IssueDto dto = IssueDto.toDtoForInsert(issue, componentId, ruleId); + IssueDto dto = IssueDto.toDtoForInsert(issue, componentId, ruleId, now); issueMapper.insert(dto); - } else /* TODO if hasChanges */ { - // TODO manage condition on update date - IssueDto dto = IssueDto.toDtoForUpdate(issue); + } else if (issue.isChanged()) { + IssueDto dto = IssueDto.toDtoForUpdate(issue, now); int count = issueMapper.update(dto); if (count < 1) { conflicts.add(issue); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/workflow/FunctionExecutor.java b/sonar-core/src/main/java/org/sonar/core/issue/workflow/FunctionExecutor.java index eaa3b7dc32a..c2d974e3def 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/workflow/FunctionExecutor.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/workflow/FunctionExecutor.java @@ -67,7 +67,7 @@ public class FunctionExecutor implements BatchComponent, ServerComponent { @Override public Function.Context setCloseDate(boolean b) { - updater.setCloseDate(issue, b ? changeContext.date() : null); + updater.setCloseDate(issue, b ? changeContext.date() : null, changeContext); return null; } } diff --git a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java index 5bdfdf1bee5..e56a212c99c 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java @@ -51,8 +51,6 @@ public class DefaultIssueBuilderTest { assertThat(issue.ruleKey().repository()).isEqualTo("squid"); assertThat(issue.ruleKey().rule()).isEqualTo("NullDereference"); assertThat(issue.severity()).isEqualTo(Severity.CRITICAL); - assertThat(issue.technicalCreationDate()).isNotNull(); - assertThat(issue.technicalUpdateDate()).isNotNull(); assertThat(issue.assignee()).isNull(); assertThat(issue.isNew()).isTrue(); assertThat(issue.resolution()).isNull(); 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 193c259d0d2..fd7f8f58b1e 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 @@ -47,18 +47,21 @@ public class IssueStorageTest extends AbstractDaoTestCase { comment.setKey("FGHIJ"); Date date = DateUtils.parseDate("2013-05-18"); - DefaultIssue issue = new DefaultIssue(); - issue.setKey("ABCDE"); - issue.setRuleKey(RuleKey.of("squid", "AvoidCycle")); - issue.setLine(5000); - issue.setNew(true); - issue.setReporter("emmerik"); - issue.setResolution("OPEN").setStatus("OPEN").setSeverity("BLOCKER"); - issue.setAttribute("foo", "bar"); - issue.addComment(comment); - issue.setCreationDate(date); - issue.setUpdateDate(date); - issue.setCloseDate(date); + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setNew(true) + + .setRuleKey(RuleKey.of("squid", "AvoidCycle")) + .setLine(5000) + .setReporter("emmerik") + .setResolution("OPEN") + .setStatus("OPEN") + .setSeverity("BLOCKER") + .setAttribute("foo", "bar") + .addComment(comment) + .setCreationDate(date) + .setUpdateDate(date) + .setCloseDate(date); saver.save(issue); @@ -76,22 +79,30 @@ public class IssueStorageTest extends AbstractDaoTestCase { comment.setKey("FGHIJ"); Date date = DateUtils.parseDate("2013-05-18"); - DefaultIssue issue = new DefaultIssue(); - issue.setKey("ABCDE"); - issue.setRuleKey(RuleKey.of("squid", "AvoidCycle")); - issue.setLine(5000); - issue.setNew(false); - issue.setChecksum("FFFFF"); - issue.setAuthorLogin("simon"); - issue.setAssignee("loic"); - issue.setFieldDiff(context, "severity", "INFO", "BLOCKER"); - issue.setReporter("emmerik"); - issue.setResolution("FIXED").setStatus("RESOLVED").setSeverity("BLOCKER"); - issue.setAttribute("foo", "bar"); - issue.addComment(comment); - issue.setCreationDate(date); - issue.setUpdateDate(date); - issue.setCloseDate(date); + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setNew(false) + .setChanged(true) + + // updated fields + .setLine(5000) + .setChecksum("FFFFF") + .setAuthorLogin("simon") + .setAssignee("loic") + .setFieldDiff(context, "severity", "INFO", "BLOCKER") + .setReporter("emmerik") + .setResolution("FIXED") + .setStatus("RESOLVED") + .setSeverity("BLOCKER") + .setAttribute("foo", "bar") + .addComment(comment) + .setCreationDate(date) + .setUpdateDate(date) + .setCloseDate(date) + + // unmodifiable fields + .setRuleKey(RuleKey.of("xxx", "unknown")) + .setComponentKey("not:a:component"); saver.save(issue); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb index ec614f6c39b..eba1a27714d 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/issue.rb @@ -26,7 +26,6 @@ class Issue :rule => issue.ruleKey.toString(), :status => issue.status } - hash[:actionPlan] = issue.actionPlanKey if issue.actionPlanKey hash[:resolution] = issue.resolution if issue.resolution hash[:severity] = issue.severity if issue.severity hash[:message] = issue.message if issue.message @@ -34,6 +33,7 @@ class Issue hash[:effortToFix] = issue.effortToFix.to_f if issue.effortToFix hash[:reporter] = issue.reporter if issue.reporter hash[:assignee] = issue.assignee if issue.assignee + hash[:actionPlan] = issue.actionPlanKey if issue.actionPlanKey hash[:creationDate] = Api::Utils.format_datetime(issue.creationDate) if issue.creationDate hash[:updateDate] = Api::Utils.format_datetime(issue.updateDate) if issue.updateDate hash[:closeDate] = Api::Utils.format_datetime(issue.closeDate) if issue.closeDate