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 572f25d41b914ac1c14c4b02c2b72d3d49911743
Author: Tran Tien Duc <[email protected]>
AuthorDate: Thu Nov 21 17:09:00 2019 +0700

    JAMES-2989 MessagePreviewStore + memory implementation
---
 server/data/data-jmap/pom.xml                      |  10 ++
 .../jmap/api/preview/MessagePreviewStore.java      |  32 ++++
 .../memory/preview/MemoryMessagePreviewStore.java  |  62 ++++++++
 .../api/preview/MessagePreviewStoreContract.java   | 168 +++++++++++++++++++++
 .../preview/MemoryMessagePreviewStoreTest.java     |  39 +++++
 5 files changed, 311 insertions(+)

diff --git a/server/data/data-jmap/pom.xml b/server/data/data-jmap/pom.xml
index 249ae81..3626162 100644
--- a/server/data/data-jmap/pom.xml
+++ b/server/data/data-jmap/pom.xml
@@ -35,6 +35,16 @@
     <dependencies>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-core</artifactId>
         </dependency>
         <dependency>
diff --git 
a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java
 
b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java
new file mode 100644
index 0000000..c772b80
--- /dev/null
+++ 
b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java
@@ -0,0 +1,32 @@
+/****************************************************************
+ * 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.preview;
+
+import org.apache.james.mailbox.model.MessageId;
+import org.reactivestreams.Publisher;
+
+public interface MessagePreviewStore {
+
+    Publisher<Void> store(MessageId messageId, Preview preview);
+
+    Publisher<Preview> retrieve(MessageId messageId);
+
+    Publisher<Void> delete(MessageId messageId);
+}
diff --git 
a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java
 
b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java
new file mode 100644
index 0000000..58bf9c4
--- /dev/null
+++ 
b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java
@@ -0,0 +1,62 @@
+/****************************************************************
+ * 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.preview;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.james.jmap.api.preview.MessagePreviewStore;
+import org.apache.james.jmap.api.preview.Preview;
+import org.apache.james.mailbox.model.MessageId;
+import org.reactivestreams.Publisher;
+
+import com.google.common.base.Preconditions;
+
+import reactor.core.publisher.Mono;
+
+public class MemoryMessagePreviewStore implements MessagePreviewStore {
+
+    private final ConcurrentHashMap<MessageId, Preview> previews;
+
+    public MemoryMessagePreviewStore() {
+        this.previews = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public Publisher<Void> store(MessageId messageId, Preview preview) {
+        Preconditions.checkNotNull(messageId);
+        Preconditions.checkNotNull(preview);
+
+        return Mono.fromRunnable(() -> previews.put(messageId, preview));
+    }
+
+    @Override
+    public Publisher<Preview> retrieve(MessageId messageId) {
+        Preconditions.checkNotNull(messageId);
+
+        return Mono.fromSupplier(() -> previews.get(messageId));
+    }
+
+    @Override
+    public Publisher<Void> delete(MessageId messageId) {
+        Preconditions.checkNotNull(messageId);
+
+        return Mono.fromRunnable(() -> previews.remove(messageId));
+    }
+}
diff --git 
a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java
 
b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java
new file mode 100644
index 0000000..3320684
--- /dev/null
+++ 
b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java
@@ -0,0 +1,168 @@
+/****************************************************************
+ * 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.preview;
+
+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 org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.TestMessageId;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
+
+import reactor.core.publisher.Mono;
+
+public interface MessagePreviewStoreContract {
+
+    MessageId MESSAGE_ID_1 = TestMessageId.of(1);
+    Preview PREVIEW_1 = Preview.from("message id 1");
+    MessageId MESSAGE_ID_2 = TestMessageId.of(2);
+    Preview PREVIEW_2 = Preview.from("message id 2");
+
+    MessagePreviewStore testee();
+
+    @Test
+    default void retrieveShouldThrowWhenNullMessageId() {
+        assertThatThrownBy(() -> Mono.from(testee().retrieve(null)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void retrieveShouldReturnStoredPreview() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+            .isEqualTo(PREVIEW_1);
+    }
+
+    @Test
+    default void retrieveShouldReturnEmptyWhenMessageIdNotFound() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_2)).blockOptional())
+            .isEmpty();
+    }
+
+    @Test
+    default void 
retrieveShouldReturnTheRightPreviewWhenStoringMultipleMessageIds() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+        Mono.from(testee().store(MESSAGE_ID_2, PREVIEW_2))
+            .block();
+
+        SoftAssertions.assertSoftly(softly -> {
+           
softly.assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+               .isEqualTo(PREVIEW_1);
+           
softly.assertThat(Mono.from(testee().retrieve(MESSAGE_ID_2)).block())
+               .isEqualTo(PREVIEW_2);
+        });
+    }
+
+    @Test
+    default void storeShouldThrowWhenNullMessageId() {
+        assertThatThrownBy(() -> Mono.from(testee().store(null, 
PREVIEW_1)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void storeShouldThrowWhenNullPreview() {
+        assertThatThrownBy(() -> Mono.from(testee().store(MESSAGE_ID_1, 
null)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void storeShouldOverrideOldRecord() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_2))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+            .isEqualTo(PREVIEW_2);
+    }
+
+    @Test
+    default void storeShouldBeIdempotent() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+            .isEqualTo(PREVIEW_1);
+    }
+
+    @Test
+    default void deleteShouldThrowWhenNullMessageId() {
+        assertThatThrownBy(() -> Mono.from(testee().delete(null)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void deleteShouldNotThrowWhenMessageIdNotFound() {
+        assertThatCode(() -> Mono.from(testee().delete(MESSAGE_ID_1)).block())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    default void deleteShouldDeleteStoredRecord() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).blockOptional())
+            .isEmpty();
+    }
+
+    @Test
+    default void deleteShouldNotDeleteAnotherRecord() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+        Mono.from(testee().store(MESSAGE_ID_2, PREVIEW_2))
+            .block();
+
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_2)).block())
+            .isEqualTo(PREVIEW_2);
+    }
+
+    @Test
+    default void deleteShouldBeIdempotent() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).blockOptional())
+            .isEmpty();
+    }
+}
\ No newline at end of file
diff --git 
a/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java
 
b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java
new file mode 100644
index 0000000..d56c38f
--- /dev/null
+++ 
b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java
@@ -0,0 +1,39 @@
+/****************************************************************
+ * 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.preview;
+
+import org.apache.james.jmap.api.preview.MessagePreviewStore;
+import org.apache.james.jmap.api.preview.MessagePreviewStoreContract;
+import org.junit.jupiter.api.BeforeEach;
+
+class MemoryMessagePreviewStoreTest implements MessagePreviewStoreContract {
+
+    private MemoryMessagePreviewStore testee;
+
+    @BeforeEach
+    void setUp() {
+        testee = new MemoryMessagePreviewStore();
+    }
+
+    @Override
+    public MessagePreviewStore testee() {
+        return testee;
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to