You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2020/11/30 12:12:27 UTC
[james-project] 01/07: JAMES-3459 Mailbox/changes
MemoryMailboxChangeRepository implementation
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 6c4d39222915334f7c48861c62ad92380d5daec7
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Wed Nov 25 17:54:51 2020 +0700
JAMES-3459 Mailbox/changes MemoryMailboxChangeRepository implementation
---
.../apache/james/jmap/draft/JmapGuiceProbe.java | 2 +-
.../vacation/CassandraNotificationRegistry.java | 2 +-
.../vacation/CassandraNotificationRegistryDAO.java | 2 +-
.../cassandra/vacation/CassandraVacationDAO.java | 2 +-
.../vacation/CassandraVacationRepository.java | 2 +-
.../james/jmap/api/change/MailboxChange.java | 124 ++++++++++
.../MailboxChangeRepository.java} | 16 +-
.../james/jmap/api/change/MailboxChanges.java | 166 +++++++++++++
.../ChangeNotFoundException.java} | 22 +-
.../jmap/api/{vacation => model}/AccountId.java | 2 +-
.../jmap/api/vacation/NotificationRegistry.java | 2 +
.../jmap/api/vacation/VacationRepository.java | 2 +
.../change/MemoryMailboxChangeRepository.java | 77 ++++++
.../vacation/MemoryNotificationRegistry.java | 2 +-
.../memory/vacation/MemoryVacationRepository.java | 2 +-
.../change/MailboxChangeRepositoryContract.java | 269 +++++++++++++++++++++
.../james/jmap/api/vacation/AccountIdTest.java | 1 +
.../api/vacation/NotificationRegistryContract.java | 1 +
.../api/vacation/VacationRepositoryContract.java | 1 +
.../change/MemoryMailboxChangeRepositoryTest.java} | 22 +-
.../apache/james/jmap/VacationIntegrationTest.java | 2 +-
.../james/jmap/VacationRelayIntegrationTest.java | 2 +-
.../integration/GetVacationResponseTest.java | 2 +-
.../integration/SetVacationResponseTest.java | 2 +-
.../draft/methods/GetVacationResponseMethod.java | 2 +-
.../draft/methods/SetVacationResponseMethod.java | 2 +-
.../apache/james/jmap/mailet/VacationMailet.java | 2 +-
.../methods/GetVacationResponseMethodTest.java | 2 +-
.../methods/SetVacationResponseMethodTest.java | 2 +-
.../james/jmap/mailet/VacationMailetTest.java | 2 +-
.../VacationResponseGetMethodContract.scala | 3 +-
.../jmap/method/VacationResponseGetMethod.scala | 3 +-
.../jmap/method/VacationResponseSetMethod.scala | 3 +-
33 files changed, 700 insertions(+), 48 deletions(-)
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
index 77ef5bc..6347e36 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
@@ -25,8 +25,8 @@ import javax.inject.Inject;
import org.apache.james.core.Username;
import org.apache.james.jmap.JMAPServer;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.projections.MessageFastViewProjection;
-import org.apache.james.jmap.api.vacation.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.api.vacation.VacationRepository;
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistry.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistry.java
index 4fa556f..4f564f8 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistry.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistry.java
@@ -25,7 +25,7 @@ import java.util.Optional;
import javax.inject.Inject;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.RecipientId;
import org.apache.james.util.date.ZonedDateTimeProvider;
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryDAO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryDAO.java
index bf297ce..508b12f 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryDAO.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraNotificationRegistryDAO.java
@@ -31,7 +31,7 @@ import java.util.Optional;
import javax.inject.Inject;
import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.RecipientId;
import org.apache.james.jmap.cassandra.vacation.tables.CassandraNotificationTable;
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
index 36d0562..5a3e472 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationDAO.java
@@ -34,7 +34,7 @@ import javax.inject.Inject;
import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
import org.apache.james.backends.cassandra.init.CassandraZonedDateTimeModule;
import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.cassandra.vacation.tables.CassandraVacationTable;
diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
index 06fc937..a3a24bb 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/vacation/CassandraVacationRepository.java
@@ -21,7 +21,7 @@ package org.apache.james.jmap.cassandra.vacation;
import javax.inject.Inject;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.api.vacation.VacationRepository;
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
new file mode 100644
index 0000000..3bb849e
--- /dev/null
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
@@ -0,0 +1,124 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.api.change;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.james.jmap.api.model.AccountId;
+import org.apache.james.mailbox.model.MailboxId;
+
+public class MailboxChange {
+
+ public static class State {
+
+ public static State of(UUID value) {
+ return new State(value);
+ }
+
+ private final UUID value;
+
+ private State(UUID value) {
+ this.value = value;
+ }
+
+ public UUID getValue() {
+ return value;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof State) {
+ State state = (State) o;
+
+ return Objects.equals(this.value, state.value);
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hash(value);
+ }
+ }
+
+ public static class Limit {
+
+ public static Limit of(int value) {
+ return new Limit(value);
+ }
+
+ private final int value;
+
+ private Limit(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+ }
+
+ public static MailboxChange of(AccountId accountId, State state, ZonedDateTime date, List<MailboxId> created, List<MailboxId> updated, List<MailboxId> destroyed) {
+ return new MailboxChange(accountId, state, date, created, updated, destroyed);
+ }
+
+ private final AccountId accountId;
+ private final State state;
+ private final ZonedDateTime date;
+ private final List<MailboxId> created;
+ private final List<MailboxId> updated;
+ private final List<MailboxId> destroyed;
+
+ private MailboxChange(AccountId accountId, State state, ZonedDateTime date, List<MailboxId> created, List<MailboxId> updated, List<MailboxId> destroyed) {
+ this.accountId = accountId;
+ this.state = state;
+ this.date = date;
+ this.created = created;
+ this.updated = updated;
+ this.destroyed = destroyed;
+ }
+
+ public AccountId getAccountId() {
+ return accountId;
+ }
+
+ public State getState() {
+ return state;
+ }
+
+ public ZonedDateTime getDate() {
+ return date;
+ }
+
+ public List<MailboxId> getCreated() {
+ return created;
+ }
+
+ public List<MailboxId> getUpdated() {
+ return updated;
+ }
+
+ public List<MailboxId> getDestroyed() {
+ return destroyed;
+ }
+}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChangeRepository.java
similarity index 75%
copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
copy to server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChangeRepository.java
index 1526ca4..fb965be 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChangeRepository.java
@@ -17,19 +17,19 @@
* under the License. *
****************************************************************/
-package org.apache.james.jmap.api.vacation;
+package org.apache.james.jmap.api.change;
-import java.time.ZonedDateTime;
import java.util.Optional;
-import reactor.core.publisher.Mono;
-
-public interface NotificationRegistry {
+import org.apache.james.jmap.api.change.MailboxChange.Limit;
+import org.apache.james.jmap.api.change.MailboxChange.State;
+import org.apache.james.jmap.api.model.AccountId;
- Mono<Void> register(AccountId accountId, RecipientId recipientId, Optional<ZonedDateTime> expiryDate);
+import reactor.core.publisher.Mono;
- Mono<Boolean> isRegistered(AccountId accountId, RecipientId recipientId);
+public interface MailboxChangeRepository {
- Mono<Void> flush(AccountId accountId);
+ Mono<Void> save(MailboxChange change);
+ Mono<MailboxChanges> getSinceState(AccountId accountId, State state, Optional<Limit> maxIdsToReturn);
}
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
new file mode 100644
index 0000000..0dc1bc9
--- /dev/null
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChanges.java
@@ -0,0 +1,166 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.api.change;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.james.mailbox.model.MailboxId;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+
+public class MailboxChanges {
+
+ public static class MailboxChangesBuilder {
+
+ public static class MailboxChangeCollector implements Collector<MailboxChange, MailboxChangesBuilder, MailboxChanges> {
+ private final MailboxChange.Limit limit;
+
+ public MailboxChangeCollector(MailboxChange.Limit limit) {
+ this.limit = limit;
+ }
+
+ @Override
+ public Supplier<MailboxChangesBuilder> supplier() {
+ return () -> new MailboxChangesBuilder(limit);
+ }
+
+ public BiConsumer<MailboxChangesBuilder, MailboxChange> accumulator() {
+ return MailboxChangesBuilder::add;
+ }
+
+ @Override
+ public BinaryOperator<MailboxChangesBuilder> combiner() {
+ throw new NotImplementedException("Not supported");
+ }
+
+ @Override
+ public Function<MailboxChangesBuilder, MailboxChanges> finisher() {
+ return MailboxChangesBuilder::build;
+ }
+
+ @Override
+ public Set<Characteristics> characteristics() {
+ return Sets.immutableEnumSet(Characteristics.UNORDERED);
+ }
+ }
+
+ private MailboxChange.State state;
+ private boolean hasMoreChanges;
+ private boolean canAddMoreItem;
+ private MailboxChange.Limit limit;
+ private Set<MailboxId> created;
+ private Set<MailboxId> updated;
+ private Set<MailboxId> destroyed;
+
+ public MailboxChangesBuilder(MailboxChange.Limit limit) {
+ this.limit = limit;
+ this.hasMoreChanges = false;
+ this.canAddMoreItem = true;
+ this.created = new HashSet<>();
+ this.updated = new HashSet<>();
+ this.destroyed = new HashSet<>();
+ }
+
+ public MailboxChanges.MailboxChangesBuilder add(MailboxChange change) {
+ if (!canAddMoreItem) {
+ return this;
+ }
+
+ Set<MailboxId> createdTemp = new HashSet<>(created);
+ Set<MailboxId> updatedTemp = new HashSet<>(updated);
+ Set<MailboxId> destroyedTemp = new HashSet<>(destroyed);
+ createdTemp.addAll(change.getCreated());
+ updatedTemp.addAll(change.getUpdated());
+ destroyedTemp.addAll(change.getDestroyed());
+
+ if (createdTemp.size() + updatedTemp.size() + destroyedTemp.size() > limit.getValue()) {
+ hasMoreChanges = true;
+ canAddMoreItem = false;
+ return this;
+ }
+
+ state = change.getState();
+ this.created.addAll(change.getCreated());
+ this.updated.addAll(change.getUpdated());
+ this.destroyed.addAll(change.getDestroyed());
+
+ return this;
+ }
+
+ public MailboxChanges build() {
+ return new MailboxChanges(state, hasMoreChanges, created, updated, destroyed);
+ }
+ }
+
+ private MailboxChange.State newState;
+ private final boolean hasMoreChanges;
+ private final Set<MailboxId> created;
+ private final Set<MailboxId> updated;
+ private final Set<MailboxId> destroyed;
+
+ private MailboxChanges(MailboxChange.State newState, boolean hasMoreChanges, Set<MailboxId> created, Set<MailboxId> updated, Set<MailboxId> destroyed) {
+ this.newState = newState;
+ this.hasMoreChanges = hasMoreChanges;
+ this.created = created;
+ this.updated = updated;
+ this.destroyed = destroyed;
+ }
+
+ public MailboxChangesBuilder build(MailboxChange.Limit limit) {
+ return new MailboxChangesBuilder(limit);
+ }
+
+ public MailboxChange.State getNewState() {
+ return newState;
+ }
+
+ public boolean hasMoreChanges() {
+ return hasMoreChanges;
+ }
+
+ public Set<MailboxId> getCreated() {
+ return created;
+ }
+
+ public Set<MailboxId> getUpdated() {
+ return updated;
+ }
+
+ public Set<MailboxId> getDestroyed() {
+ return destroyed;
+ }
+
+ public List<MailboxId> getAllChanges() {
+ return ImmutableList.<MailboxId>builder()
+ .addAll(created)
+ .addAll(updated)
+ .addAll(destroyed)
+ .build();
+ }
+}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/exception/ChangeNotFoundException.java
similarity index 74%
copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
copy to server/data/data-jmap/src/main/java/org/apache/james/jmap/api/exception/ChangeNotFoundException.java
index 1526ca4..9fcc4a0 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/exception/ChangeNotFoundException.java
@@ -17,19 +17,19 @@
* under the License. *
****************************************************************/
-package org.apache.james.jmap.api.vacation;
+package org.apache.james.jmap.api.exception;
-import java.time.ZonedDateTime;
-import java.util.Optional;
+import org.apache.james.jmap.api.change.MailboxChange;
-import reactor.core.publisher.Mono;
+public class ChangeNotFoundException extends RuntimeException {
+ private final MailboxChange.State state;
-public interface NotificationRegistry {
-
- Mono<Void> register(AccountId accountId, RecipientId recipientId, Optional<ZonedDateTime> expiryDate);
-
- Mono<Boolean> isRegistered(AccountId accountId, RecipientId recipientId);
-
- Mono<Void> flush(AccountId accountId);
+ public ChangeNotFoundException(MailboxChange.State state, String msg) {
+ super(msg);
+ this.state = state;
+ }
+ public MailboxChange.State getState() {
+ return state;
+ }
}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/AccountId.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/AccountId.java
similarity index 98%
rename from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/AccountId.java
rename to server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/AccountId.java
index 59b181a..4f6417c 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/AccountId.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/AccountId.java
@@ -17,7 +17,7 @@
* under the License. *
****************************************************************/
-package org.apache.james.jmap.api.vacation;
+package org.apache.james.jmap.api.model;
import java.util.Objects;
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
index 1526ca4..b6f5a58 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/NotificationRegistry.java
@@ -22,6 +22,8 @@ package org.apache.james.jmap.api.vacation;
import java.time.ZonedDateTime;
import java.util.Optional;
+import org.apache.james.jmap.api.model.AccountId;
+
import reactor.core.publisher.Mono;
public interface NotificationRegistry {
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java
index fe58e49..9077da7 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java
@@ -19,6 +19,8 @@
package org.apache.james.jmap.api.vacation;
+import org.apache.james.jmap.api.model.AccountId;
+
import reactor.core.publisher.Mono;
public interface VacationRepository {
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java
new file mode 100644
index 0000000..e920904
--- /dev/null
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java
@@ -0,0 +1,77 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.memory.change;
+
+import java.util.Comparator;
+import java.util.Optional;
+
+import org.apache.james.jmap.api.change.MailboxChange;
+import org.apache.james.jmap.api.change.MailboxChange.Limit;
+import org.apache.james.jmap.api.change.MailboxChange.State;
+import org.apache.james.jmap.api.change.MailboxChangeRepository;
+import org.apache.james.jmap.api.change.MailboxChanges;
+import org.apache.james.jmap.api.change.MailboxChanges.MailboxChangesBuilder.MailboxChangeCollector;
+import org.apache.james.jmap.api.exception.ChangeNotFoundException;
+import org.apache.james.jmap.api.model.AccountId;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class MemoryMailboxChangeRepository implements MailboxChangeRepository {
+
+ public static final Limit DEFAULT_NUMBER_OF_CHANGES = Limit.of(5);
+ private final Multimap<AccountId, MailboxChange> mailboxChangeMap;
+
+ public MemoryMailboxChangeRepository() {
+ this.mailboxChangeMap = ArrayListMultimap.create();
+ }
+
+ @Override
+ public Mono<Void> save(MailboxChange change) {
+ Preconditions.checkNotNull(change.getAccountId());
+ Preconditions.checkNotNull(change.getState());
+
+ return Mono.just(mailboxChangeMap.put(change.getAccountId(), change)).then();
+ }
+
+ @Override
+ public Mono<MailboxChanges> getSinceState(AccountId accountId, State state, Optional<Limit> maxChanges) {
+ Preconditions.checkNotNull(accountId);
+ Preconditions.checkNotNull(state);
+ maxChanges.ifPresent(limit -> Preconditions.checkArgument(limit.getValue() > 0, "maxChanges must be a positive integer"));
+
+ return findByState(accountId, state)
+ .flatMapMany(currentState -> Flux.fromIterable(mailboxChangeMap.get(accountId))
+ .filter(change -> change.getDate().isAfter(currentState.getDate()))
+ .sort(Comparator.comparing(MailboxChange::getDate)))
+ .collect(new MailboxChangeCollector(maxChanges.orElse(DEFAULT_NUMBER_OF_CHANGES)));
+ }
+
+ private Mono<MailboxChange> findByState(AccountId accountId, State state) {
+ return Flux.fromIterable(mailboxChangeMap.get(accountId))
+ .filter(change -> change.getState().equals(state))
+ .switchIfEmpty(Mono.error(new ChangeNotFoundException(state, String.format("State '%s' could not be found", state.getValue()))))
+ .single();
+ }
+}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryNotificationRegistry.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryNotificationRegistry.java
index 315680e..914bbb2 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryNotificationRegistry.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryNotificationRegistry.java
@@ -24,7 +24,7 @@ import java.util.Optional;
import javax.inject.Inject;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.RecipientId;
import org.apache.james.util.date.ZonedDateTimeProvider;
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryVacationRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryVacationRepository.java
index 82e3b14..3948d05 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryVacationRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/vacation/MemoryVacationRepository.java
@@ -22,7 +22,7 @@ package org.apache.james.jmap.memory.vacation;
import java.util.HashMap;
import java.util.Map;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.api.vacation.VacationRepository;
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
new file mode 100644
index 0000000..66f27e3
--- /dev/null
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
@@ -0,0 +1,269 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jmap.api.change;
+
+import static org.apache.james.mailbox.fixture.MailboxFixture.BOB;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+import java.util.UUID;
+
+import org.apache.james.jmap.api.change.MailboxChange.Limit;
+import org.apache.james.jmap.api.change.MailboxChange.State;
+import org.apache.james.jmap.api.exception.ChangeNotFoundException;
+import org.apache.james.jmap.api.model.AccountId;
+import org.apache.james.mailbox.model.TestId;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public interface MailboxChangeRepositoryContract {
+ AccountId ACCOUNT_ID = AccountId.fromUsername(BOB);
+ ZonedDateTime DATE = ZonedDateTime.now();
+ State STATE_0 = State.of(UUID.randomUUID());
+
+ MailboxChangeRepository mailboxChangeRepository();
+
+ @Test
+ default void saveChangeShouldSuccess() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange change = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE, ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+
+ assertThatCode(() -> repository.save(change))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ default void saveChangeShouldFailWhenNoAccountId() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange change = MailboxChange.of(null, STATE_0, DATE, ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+
+ assertThatThrownBy(() -> repository.save(change).block())
+ .isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ default void saveChangeShouldFailWhenNoState() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange change = MailboxChange.of(ACCOUNT_ID, null, DATE, ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+
+ assertThatThrownBy(() -> repository.save(change).block())
+ .isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ default void getChangesShouldSuccess() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(1), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(), ImmutableList.of(TestId.of(1)), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ .hasSameElementsAs(change.getUpdated());
+ }
+
+ @Test
+ default void getChangesShouldReturnEmptyWhenNoNewerState() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE, ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ repository.save(oldState);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ .isEmpty();
+ }
+
+ @Test
+ default void getChangesShouldLimitChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(3), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(2), ImmutableList.of(TestId.of(2)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(3)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change3 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(4)), ImmutableList.of(), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+ repository.save(change3);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getCreated())
+ .containsExactlyInAnyOrder(TestId.of(2), TestId.of(3), TestId.of(4));
+ }
+
+ @Test
+ default void getChangesShouldLimitChangesWhenMaxChangesOmitted() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(7)), ImmutableList.of(), ImmutableList.of());
+
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getAllChanges())
+ .hasSameElementsAs(change1.getCreated());
+ }
+
+ @Test
+ default void getChangesShouldNotReturnMoreThanMaxChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(4), TestId.of(5)), ImmutableList.of(), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block().getAllChanges())
+ .hasSameElementsAs(change1.getCreated());
+ }
+
+ @Test
+ default void getChangesShouldReturnEmptyWhenNumberOfChangesExceedMaxChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of(), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change1);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().getAllChanges())
+ .isEmpty();
+ }
+
+ @Test
+ default void getChangesShouldReturnNewState() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block().getNewState())
+ .isEqualTo(change2.getState());
+ }
+
+ @Test
+ default void hasMoreChangesShouldBeTrueWhenMoreChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(1))).block().hasMoreChanges())
+ .isTrue();
+ }
+
+ @Test
+ default void hasMoreChangesShouldBeFalseWhenNoMoreChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of());
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(4))).block().hasMoreChanges())
+ .isFalse();
+ }
+
+ @Test
+ default void changesShouldBeStoredInTheirRespectiveType() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(3), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(2), ImmutableList.of(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(TestId.of(6), TestId.of(7)), ImmutableList.of(TestId.of(2), TestId.of(3)), ImmutableList.of(TestId.of(4)));
+ MailboxChange change3 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(8)), ImmutableList.of(TestId.of(6), TestId.of(7)), ImmutableList.of(TestId.of(5)));
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+ repository.save(change3);
+
+ MailboxChanges mailboxChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(20))).block();
+
+ SoftAssertions.assertSoftly(softly -> {
+ softly.assertThat(mailboxChanges.getCreated()).containsExactlyInAnyOrder(TestId.of(2), TestId.of(3), TestId.of(4), TestId.of(5), TestId.of(6), TestId.of(7), TestId.of(8));
+ softly.assertThat(mailboxChanges.getUpdated()).containsExactlyInAnyOrder(TestId.of(2), TestId.of(3), TestId.of(6), TestId.of(7));
+ softly.assertThat(mailboxChanges.getDestroyed()).containsExactlyInAnyOrder(TestId.of(4), TestId.of(5));
+ });
+ }
+
+ @Test
+ default void getChangesShouldIgnoreDuplicatedValues() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange oldState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE.minusHours(2), ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change1 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE.minusHours(1), ImmutableList.of(), ImmutableList.of(TestId.of(1), TestId.of(2)), ImmutableList.of());
+ MailboxChange change2 = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(3)), ImmutableList.of(TestId.of(1), TestId.of(2)), ImmutableList.of());
+
+ repository.save(oldState);
+ repository.save(change1);
+ repository.save(change2);
+
+ MailboxChanges mailboxChanges = repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(3))).block();
+ SoftAssertions.assertSoftly(softly -> {
+ softly.assertThat(mailboxChanges.getUpdated()).containsExactly(TestId.of(1), TestId.of(2));
+ softly.assertThat(mailboxChanges.getCreated()).containsExactly(TestId.of(3));
+ });
+ }
+
+ @Test
+ default void getChangesShouldFailWhenInvalidMaxChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ MailboxChange currentState = MailboxChange.of(ACCOUNT_ID, STATE_0, DATE, ImmutableList.of(TestId.of(1)), ImmutableList.of(), ImmutableList.of());
+ MailboxChange change = MailboxChange.of(ACCOUNT_ID, State.of(UUID.randomUUID()), DATE, ImmutableList.of(TestId.of(2)), ImmutableList.of(), ImmutableList.of());
+ repository.save(currentState);
+ repository.save(change);
+
+ assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.of(Limit.of(-1))))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ default void getChangesShouldFailWhenSinceStateNotFound() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+
+ assertThatThrownBy(() -> repository.getSinceState(ACCOUNT_ID, STATE_0, Optional.empty()).block())
+ .isInstanceOf(ChangeNotFoundException.class);
+ }
+}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AccountIdTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AccountIdTest.java
index ac4aa25..1870a49 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AccountIdTest.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/AccountIdTest.java
@@ -22,6 +22,7 @@ package org.apache.james.jmap.api.vacation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import org.apache.james.jmap.api.model.AccountId;
import org.junit.jupiter.api.Test;
class AccountIdTest {
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/NotificationRegistryContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/NotificationRegistryContract.java
index afd2c64..0d9d986 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/NotificationRegistryContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/NotificationRegistryContract.java
@@ -28,6 +28,7 @@ import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.util.date.ZonedDateTimeProvider;
import org.junit.jupiter.api.Test;
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationRepositoryContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationRepositoryContract.java
index 436e13a..23d5770 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationRepositoryContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/vacation/VacationRepositoryContract.java
@@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.ZonedDateTime;
import java.util.Optional;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.util.ValuePatch;
import org.junit.jupiter.api.Test;
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java
similarity index 66%
copy from server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java
copy to server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java
index fe58e49..9079e65 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/vacation/VacationRepository.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepositoryTest.java
@@ -17,16 +17,22 @@
* under the License. *
****************************************************************/
-package org.apache.james.jmap.api.vacation;
+package org.apache.james.jmap.memory.change;
-import reactor.core.publisher.Mono;
+import org.apache.james.jmap.api.change.MailboxChangeRepository;
+import org.apache.james.jmap.api.change.MailboxChangeRepositoryContract;
+import org.junit.jupiter.api.BeforeEach;
-public interface VacationRepository {
+public class MemoryMailboxChangeRepositoryTest implements MailboxChangeRepositoryContract {
+ MailboxChangeRepository mailboxChangeRepository;
- Vacation DEFAULT_VACATION = Vacation.builder().enabled(false).build();
-
- Mono<Void> modifyVacation(AccountId accountId, VacationPatch vacationPatch);
-
- Mono<Vacation> retrieveVacation(AccountId accountId);
+ @BeforeEach
+ void setup() {
+ mailboxChangeRepository = new MemoryMailboxChangeRepository();
+ }
+ @Override
+ public MailboxChangeRepository mailboxChangeRepository() {
+ return mailboxChangeRepository;
+ }
}
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
index ff7c010..9f72d73 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationIntegrationTest.java
@@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.james.GuiceJamesServer;
import org.apache.james.core.Username;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.draft.JmapGuiceProbe;
import org.apache.james.junit.categories.BasicFeature;
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationRelayIntegrationTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationRelayIntegrationTest.java
index 38d7344..77ad8a4 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationRelayIntegrationTest.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/VacationRelayIntegrationTest.java
@@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.net.smtp.SMTPClient;
import org.apache.james.GuiceJamesServer;
import org.apache.james.dnsservice.api.InMemoryDNSService;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.draft.JmapGuiceProbe;
import org.apache.james.junit.categories.BasicFeature;
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetVacationResponseTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetVacationResponseTest.java
index 3139ef0..dd150be 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetVacationResponseTest.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetVacationResponseTest.java
@@ -38,7 +38,7 @@ import java.time.ZonedDateTime;
import org.apache.james.GuiceJamesServer;
import org.apache.james.jmap.AccessToken;
import org.apache.james.jmap.FixedDateZonedDateTimeProvider;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.draft.JmapGuiceProbe;
import org.apache.james.junit.categories.BasicFeature;
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetVacationResponseTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetVacationResponseTest.java
index bf69793..0180c11 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetVacationResponseTest.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetVacationResponseTest.java
@@ -36,7 +36,7 @@ import java.util.Optional;
import org.apache.james.GuiceJamesServer;
import org.apache.james.core.Username;
import org.apache.james.jmap.AccessToken;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationPatch;
import org.apache.james.jmap.draft.JmapGuiceProbe;
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
index e47af51..df9aae3 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethod.java
@@ -23,7 +23,7 @@ import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
import javax.inject.Inject;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationRepository;
import org.apache.james.jmap.draft.model.GetVacationRequest;
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
index e8f2839..3b41a6c 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethod.java
@@ -24,7 +24,7 @@ import static org.apache.james.util.ReactorUtils.context;
import javax.inject.Inject;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationRepository;
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java
index aea13e6..f5fd41f 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java
@@ -27,7 +27,7 @@ import javax.mail.MessagingException;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.core.MailAddress;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.RecipientId;
import org.apache.james.jmap.api.vacation.Vacation;
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java
index 22ad61d..35c05ac 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetVacationResponseMethodTest.java
@@ -28,7 +28,7 @@ import java.util.Optional;
import java.util.stream.Stream;
import org.apache.james.core.Username;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationRepository;
import org.apache.james.jmap.draft.model.GetMailboxesRequest;
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java
index f8c9c20..04386b6 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetVacationResponseMethodTest.java
@@ -31,7 +31,7 @@ import java.util.Optional;
import java.util.stream.Stream;
import org.apache.james.core.Username;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.Vacation;
import org.apache.james.jmap.api.vacation.VacationRepository;
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java
index 4d36816..971628f 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java
@@ -33,7 +33,7 @@ import java.util.Optional;
import javax.mail.MessagingException;
import org.apache.james.core.MailAddress;
-import org.apache.james.jmap.api.vacation.AccountId;
+import org.apache.james.jmap.api.model.AccountId;
import org.apache.james.jmap.api.vacation.NotificationRegistry;
import org.apache.james.jmap.api.vacation.RecipientId;
import org.apache.james.jmap.api.vacation.Vacation;
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/VacationResponseGetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/VacationResponseGetMethodContract.scala
index 1ca2caf..0e39b11 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/VacationResponseGetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/VacationResponseGetMethodContract.scala
@@ -27,7 +27,8 @@ import io.restassured.http.ContentType.JSON
import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
import org.apache.http.HttpStatus.SC_OK
import org.apache.james.GuiceJamesServer
-import org.apache.james.jmap.api.vacation.{AccountId, VacationPatch}
+import org.apache.james.jmap.api.model.AccountId
+import org.apache.james.jmap.api.vacation.VacationPatch
import org.apache.james.jmap.draft.JmapGuiceProbe
import org.apache.james.jmap.http.UserCredential
import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder}
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala
index 926f5e0..b06821b 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala
@@ -21,7 +21,8 @@ package org.apache.james.jmap.method
import eu.timepit.refined.auto._
import javax.inject.Inject
-import org.apache.james.jmap.api.vacation.{VacationRepository, AccountId => JavaAccountId}
+import org.apache.james.jmap.api.model.{AccountId => JavaAccountId}
+import org.apache.james.jmap.api.vacation.VacationRepository
import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE}
import org.apache.james.jmap.core.Invocation.{Arguments, MethodCallId, MethodName}
import org.apache.james.jmap.core.State.INSTANCE
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala
index 56bd506..8cb940a 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala
@@ -21,7 +21,8 @@ package org.apache.james.jmap.method
import eu.timepit.refined.auto._
import javax.inject.Inject
-import org.apache.james.jmap.api.vacation.{AccountId, VacationPatch, VacationRepository}
+import org.apache.james.jmap.api.model.AccountId
+import org.apache.james.jmap.api.vacation.{VacationPatch, VacationRepository}
import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE}
import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
import org.apache.james.jmap.core.SetError.SetErrorDescription
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org