public DefaultIssue setFieldChange(IssueChangeContext context, String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) { if (!Objects.equals(oldValue, newValue)) { if (currentChange == null) { currentChange = new FieldDiffs(); currentChange.setUserUuid(context.userUuid()); currentChange.setCreationDate(context.date()); } currentChange.setDiff(field, oldValue, newValue); } addChange(currentChange); return this; }
/** * Copy a diff from another issue */ private static Optional<FieldDiffs> copyFieldDiffOfIssueFromOtherBranch(String issueKey, FieldDiffs c) { FieldDiffs result = new FieldDiffs(); result.setIssueKey(issueKey); result.setUserUuid(c.userUuid()); result.setCreationDate(c.creationDate()); // Don't copy "file" changelogs as they refer to file uuids that might later be purged c.diffs().entrySet().stream().filter(e -> !e.getKey().equals(IssueFieldsSetter.FILE)) .forEach(e -> result.setDiff(e.getKey(), e.getValue().oldValue(), e.getValue().newValue())); if (result.diffs().isEmpty()) { return Optional.empty(); } return Optional.of(result); }
@CheckForNull private StatusAndResolutionDiffs parse(FieldDiffs fieldDiffs) { FieldDiffs.Diff status = fieldDiffs.get("status"); if (status == null) { return null; } FieldDiffs.Diff resolution = fieldDiffs.get("resolution"); if (resolution == null) { return new StatusAndResolutionDiffs(Issue.STATUS_CLOSED.equals(status.newValue()), null, null); } return new StatusAndResolutionDiffs(Issue.STATUS_CLOSED.equals(status.newValue()), (String) resolution.oldValue(), (String) resolution.newValue()); }
public FieldDiffs toFieldDiffs() { return FieldDiffs.parse(changeData) .setUserUuid(userUuid) .setCreationDate(new Date(getIssueChangeCreationDate())) .setIssueKey(issueKey); } }
private static void addStatusChange(DefaultIssue issue, Date date, String previousStatus, String newStatus) { issue.addChange(new FieldDiffs().setCreationDate(date).setDiff("status", previousStatus, newStatus)); }
public static FieldDiffs parse(@Nullable String s) { FieldDiffs diffs = new FieldDiffs(); if (isNullOrEmpty(s)) { return diffs; } Iterable<String> fields = FIELDS_SPLITTER.split(s); for (String field : fields) { String[] keyValues = field.split("=", 2); if (keyValues.length == 2) { String values = keyValues[1]; int split = values.indexOf('|'); if (split > -1) { diffs.setDiff(keyValues[0], emptyToNull(values.substring(0, split)), emptyToNull(values.substring(split + 1))); } else { diffs.setDiff(keyValues[0], null, emptyToNull(values)); } } else { diffs.setDiff(keyValues[0], null, null); } } return diffs; }
private Function<FieldDiffs, Changelog> toWsChangelog(ChangeLogResults results) { return change -> { String userUUuid = change.userUuid(); Changelog.Builder changelogBuilder = Changelog.newBuilder(); changelogBuilder.setCreationDate(formatDateTime(change.creationDate())); UserDto user = userUUuid == null ? null : results.users.get(userUUuid); if (user != null) { changelogBuilder.setUser(user.getLogin()); changelogBuilder.setUserName(user.getName()); ofNullable(emptyToNull(user.getEmail())).ifPresent(email -> changelogBuilder.setAvatar(avatarFactory.create(user))); } change.diffs().entrySet().stream() .map(toWsDiff(results)) .forEach(changelogBuilder::addDiffs); return changelogBuilder.build(); }; }
@Test public void diffs_should_be_empty_by_default() { assertThat(diffs.diffs()).isEmpty(); }
.setManualSeverity(false) .setLocations(issueLocations) .addChange(new FieldDiffs().setDiff("foo", "bar", "donut")) .addChange(new FieldDiffs().setDiff("file", "A", "B")); assertThat(raw.isChanged()).isFalse(); assertThat(raw.changes()).hasSize(2); assertThat(raw.changes().get(0).diffs()) .containsOnly(entry("foo", new FieldDiffs.Diff("bar", "donut"))); assertThat(raw.changes().get(1).diffs()) .containsOnly(entry("file", new FieldDiffs.Diff("A", "B")));
@Test public void to_field_diffs_with_issue_creation_date() { IssueChangeDto changeDto = new IssueChangeDto() .setKey("EFGH") .setUserUuid("user_uuid") .setChangeData("Some text") .setIssueKey("ABCDE") .setIssueChangeCreationDate(System2.INSTANCE.now()); FieldDiffs diffs = changeDto.toFieldDiffs(); assertThat(diffs.userUuid()).isEqualTo("user_uuid"); assertThat(diffs.issueKey()).isEqualTo("ABCDE"); assertThat(diffs.creationDate()).isNotNull(); }
private static String randomDiffWith(String... fieldsAndValues) { Random random = new Random(); List<Diff> diffs = new ArrayList<>(); for (int i = 0; i < fieldsAndValues.length; i++) { int oldOrNew = random.nextInt(3); String value = fieldsAndValues[i + 1]; diffs.add(new Diff(fieldsAndValues[i], oldOrNew <= 2 ? value : null, oldOrNew >= 2 ? value : null)); i++; } IntStream.range(0, random.nextInt(5)) .forEach(i -> diffs.add(new Diff(randomAlphabetic(10), random.nextBoolean() ? null : randomAlphabetic(11), random.nextBoolean() ? null : randomAlphabetic(12)))); Collections.shuffle(diffs); FieldDiffs res = new FieldDiffs(); diffs.forEach(diff -> res.setDiff(diff.field, diff.oldValue, diff.newValue)); return res.toEncodedString(); }
public static IssueChangeDto of(String issueKey, FieldDiffs diffs) { IssueChangeDto dto = newDto(issueKey); dto.setChangeType(IssueChangeDto.TYPE_FIELD_CHANGE); dto.setChangeData(diffs.toEncodedString()); dto.setUserUuid(diffs.userUuid()); Date createdAt = requireNonNull(diffs.creationDate(), "Diffs created at must not be null"); dto.setIssueChangeCreationDate(createdAt.getTime()); return dto; }
public FieldDiffs toFieldDiffs() { return FieldDiffs.parse(changeData) .setUserLogin(userLogin) // issueChangeCreationDate can be null as it has been introduced after createdAt .setCreationDate(issueChangeCreationDate != null ? new Date(issueChangeCreationDate) : new Date(createdAt)) .setIssueKey(issueKey); } }
@Override public boolean matches(Issue issue) { DefaultIssue defaultIssue = (DefaultIssue) issue; Optional<String> lastPreviousStatus = defaultIssue.changes().stream() // exclude current change (if any) .filter(change -> change != defaultIssue.currentChange()) .filter(change -> change.creationDate() != null) .sorted(Comparator.comparing(FieldDiffs::creationDate).reversed()) .map(change -> change.get("status")) .filter(Objects::nonNull) .findFirst() .map(t -> (String) t.oldValue()); return lastPreviousStatus.filter(this.expectedPreviousStatus::equals).isPresent(); } }
@Test public void setIssueMoved_changes_componentUuid_adds_a_change() { String oldComponentUuid = "a"; String newComponentUuid = "b"; issue.setComponentUuid(oldComponentUuid); underTest.setIssueMoved(issue, newComponentUuid, context); assertThat(issue.changes()).hasSize(1); FieldDiffs fieldDiffs = issue.changes().get(0); assertThat(fieldDiffs.creationDate()).isEqualTo(context.date()); assertThat(fieldDiffs.diffs()).hasSize(1); Map.Entry<String, FieldDiffs.Diff> entry = fieldDiffs.diffs().entrySet().iterator().next(); assertThat(entry.getKey()).isEqualTo("file"); assertThat(entry.getValue().oldValue()).isEqualTo(oldComponentUuid); assertThat(entry.getValue().newValue()).isEqualTo(newComponentUuid); assertThat(issue.componentUuid()).isEqualTo(newComponentUuid); assertThat(issue.isChanged()).isTrue(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(context.date(), Calendar.SECOND)); } }
@Test public void lazy_load_changes() { UserDto user1 = db.users().insertUser(); IssueDto issue1 = db.issues() .insertIssue(IssueTesting.newIssue(rule, branch1Dto, fileOnBranch1Dto).setKee("issue1").setStatus(Issue.STATUS_REOPENED).setLine(1).setChecksum("checksum")); db.issues().insertComment(issue1, user1, "A comment 1"); db.issues().insertFieldDiffs(issue1, FieldDiffs.parse("severity=BLOCKER|INFO,assignee=toto|titi").setCreationDate(new Date())); UserDto user2 = db.users().insertUser(); IssueDto issue2 = db.issues() .insertIssue(IssueTesting.newIssue(rule, branch2Dto, fileOnBranch2Dto).setKee("issue2").setStatus(Issue.STATUS_CONFIRMED).setLine(1).setChecksum("checksum")); db.issues().insertComment(issue2, user2, "A comment 2"); db.issues().insertFieldDiffs(issue2, FieldDiffs.parse("severity=BLOCKER|MINOR,assignee=foo|bar").setCreationDate(new Date())); DefaultIssue newIssue = createIssue("newIssue", rule.getKey(), Issue.STATUS_OPEN, null, new Date()); copier.tryMerge(FILE_1, Collections.singleton(newIssue)); ArgumentCaptor<DefaultIssue> issueToMerge = ArgumentCaptor.forClass(DefaultIssue.class); verify(issueLifecycle).mergeConfirmedOrResolvedFromShortLivingBranch(eq(newIssue), issueToMerge.capture(), eq("myBranch2")); assertThat(issueToMerge.getValue().key()).isEqualTo("issue2"); assertThat(issueToMerge.getValue().defaultIssueComments()).isNotEmpty(); assertThat(issueToMerge.getValue().changes()).isNotEmpty(); }