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]
