You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2020/12/28 07:43:47 UTC
[james-project] 15/16: JAMES-3465 Mailbox/changes updatedProperties
handling
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 27dedd5a72a9fcbe79402efa47ed6cc464afc2a3
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Dec 22 16:47:38 2020 +0700
JAMES-3465 Mailbox/changes updatedProperties handling
---
.../james/jmap/api/change/MailboxChange.java | 41 ++++-
.../james/jmap/api/change/MailboxChanges.java | 17 ++-
.../change/MailboxChangeRepositoryContract.java | 106 +++++++------
.../contract/MailboxChangesMethodContract.scala | 166 ++++++++++++++++++---
.../contract/MailboxSetMethodContract.scala | 5 +-
.../james/jmap/method/MailboxChangesMethod.scala | 7 +-
.../jmap/change/MailboxChangeListenerTest.scala | 18 +--
7 files changed, 271 insertions(+), 89 deletions(-)
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
index f8af13e..caa954e 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
@@ -64,7 +64,12 @@ public class MailboxChange {
@FunctionalInterface
public interface RequiredDate {
- Builder date(ZonedDateTime date);
+ RequiredIsCountChange date(ZonedDateTime date);
+ }
+
+ @FunctionalInterface
+ public interface RequiredIsCountChange {
+ Builder isCountChange(boolean isCountChange);
}
public static class Builder {
@@ -72,11 +77,12 @@ public class MailboxChange {
private final State state;
private final ZonedDateTime date;
private boolean delegated;
+ private boolean isCountChange;
private Optional<List<MailboxId>> created;
private Optional<List<MailboxId>> updated;
private Optional<List<MailboxId>> destroyed;
- private Builder(AccountId accountId, State state, ZonedDateTime date) {
+ private Builder(AccountId accountId, State state, ZonedDateTime date, boolean isCountChange) {
Preconditions.checkNotNull(accountId, "'accountId' cannot be null");
Preconditions.checkNotNull(state, "'state' cannot be null");
Preconditions.checkNotNull(date, "'date' cannot be null");
@@ -84,6 +90,7 @@ public class MailboxChange {
this.accountId = accountId;
this.state = state;
this.date = date;
+ this.isCountChange = isCountChange;
this.created = Optional.empty();
this.updated = Optional.empty();
this.destroyed = Optional.empty();
@@ -94,6 +101,11 @@ public class MailboxChange {
return this;
}
+ public Builder isCountChange(boolean isCountChange) {
+ this.isCountChange = isCountChange;
+ return this;
+ }
+
public Builder created(List<MailboxId> created) {
this.created = Optional.of(created);
return this;
@@ -110,12 +122,12 @@ public class MailboxChange {
}
public MailboxChange build() {
- return new MailboxChange(accountId, state, date, delegated, created.orElse(ImmutableList.of()), updated.orElse(ImmutableList.of()), destroyed.orElse(ImmutableList.of()));
+ return new MailboxChange(accountId, state, date, delegated, isCountChange, created.orElse(ImmutableList.of()), updated.orElse(ImmutableList.of()), destroyed.orElse(ImmutableList.of()));
}
}
public static RequiredAccountId builder() {
- return accountId -> state -> date -> new Builder(accountId, state, date);
+ return accountId -> state -> date -> isCountChange -> new Builder(accountId, state, date, isCountChange);
}
public static class Factory {
@@ -139,6 +151,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(mailboxAdded.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.created(ImmutableList.of(mailboxAdded.getMailboxId()))
.build());
}
@@ -149,6 +162,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(mailboxRenamed.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.updated(ImmutableList.of(mailboxRenamed.getMailboxId()))
.build();
@@ -157,6 +171,7 @@ public class MailboxChange {
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.updated(ImmutableList.of(mailboxRenamed.getMailboxId()))
.delegated()
.build());
@@ -171,6 +186,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(mailboxACLUpdated.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.updated(ImmutableList.of(mailboxACLUpdated.getMailboxId()))
.build();
@@ -179,6 +195,7 @@ public class MailboxChange {
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.updated(ImmutableList.of(mailboxACLUpdated.getMailboxId()))
.delegated()
.build());
@@ -193,6 +210,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(mailboxDeletion.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.destroyed(ImmutableList.of(mailboxDeletion.getMailboxId()))
.build();
@@ -206,6 +224,7 @@ public class MailboxChange {
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(false)
.destroyed(ImmutableList.of(mailboxDeletion.getMailboxId()))
.delegated()
.build());
@@ -220,6 +239,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(messageAdded.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(true)
.updated(ImmutableList.of(messageAdded.getMailboxId()))
.build();
@@ -228,6 +248,7 @@ public class MailboxChange {
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(true)
.updated(ImmutableList.of(messageAdded.getMailboxId()))
.delegated()
.build());
@@ -245,6 +266,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(messageFlagUpdated.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(true)
.updated(ImmutableList.of(messageFlagUpdated.getMailboxId()))
.build();
@@ -253,6 +275,7 @@ public class MailboxChange {
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(true)
.updated(ImmutableList.of(messageFlagUpdated.getMailboxId()))
.delegated()
.build());
@@ -267,6 +290,7 @@ public class MailboxChange {
.accountId(AccountId.fromUsername(expunged.getUsername()))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(true)
.updated(ImmutableList.of(expunged.getMailboxId()))
.build();
@@ -275,6 +299,7 @@ public class MailboxChange {
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
.date(now)
+ .isCountChange(true)
.updated(ImmutableList.of(expunged.getMailboxId()))
.delegated()
.build());
@@ -305,15 +330,17 @@ public class MailboxChange {
private final State state;
private final ZonedDateTime date;
private final boolean delegated;
+ private final boolean isCountChange;
private final List<MailboxId> created;
private final List<MailboxId> updated;
private final List<MailboxId> destroyed;
- private MailboxChange(AccountId accountId, State state, ZonedDateTime date, boolean delegated, List<MailboxId> created, List<MailboxId> updated, List<MailboxId> destroyed) {
+ private MailboxChange(AccountId accountId, State state, ZonedDateTime date, boolean delegated, boolean isCountChange, List<MailboxId> created, List<MailboxId> updated, List<MailboxId> destroyed) {
this.accountId = accountId;
this.state = state;
this.date = date;
this.delegated = delegated;
+ this.isCountChange = isCountChange;
this.created = created;
this.updated = updated;
this.destroyed = destroyed;
@@ -335,6 +362,10 @@ public class MailboxChange {
return delegated;
}
+ public boolean isCountChange() {
+ return isCountChange;
+ }
+
public List<MailboxId> getCreated() {
return created;
}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChanges.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChanges.java
index bbe718b..30493fb 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChanges.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChanges.java
@@ -77,6 +77,7 @@ public class MailboxChanges {
private boolean hasMoreChanges;
private boolean canAddMoreItem;
private Limit limit;
+ private boolean isCountChangeOnly;
private Set<MailboxId> created;
private Set<MailboxId> updated;
private Set<MailboxId> destroyed;
@@ -85,6 +86,7 @@ public class MailboxChanges {
this.limit = limit;
this.state = state;
this.hasMoreChanges = false;
+ this.isCountChangeOnly = false;
this.canAddMoreItem = true;
this.created = new HashSet<>();
this.updated = new HashSet<>();
@@ -121,6 +123,11 @@ public class MailboxChanges {
return this;
}
+ if (created.isEmpty() && updated.isEmpty() && destroyed.isEmpty()) {
+ isCountChangeOnly = change.isCountChange();
+ } else {
+ isCountChangeOnly = isCountChangeOnly && change.isCountChange();
+ }
state = change.getState();
created = createdTemp;
updated = updatedTemp;
@@ -130,19 +137,21 @@ public class MailboxChanges {
}
public MailboxChanges build() {
- return new MailboxChanges(state, hasMoreChanges, created, updated, destroyed);
+ return new MailboxChanges(state, hasMoreChanges, isCountChangeOnly, created, updated, destroyed);
}
}
private State newState;
private final boolean hasMoreChanges;
+ private final boolean isCountChangesOnly;
private final Set<MailboxId> created;
private final Set<MailboxId> updated;
private final Set<MailboxId> destroyed;
- private MailboxChanges(State newState, boolean hasMoreChanges, Set<MailboxId> created, Set<MailboxId> updated, Set<MailboxId> destroyed) {
+ private MailboxChanges(State newState, boolean hasMoreChanges, boolean isCountChangesOnly, Set<MailboxId> created, Set<MailboxId> updated, Set<MailboxId> destroyed) {
this.newState = newState;
this.hasMoreChanges = hasMoreChanges;
+ this.isCountChangesOnly = isCountChangesOnly;
this.created = created;
this.updated = updated;
this.destroyed = destroyed;
@@ -156,6 +165,10 @@ public class MailboxChanges {
return hasMoreChanges;
}
+ public boolean isCountChangesOnly() {
+ return isCountChangesOnly;
+ }
+
public Set<MailboxId> getCreated() {
return created;
}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
index 36a64b5..8a06e96 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
@@ -48,7 +48,7 @@ public interface MailboxChangeRepositoryContract {
MailboxChangeRepository repository = mailboxChangeRepository();
State state = stateFactory().generate();
- MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
assertThatCode(() -> repository.save(change).block())
.doesNotThrowAnyException();
@@ -67,9 +67,9 @@ public interface MailboxChangeRepositoryContract {
MailboxChangeRepository repository = mailboxChangeRepository();
State.Factory stateFactory = stateFactory();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
- MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(4))).build();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
@@ -83,12 +83,13 @@ public interface MailboxChangeRepositoryContract {
MailboxChangeRepository repository = mailboxChangeRepository();
State.Factory stateFactory = stateFactory();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
MailboxChange change3 = MailboxChange.builder()
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE)
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(4)))
.delegated()
.build();
@@ -113,9 +114,9 @@ public interface MailboxChangeRepositoryContract {
MailboxChangeRepository repository = mailboxChangeRepository();
State.Factory stateFactory = stateFactory();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
- MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(4))).build();
repository.save(change1).block();
repository.save(change2).block();
repository.save(change3).block();
@@ -129,12 +130,13 @@ public interface MailboxChangeRepositoryContract {
MailboxChangeRepository repository = mailboxChangeRepository();
State.Factory stateFactory = stateFactory();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
MailboxChange change3 = MailboxChange.builder()
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE)
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(4)))
.delegated()
.build();
@@ -152,8 +154,8 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).updated(ImmutableList.of(TestId.of(1))).build();
repository.save(oldState);
repository.save(change);
@@ -167,7 +169,7 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
repository.save(oldState);
assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getAllChanges())
@@ -180,7 +182,7 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
repository.save(oldState);
assertThat(repository.getSinceState(ACCOUNT_ID, referenceState, Optional.empty()).block().getNewState())
@@ -193,10 +195,10 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
- MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(4))).build();
repository.save(oldState);
repository.save(change1);
repository.save(change2);
@@ -212,10 +214,10 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
- MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(4))).build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
@@ -231,11 +233,11 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
State state2 = stateFactory.generate();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(state2).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(3))).build();
- MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(state2).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(3))).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(4))).build();
repository.save(oldState).block();
repository.save(change1).block();
repository.save(change2).block();
@@ -252,9 +254,9 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(7))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(7))).build();
repository.save(oldState).block();
repository.save(change1).block();
@@ -270,9 +272,9 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(4), TestId.of(5))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(4), TestId.of(5))).build();
repository.save(oldState);
repository.save(change1);
repository.save(change2);
@@ -287,8 +289,8 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
repository.save(oldState);
repository.save(change1);
@@ -302,9 +304,9 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
repository.save(oldState);
repository.save(change1);
repository.save(change2);
@@ -319,9 +321,9 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
repository.save(oldState);
repository.save(change1);
repository.save(change2);
@@ -336,9 +338,9 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
- MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).created(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).updated(ImmutableList.of(TestId.of(2), TestId.of(3))).build();
repository.save(oldState);
repository.save(change1);
repository.save(change2);
@@ -357,18 +359,21 @@ public interface MailboxChangeRepositoryContract {
.accountId(ACCOUNT_ID)
.state(referenceState)
.date(DATE.minusHours(3))
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(1), TestId.of(9), TestId.of(10)))
.build();
MailboxChange change1 = MailboxChange.builder()
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE.minusHours(2))
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5)))
.build();
MailboxChange change2 = MailboxChange.builder()
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE.minusHours(1))
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(6), TestId.of(7)))
.updated(ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(9)))
.destroyed(ImmutableList.of(TestId.of(4))).build();
@@ -376,6 +381,7 @@ public interface MailboxChangeRepositoryContract {
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE)
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(8)))
.updated(ImmutableList.of(TestId.of(6), TestId.of(7)))
.destroyed(ImmutableList.of(TestId.of(5), TestId.of(10))).build();
@@ -400,12 +406,13 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).updated(ImmutableList.of(TestId.of(1), TestId.of(2))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).updated(ImmutableList.of(TestId.of(1), TestId.of(2))).build();
MailboxChange change2 = MailboxChange.builder()
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE)
+ .isCountChange(false)
.created(ImmutableList.of(TestId.of(3)))
.updated(ImmutableList.of(TestId.of(1), TestId.of(2)))
.build();
@@ -427,11 +434,12 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange oldState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
MailboxChange change1 = MailboxChange.builder()
.accountId(ACCOUNT_ID)
.state(stateFactory.generate())
.date(DATE.minusHours(1))
+ .isCountChange(false)
.updated(ImmutableList.of(TestId.of(1)))
.delegated()
.build();
@@ -450,8 +458,8 @@ public interface MailboxChangeRepositoryContract {
State.Factory stateFactory = stateFactory();
State referenceState = stateFactory.generate();
- MailboxChange currentState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).created(ImmutableList.of(TestId.of(1))).build();
- MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).created(ImmutableList.of(TestId.of(2))).build();
+ MailboxChange currentState = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(1))).build();
+ MailboxChange change = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).created(ImmutableList.of(TestId.of(2))).build();
repository.save(currentState);
repository.save(change);
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
index 46fd74f..918f062 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
@@ -133,7 +133,6 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": ["$mailboxId1", "$mailboxId2", "$mailboxId3"],
| "updated": [],
| "destroyed": []
@@ -191,7 +190,6 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -255,7 +253,7 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -321,7 +319,7 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -389,7 +387,7 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -455,7 +453,7 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -526,7 +524,7 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -590,7 +588,6 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -661,7 +658,7 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -731,7 +728,7 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -802,7 +799,7 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
| "created": [],
| "updated": ["$mailboxId"],
| "destroyed": []
@@ -873,7 +870,6 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": [],
| "destroyed": []
@@ -937,7 +933,6 @@ trait MailboxChangesMethodContract {
| "accountId": "$ANDRE_ACCOUNT_ID",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": [],
| "destroyed": ["$mailboxId"]
@@ -998,7 +993,6 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": [],
| "destroyed": ["$mailboxId"]
@@ -1072,7 +1066,6 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": ["$mailboxId3"],
| "updated": ["$mailboxId1"],
| "destroyed": ["$mailboxId2"]
@@ -1145,7 +1138,6 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": ["$mailboxId2"],
| "updated": [],
| "destroyed": []
@@ -1220,7 +1212,6 @@ trait MailboxChangesMethodContract {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "oldState": "${oldState.getValue}",
| "hasMoreChanges": true,
- | "updatedProperties": [],
| "created": ["$mailboxId1", "$mailboxId2", "$mailboxId3", "$mailboxId4", "$mailboxId5"],
| "updated": [],
| "destroyed": []
@@ -1355,7 +1346,6 @@ trait MailboxChangesMethodContract {
| "oldState": "${oldState.getValue}",
| "newState": "${oldState.getValue}",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": [],
| "destroyed": []
@@ -1480,7 +1470,6 @@ trait MailboxChangesMethodContract {
| "oldState": "$newState",
| "newState": "$newState",
| "hasMoreChanges": false,
- | "updatedProperties": [],
| "created": [],
| "updated": [],
| "destroyed": []
@@ -1489,11 +1478,148 @@ trait MailboxChangesMethodContract {
|}""".stripMargin)
}
+ @Test
+ def mailboxChangesShouldReturnUpdatedPropertiesWhenOnlyCountChanges(server: GuiceJamesServer): Unit = {
+ val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+
+ provisionSystemMailboxes(server)
+
+ val path = MailboxPath.forUser(BOB, "mailbox1")
+ val mailboxId: String = mailboxProbe
+ .createMailbox(path)
+ .serialize
+
+ val oldState: State = storeReferenceState(server, BOB)
+
+ val message: Message = Message.Builder
+ .of
+ .setSubject("test")
+ .setBody("testmail", StandardCharsets.UTF_8)
+ .build
+ val messageId1: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+ val messageId2: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+ val messageId3: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+ JmapRequests.destroyEmail(messageId2)
+ JmapRequests.markEmailAsSeen(messageId3)
+
+ val request =
+ s"""{
+ | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [[
+ | "Mailbox/changes",
+ | {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "sinceState": "${oldState.getValue}"
+ | },
+ | "c1"]]
+ |}""".stripMargin
+
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
+
+ @Test
+ def mailboxChangesShouldNotReturnUpdatedPropertiesWhenMixedChanges(server: GuiceJamesServer): Unit = {
+ val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+
+ provisionSystemMailboxes(server)
+
+ val path = MailboxPath.forUser(BOB, "mailbox1")
+ val mailboxId1: String = mailboxProbe
+ .createMailbox(path)
+ .serialize
+
+ val oldState: State = storeReferenceState(server, BOB)
+
+ val path2 = MailboxPath.forUser(BOB, "mailbox2")
+ val mailboxId2: String = mailboxProbe
+ .createMailbox(path2)
+ .serialize
+
+ val message: Message = Message.Builder
+ .of
+ .setSubject("test")
+ .setBody("testmail", StandardCharsets.UTF_8)
+ .build
+ mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message))
+
+ val request =
+ s"""{
+ | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [[
+ | "Mailbox/changes",
+ | {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "sinceState": "${oldState.getValue}"
+ | },
+ | "c1"]]
+ |}""".stripMargin
+
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "created": ["$mailboxId2"],
+ | "updated": ["$mailboxId1"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
+
private def storeReferenceState(server: GuiceJamesServer, username: Username): State = {
val state: State = stateFactory.generate()
val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
- jmapGuiceProbe.saveMailboxChange(MailboxChange.builder.accountId(AccountId.fromUsername(username)).state(state).date(ZonedDateTime.now()).updated(List(TestId.of(0)).asJava).build)
+ jmapGuiceProbe.saveMailboxChange(MailboxChange.builder.accountId(AccountId.fromUsername(username)).state(state).date(ZonedDateTime.now()).isCountChange(false).updated(List(TestId.of(0)).asJava).build)
state
}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
index 3e034fd..4292b01 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
@@ -35,7 +35,6 @@ import org.apache.james.jmap.core.State.INSTANCE
import org.apache.james.jmap.draft.MessageIdProbe
import org.apache.james.jmap.http.UserCredential
import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, ANDRE, BOB, BOB_PASSWORD, CEDRIC, DAVID, DOMAIN, authScheme, baseRequestSpecBuilder}
-import org.apache.james.jmap.rfc8621.contract.MailboxGetMethodContract.ARGUMENTS
import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
import org.apache.james.mailbox.MessageManager.AppendCommand
import org.apache.james.mailbox.model.MailboxACL.{EntryKey, Right}
@@ -7674,7 +7673,7 @@ trait MailboxSetMethodContract {
s"""{
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": null,
| "created": [],
| "updated": [],
| "destroyed": []
@@ -7735,7 +7734,7 @@ trait MailboxSetMethodContract {
s"""{
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "hasMoreChanges": false,
- | "updatedProperties": [],
+ | "updatedProperties": null,
| "created": [],
| "updated": ["${mailboxId.serialize}"],
| "destroyed": []
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala
index ab0003c..c1f985b 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala
@@ -29,6 +29,7 @@ import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
import org.apache.james.jmap.core.{CapabilityIdentifier, Invocation, Properties, State}
import org.apache.james.jmap.json.{MailboxSerializer, ResponseSerializer}
import org.apache.james.jmap.mail.{HasMoreChanges, MailboxChangesRequest, MailboxChangesResponse}
+import org.apache.james.jmap.method.MailboxChangesMethod.updatedProperties
import org.apache.james.jmap.routes.SessionSupplier
import org.apache.james.mailbox.MailboxSession
import org.apache.james.metrics.api.MetricFactory
@@ -38,6 +39,10 @@ import reactor.core.scala.publisher.SMono
import scala.jdk.CollectionConverters._
import scala.jdk.OptionConverters._
+object MailboxChangesMethod {
+ val updatedProperties: Properties = Properties("totalEmails", "unreadEmails", "totalThreads", "unreadThreads")
+}
+
class MailboxChangesMethod @Inject()(mailboxSerializer: MailboxSerializer,
val metricFactory: MetricFactory,
val sessionSupplier: SessionSupplier,
@@ -59,7 +64,7 @@ class MailboxChangesMethod @Inject()(mailboxSerializer: MailboxSerializer,
oldState = request.sinceState,
newState = State.fromMailboxChanges(mailboxChanges),
hasMoreChanges = HasMoreChanges.fromMailboxChanges(mailboxChanges),
- updatedProperties = Some(Properties()),
+ updatedProperties = if (mailboxChanges.isCountChangesOnly) Some(updatedProperties) else None,
created = mailboxChanges.getCreated.asScala.toSet,
updated = mailboxChanges.getUpdated.asScala.toSet,
destroyed = mailboxChanges.getDestroyed.asScala.toSet))
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
index 7c0c39d..edced0c 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
@@ -74,7 +74,7 @@ class MailboxChangeListenerTest {
@Test
def createMailboxShouldStoreCreatedEvent(): Unit = {
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
val mailboxSession = MailboxSessionUtil.create(BOB)
val inboxId: MailboxId = mailboxManager.createMailbox(MailboxPath.inbox(BOB), mailboxSession).get
@@ -91,7 +91,7 @@ class MailboxChangeListenerTest {
val inboxId: MailboxId = mailboxManager.createMailbox(path, mailboxSession).get
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
mailboxManager.renameMailbox(path, newPath, mailboxSession)
@@ -119,7 +119,7 @@ class MailboxChangeListenerTest {
val inboxId: MailboxId = mailboxManager.createMailbox(path, mailboxSession).get
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
mailboxManager.applyRightsCommand(path, MailboxACL.command().forUser(ALICE).rights(MailboxACL.Right.Read).asAddition(), mailboxSession)
@@ -140,7 +140,7 @@ class MailboxChangeListenerTest {
messageManager.appendMessage(AppendCommand.builder().build("header: value\r\n\r\nbody"), mailboxSession)
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
messageManager.setFlags(new Flags(Flags.Flag.SEEN), FlagsUpdateMode.ADD, MessageRange.all(), mailboxSession)
@@ -159,7 +159,7 @@ class MailboxChangeListenerTest {
.build("header: value\r\n\r\nbody"), mailboxSession)
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
messageManager.setFlags(new Flags(Flags.Flag.SEEN), FlagsUpdateMode.REMOVE, MessageRange.all(), mailboxSession)
@@ -176,7 +176,7 @@ class MailboxChangeListenerTest {
messageManager.appendMessage(AppendCommand.builder().build("header: value\r\n\r\nbody"), mailboxSession)
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
messageManager.setFlags(new Flags(Flags.Flag.ANSWERED), FlagsUpdateMode.ADD, MessageRange.all(), mailboxSession)
@@ -195,7 +195,7 @@ class MailboxChangeListenerTest {
.build("header: value\r\n\r\nbody"), mailboxSession)
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
messageManager.setFlags(new Flags(Flags.Flag.DELETED), FlagsUpdateMode.REPLACE, MessageRange.all(), mailboxSession)
@@ -212,7 +212,7 @@ class MailboxChangeListenerTest {
val appendResult: AppendResult = messageManager.appendMessage(AppendCommand.builder().build("header: value\r\n\r\nbody"), mailboxSession)
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
messageManager.delete(List(appendResult.getId.getUid).asJava, mailboxSession)
assertThat(repository.getSinceState(ACCOUNT_ID, state, None.toJava).block().getUpdated)
@@ -226,7 +226,7 @@ class MailboxChangeListenerTest {
val inboxId: MailboxId = mailboxManager.createMailbox(path, mailboxSession).get
val state = stateFactory.generate()
- repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).created(List[MailboxId](TestId.of(0)).asJava).build).block()
+ repository.save(MailboxChange.builder().accountId(ACCOUNT_ID).state(state).date(ZonedDateTime.now).isCountChange(false).created(List[MailboxId](TestId.of(0)).asJava).build).block()
mailboxManager.deleteMailbox(inboxId, mailboxSession)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org