From 83f816c2f6aee4eb2f83dfd4b8e111fdc400f986 Mon Sep 17 00:00:00 2001 From: Yurii Dubinka Date: Fri, 5 Apr 2019 21:08:23 +0530 Subject: [PATCH] #4: Implement draft of search mechanism --- readme.md | 2 +- .../java/io/github/dgroup/mbox4j/Query.java | 6 +- .../mbox4j/inbox/javax/JavaxMailInbox.java | 11 +- .../inbox/javax/search/{mode => }/All.java | 33 +---- .../inbox/javax/search/{mode => }/Modes.java | 22 ++-- .../mbox4j/inbox/javax/search/Range.java | 56 ++++++++ .../mbox4j/inbox/javax/search/Recent.java | 58 +++++++++ .../search/Search.java} | 45 ++++--- .../mbox4j/inbox/javax/search/SearchOf.java | 121 ++++++++++++++++++ .../mbox4j/inbox/javax/search/Unread.java | 58 +++++++++ .../inbox/javax/search/package-info.java | 39 ++++++ .../mode/package-info.java => query/Arg.java} | 20 ++- .../io/github/dgroup/mbox4j/query/ArgOf.java | 63 +++++++++ .../io/github/dgroup/mbox4j/query/Mode.java | 69 ++++++++++ .../github/dgroup/mbox4j/query/QueryOf.java | 5 +- .../github/dgroup/mbox4j/query/mode/All.java | 10 +- .../mbox4j/query/mode/ModeEnvelope.java | 79 ++++++++++++ .../query/mode/{ModeOf.java => Range.java} | 49 ++----- .../query/mode/{Mode.java => Recent.java} | 14 +- .../mbox4j/query/mode/package-info.java | 4 +- .../inbox/javax/JavaxMailInboxTestIT.java | 27 +--- 21 files changed, 646 insertions(+), 145 deletions(-) rename src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/{mode => }/All.java (60%) rename src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/{mode => }/Modes.java (75%) create mode 100644 src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Range.java create mode 100644 src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Recent.java rename src/main/java/io/github/dgroup/mbox4j/inbox/{InboxOf.java => javax/search/Search.java} (58%) create mode 100644 src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/SearchOf.java create mode 100644 src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Unread.java create mode 100644 src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/package-info.java rename src/main/java/io/github/dgroup/mbox4j/{inbox/javax/search/mode/package-info.java => query/Arg.java} (79%) create mode 100644 src/main/java/io/github/dgroup/mbox4j/query/ArgOf.java create mode 100644 src/main/java/io/github/dgroup/mbox4j/query/Mode.java create mode 100644 src/main/java/io/github/dgroup/mbox4j/query/mode/ModeEnvelope.java rename src/main/java/io/github/dgroup/mbox4j/query/mode/{ModeOf.java => Range.java} (57%) rename src/main/java/io/github/dgroup/mbox4j/query/mode/{Mode.java => Recent.java} (82%) diff --git a/readme.md b/readme.md index ffcab59..574c8e7 100644 --- a/readme.md +++ b/readme.md @@ -62,7 +62,7 @@ public static void main(final String[] args) { ... final Inbox inbox = new JavaxMailInbox(smtp); final Iterable msgs = inbox.read( - new Query("imaps", "INBOX", new All()) + new Query("pop3s", "INBOX", new All()) ); for(final Msg msg : msgs) { System.out.println(msg); diff --git a/src/main/java/io/github/dgroup/mbox4j/Query.java b/src/main/java/io/github/dgroup/mbox4j/Query.java index ea434d8..7ba9bff 100644 --- a/src/main/java/io/github/dgroup/mbox4j/Query.java +++ b/src/main/java/io/github/dgroup/mbox4j/Query.java @@ -24,7 +24,7 @@ package io.github.dgroup.mbox4j; -import io.github.dgroup.mbox4j.query.mode.Mode; +import io.github.dgroup.mbox4j.query.Mode; /** * The query for email search procedure.. @@ -50,9 +50,9 @@ public interface Query { String folder(); /** - * The type of search mode within email folder. + * The type of the search mode within email folder. * @return The mode. - * @see io.github.dgroup.mbox4j.query.mode.All + * @see io.github.dgroup.mbox4j.query.mode */ Mode mode(); diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInbox.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInbox.java index 58eef67..e3230f8 100644 --- a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInbox.java +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInbox.java @@ -28,8 +28,8 @@ import io.github.dgroup.mbox4j.Inbox; import io.github.dgroup.mbox4j.Msg; import io.github.dgroup.mbox4j.Query; -import io.github.dgroup.mbox4j.inbox.javax.search.mode.Modes; -import java.util.Collections; +import io.github.dgroup.mbox4j.inbox.javax.search.Modes; +import io.github.dgroup.mbox4j.inbox.javax.search.Search; import java.util.Properties; import javax.mail.Folder; import javax.mail.MessagingException; @@ -44,8 +44,6 @@ * {@code final Inbox inbox = new JavaxMailInbox(smptProperties);} * * @since 0.1.0 - * @todo #/DEV Implement search to the javax instead of fetching all messages. - * The search should be based on {@link Query}. */ public final class JavaxMailInbox implements Inbox { @@ -100,8 +98,9 @@ public Iterable read(final Query query) throws EmailException { folder = store.getFolder(query.folder()); folder.open(Folder.READ_ONLY); return this.modes.getOrDefault( - query.mode(), fallback -> Collections.emptySet() - ).apply(folder); + query.mode().name(), + new Search.Empty() + ).apply(query, folder); // @checkstyle IllegalCatchCheck (3 lines) } catch (final Exception cause) { throw new EmailException(cause); diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/All.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/All.java similarity index 60% rename from src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/All.java rename to src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/All.java index ac6b620..b2aeda6 100644 --- a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/All.java +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/All.java @@ -22,46 +22,25 @@ * OR OTHER DEALINGS IN THE SOFTWARE. */ -package io.github.dgroup.mbox4j.inbox.javax.search.mode; +package io.github.dgroup.mbox4j.inbox.javax.search; -import io.github.dgroup.mbox4j.Msg; -import io.github.dgroup.mbox4j.inbox.javax.ToMsg; -import java.util.ArrayList; -import javax.mail.Folder; -import javax.mail.Message; -import org.cactoos.Func; -import org.cactoos.collection.Mapped; +import io.github.dgroup.mbox4j.query.Mode; +import org.cactoos.iterable.IterableOf; /** * Search mode within the email folder which is fetching all emails * using {@link javax.mail}. * * @since 0.1.0 + * @todo #/DEV All#search - Add integration test */ -public final class All implements Func> { - - /** - * The function to map {@link javax.mail.Message} to {@link Msg}. - */ - private final Func fnc; +public final class All extends SearchOf { /** * Ctor. */ public All() { - this(new ToMsg()); + super((query, folder) -> new IterableOf<>(folder.getMessages()), Mode.ALL); } - /** - * Ctor. - * @param fnc The function to map {@link javax.mail.Message} to {@link Msg}. - */ - public All(final Func fnc) { - this.fnc = fnc; - } - - @Override - public Iterable apply(final Folder folder) throws Exception { - return new ArrayList<>(new Mapped<>(this.fnc, folder.getMessages())); - } } diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/Modes.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Modes.java similarity index 75% rename from src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/Modes.java rename to src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Modes.java index 3c3fbb4..db72dfe 100644 --- a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/Modes.java +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Modes.java @@ -22,13 +22,10 @@ * OR OTHER DEALINGS IN THE SOFTWARE. */ -package io.github.dgroup.mbox4j.inbox.javax.search.mode; +package io.github.dgroup.mbox4j.inbox.javax.search; -import io.github.dgroup.mbox4j.Msg; -import io.github.dgroup.mbox4j.query.mode.Mode; +import io.github.dgroup.mbox4j.query.Mode; import java.util.Map; -import javax.mail.Folder; -import org.cactoos.Func; import org.cactoos.map.MapEntry; import org.cactoos.map.MapEnvelope; import org.cactoos.map.MapOf; @@ -38,24 +35,25 @@ * * @since 0.1.0 */ -public final class Modes extends MapEnvelope>> { +public final class Modes extends MapEnvelope { /** * Ctor. */ public Modes() { - this( - new MapOf<>( - new MapEntry<>(new io.github.dgroup.mbox4j.query.mode.All(), new All()) - ) - ); + this(new MapOf<>( + new MapEntry<>(Mode.ALL, new All()), + new MapEntry<>(Mode.RECENT, new Recent()), + new MapEntry<>(Mode.RANGE, new Range()), + new MapEntry<>(Mode.UNREAD, new Unread()) + )); } /** * Ctor. * @param modes The search modes. */ - public Modes(final Map>> modes) { + public Modes(final Map modes) { super(() -> modes); } } diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Range.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Range.java new file mode 100644 index 0000000..78780a6 --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Range.java @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.inbox.javax.search; + +import io.github.dgroup.mbox4j.query.Mode; +import org.cactoos.iterable.IterableOf; + +/** + * Search mode within the email folder which is fetching emails + * based on their indexes using {@link javax.mail}. + * + * The indexing starts from 1. + * + * @since 0.1.0 + * @todo #/DEV Range#search - add integration test + */ +public final class Range extends SearchOf { + + /** + * Ctor. + */ + public Range() { + super( + (query, folder) -> { + final String zero = "0"; + final int start = Integer.parseInt(query.mode().argument("start", zero)); + final int end = Integer.parseInt(query.mode().argument("end", zero)); + return new IterableOf<>(folder.getMessages(start, end)); + }, + Mode.RANGE + ); + } + +} diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Recent.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Recent.java new file mode 100644 index 0000000..a6ce3fc --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Recent.java @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.inbox.javax.search; + +import io.github.dgroup.mbox4j.query.Mode; +import java.util.concurrent.atomic.AtomicInteger; +import javax.mail.Flags.Flag; +import org.cactoos.iterable.Filtered; + +/** + * Search mode within the email folder which is fetching all recent email. + * using {@link javax.mail}. + * + * @since 0.1.0 + * @todo #/DEV Recent#search - add integration test + */ +public final class Recent extends SearchOf { + + /** + * Ctor. + */ + public Recent() { + super( + (query, folder) -> { + final int quantity = folder.getNewMessageCount(); + final AtomicInteger added = new AtomicInteger(0); + return new Filtered<>( + msg -> msg.isSet(Flag.RECENT) && added.incrementAndGet() < quantity, + folder.getMessages() + ); + }, + Mode.RECENT + ); + } + +} diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/InboxOf.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Search.java similarity index 58% rename from src/main/java/io/github/dgroup/mbox4j/inbox/InboxOf.java rename to src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Search.java index d9b6ce5..6466b71 100644 --- a/src/main/java/io/github/dgroup/mbox4j/inbox/InboxOf.java +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Search.java @@ -22,37 +22,42 @@ * OR OTHER DEALINGS IN THE SOFTWARE. */ -package io.github.dgroup.mbox4j.inbox; +package io.github.dgroup.mbox4j.inbox.javax.search; import io.github.dgroup.mbox4j.EmailException; import io.github.dgroup.mbox4j.Msg; import io.github.dgroup.mbox4j.Query; -import org.cactoos.Func; +import java.util.Collections; +import javax.mail.Folder; +import org.cactoos.BiFunc; /** - * The email inbox. - * - * @see io.github.dgroup.mbox4j.Inbox - * @see io.github.dgroup.mbox4j.inbox.javax.func + * The search within email folder. * * @since 0.1.0 + * @todo #/DEV Add documentation about {@link io.github.dgroup.mbox4j.inbox.javax.search} + * to the readme.md. */ -public final class InboxOf extends InboxEnvelope { +public interface Search extends BiFunc> { /** - * Ctor. - * @param fnc The function to fetch email messages based on query. - * @see io.github.dgroup.mbox4j.inbox.javax.func + * Search the emails. + * @param query The search details. + * @param folder The email folder. + * @return The emails. + * @throws EmailException In the case of connectivity/transformation issues. */ - @SuppressWarnings("PMD.AvoidCatchingGenericException") - public InboxOf(final Func> fnc) { - super(query -> { - try { - return fnc.apply(query); - // @checkstyle IllegalCatchCheck (3 lines) - } catch (final Exception cause) { - throw new EmailException(cause); - } - }); + Iterable apply(Query query, Folder folder) throws EmailException; + + /** + * The search which returns empty result. + * @since 0.1.0 + */ + class Empty implements Search { + + @Override + public Iterable apply(final Query query, final Folder folder) { + return Collections.emptySet(); + } } } diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/SearchOf.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/SearchOf.java new file mode 100644 index 0000000..c97b382 --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/SearchOf.java @@ -0,0 +1,121 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.inbox.javax.search; + +import io.github.dgroup.mbox4j.EmailException; +import io.github.dgroup.mbox4j.Msg; +import io.github.dgroup.mbox4j.Query; +import io.github.dgroup.mbox4j.inbox.javax.ToMsg; +import java.util.ArrayList; +import java.util.Objects; +import javax.mail.Folder; +import javax.mail.Message; +import org.cactoos.BiFunc; +import org.cactoos.Func; +import org.cactoos.collection.Mapped; + +/** + * The default search. + * + * @since 0.1.0 + */ +public class SearchOf implements Search { + + /** + * The function to filter messages from particular email folder. + */ + private final BiFunc> fltr; + + /** + * The name of the search mode. + */ + private final String mode; + + /** + * The function to map {@link Message} to {@link Msg}. + */ + private final Func fmap; + + /** + * Ctor. + * @param fltr The function to filter the messages from. + * @param mode The search mode. + */ + public SearchOf(final BiFunc> fltr, final String mode) { + this(fltr, mode, new ToMsg()); + } + + /** + * Ctor. + * @param fltr The function to filter the messages from. + * @param mode The search mode. + * @param fmap The function to map {@link Message} to {@link Msg}. + */ + public SearchOf( + final BiFunc> fltr, + final String mode, + final Func fmap + ) { + this.fmap = fmap; + this.fltr = fltr; + this.mode = mode; + } + + @Override + @SuppressWarnings("PMD.AvoidCatchingGenericException") + public final Iterable apply(final Query query, final Folder folder) throws EmailException { + try { + return new ArrayList<>( + new Mapped<>(this.fmap, this.fltr.apply(query, folder)) + ); + // @checkstyle IllegalCatchCheck (3 lines) + } catch (final Exception cause) { + throw new EmailException(cause); + } + } + + @Override + public final int hashCode() { + return this.toString().hashCode(); + } + + @Override + @SuppressWarnings("PMD.OnlyOneReturn") + public final boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Search)) { + return false; + } + final Search that = (Search) obj; + return Objects.equals(this.toString(), that.toString()); + } + + @Override + public final String toString() { + return this.mode; + } +} diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Unread.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Unread.java new file mode 100644 index 0000000..2d55e60 --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/Unread.java @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.inbox.javax.search; + +import io.github.dgroup.mbox4j.query.Mode; +import java.util.concurrent.atomic.AtomicInteger; +import javax.mail.Flags; +import org.cactoos.iterable.Filtered; + +/** + * Search mode within the email folder which is fetching all unread email. + * using {@link javax.mail}. + * + * @since 0.1.0 + * @todo #/DEV Unread#search - add integration test + */ +public final class Unread extends SearchOf { + + /** + * Ctor. + */ + public Unread() { + super( + (query, folder) -> { + final int quantity = folder.getUnreadMessageCount(); + final AtomicInteger added = new AtomicInteger(0); + return new Filtered<>( + msg -> !msg.isSet(Flags.Flag.SEEN) && added.incrementAndGet() < quantity, + folder.getMessages() + ); + }, + Mode.RECENT + ); + } + +} diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/package-info.java b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/package-info.java new file mode 100644 index 0000000..e949a81 --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/package-info.java @@ -0,0 +1,39 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * The classes related to search procedure within the emails + * using {@link javax.mail} framework. + * + * @since 0.1.0 + * @todo #/DEV From: new search mode which allows to fetch only emails from + * the particular sender. + * @todo #/DEV HasAttachments: new search mode which allows to fetch only emails + * which have the attachments. + * @todo #/DEV Subject: new search mode which allows to fetch only emails + * with particular subject. + * @todo #/DEV Important: new search mode which allows to fetch only emails + * which are flagged by important flag. + */ +package io.github.dgroup.mbox4j.inbox.javax.search; diff --git a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/package-info.java b/src/main/java/io/github/dgroup/mbox4j/query/Arg.java similarity index 79% rename from src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/package-info.java rename to src/main/java/io/github/dgroup/mbox4j/query/Arg.java index 624bba5..cedd285 100644 --- a/src/main/java/io/github/dgroup/mbox4j/inbox/javax/search/mode/package-info.java +++ b/src/main/java/io/github/dgroup/mbox4j/query/Arg.java @@ -22,10 +22,24 @@ * OR OTHER DEALINGS IN THE SOFTWARE. */ +package io.github.dgroup.mbox4j.query; + /** - * The classes related to search procedure within the emails - * using {@link javax.mail} framework. + * The single search argument. * * @since 0.1.0 */ -package io.github.dgroup.mbox4j.inbox.javax.search.mode; +public interface Arg { + + /** + * The label of search argument. + * @return The label. + */ + String name(); + + /** + * The value of search argument. + * @return The value. + */ + String value(); +} diff --git a/src/main/java/io/github/dgroup/mbox4j/query/ArgOf.java b/src/main/java/io/github/dgroup/mbox4j/query/ArgOf.java new file mode 100644 index 0000000..8314650 --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/query/ArgOf.java @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.query; + +/** + * The search argument. + * + * @since 0.1.0 + */ +public final class ArgOf implements Arg { + + /** + * The name of the argument. + */ + private final String label; + + /** + * The value of the argument. + */ + private final String val; + + /** + * Ctor. + * @param label The name of the argument. + * @param val The value of the argument. + */ + public ArgOf(final String label, final String val) { + this.label = label; + this.val = val; + } + + @Override + public String name() { + return this.label; + } + + @Override + public String value() { + return this.val; + } +} diff --git a/src/main/java/io/github/dgroup/mbox4j/query/Mode.java b/src/main/java/io/github/dgroup/mbox4j/query/Mode.java new file mode 100644 index 0000000..fda3add --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/query/Mode.java @@ -0,0 +1,69 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.query; + +/** + * The supported email search modes. + * + * @since 0.1.0 + */ +public interface Mode { + + /** + * Find all emails within particular folder. + */ + String ALL = "all"; + + /** + * Find all recent emails within particular folder. + */ + String RECENT = "recent"; + + /** + * Find the range of emails based on their indexes + * within particular folder. + * The indexes starts from 1. + */ + String RANGE = "range"; + + /** + * Find all unread emails within particular folder. + */ + String UNREAD = "unread"; + + /** + * The type of the search mode. + * @return The name. + */ + String name(); + + /** + * The argument's value within the search mode. + * @param name The name of the argument. + * @param fallback The default value in case if argument is absent. + * @return The value. + */ + String argument(String name, String fallback); +} diff --git a/src/main/java/io/github/dgroup/mbox4j/query/QueryOf.java b/src/main/java/io/github/dgroup/mbox4j/query/QueryOf.java index 0373177..54dc5f7 100644 --- a/src/main/java/io/github/dgroup/mbox4j/query/QueryOf.java +++ b/src/main/java/io/github/dgroup/mbox4j/query/QueryOf.java @@ -25,7 +25,6 @@ package io.github.dgroup.mbox4j.query; import io.github.dgroup.mbox4j.Query; -import io.github.dgroup.mbox4j.query.mode.Mode; import java.util.Objects; /** @@ -46,7 +45,7 @@ public final class QueryOf implements Query { private final String fld; /** - * The type of search mode within email folder. + * The type of the search mode within email folder. */ private final Mode mde; @@ -54,7 +53,7 @@ public final class QueryOf implements Query { * Ctor. * @param protocol The email connection protocol. * @param folder The root folder for search. - * @param mode The type of search mode within email folder. + * @param mode The type of the search mode within email folder. */ public QueryOf(final String protocol, final String folder, final Mode mode) { this.pcl = protocol; diff --git a/src/main/java/io/github/dgroup/mbox4j/query/mode/All.java b/src/main/java/io/github/dgroup/mbox4j/query/mode/All.java index 9c75d0c..69ff37d 100644 --- a/src/main/java/io/github/dgroup/mbox4j/query/mode/All.java +++ b/src/main/java/io/github/dgroup/mbox4j/query/mode/All.java @@ -24,18 +24,20 @@ package io.github.dgroup.mbox4j.query.mode; +import io.github.dgroup.mbox4j.query.Mode; +import java.util.Collections; + /** - * Search mode within the email folder which is fetching all emails. + * Find all emails within folder. * * @since 0.1.0 */ -public final class All extends ModeOf { +public final class All extends ModeEnvelope { /** * Ctor. */ public All() { - super("all"); + super(Mode.ALL, Collections.emptyMap()); } - } diff --git a/src/main/java/io/github/dgroup/mbox4j/query/mode/ModeEnvelope.java b/src/main/java/io/github/dgroup/mbox4j/query/mode/ModeEnvelope.java new file mode 100644 index 0000000..ddeb687 --- /dev/null +++ b/src/main/java/io/github/dgroup/mbox4j/query/mode/ModeEnvelope.java @@ -0,0 +1,79 @@ +/* + * MIT License + * + * Copyright (c) 2019 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.mbox4j.query.mode; + +import io.github.dgroup.mbox4j.query.Arg; +import io.github.dgroup.mbox4j.query.Mode; +import java.util.Map; +import org.cactoos.iterable.IterableOf; +import org.cactoos.map.MapOf; + +/** + * The envelope for {@link Mode}. + * + * @since 0.1.0 + */ +public class ModeEnvelope implements Mode { + + /** + * The name of the search mode. + */ + private final String label; + + /** + * The search arguments. + */ + private final Map arg; + + /** + * Ctor. + * @param mode The name of the search mode. + * @param args The search arguments. + */ + public ModeEnvelope(final String mode, final Arg... args) { + this(mode, new MapOf<>(Arg::name, Arg::value, new IterableOf<>(args))); + } + + /** + * Ctor. + * @param mode The name of the search mode. + * @param args The search arguments. + */ + public ModeEnvelope(final String mode, final Map args) { + this.label = mode; + this.arg = args; + } + + @Override + public final String name() { + return this.label; + } + + @Override + public final String argument(final String name, final String fallback) { + return this.arg.getOrDefault(name, fallback); + } + +} diff --git a/src/main/java/io/github/dgroup/mbox4j/query/mode/ModeOf.java b/src/main/java/io/github/dgroup/mbox4j/query/mode/Range.java similarity index 57% rename from src/main/java/io/github/dgroup/mbox4j/query/mode/ModeOf.java rename to src/main/java/io/github/dgroup/mbox4j/query/mode/Range.java index 558d990..8cd6928 100644 --- a/src/main/java/io/github/dgroup/mbox4j/query/mode/ModeOf.java +++ b/src/main/java/io/github/dgroup/mbox4j/query/mode/Range.java @@ -24,53 +24,24 @@ package io.github.dgroup.mbox4j.query.mode; -import java.util.Objects; +import io.github.dgroup.mbox4j.query.ArgOf; +import io.github.dgroup.mbox4j.query.Mode; /** - * Search mode within email folder. + * Find range of emails based on their indexes. + * + * The indexes starts from 1. * * @since 0.1.0 */ -public class ModeOf implements Mode { - - /** - * The type of search mode within email folder. - */ - private final String mode; +public final class Range extends ModeEnvelope { /** * Ctor. - * @param mode The type of search mode within email folder. + * @param start The start email index. + * @param end The end email index. */ - public ModeOf(final String mode) { - this.mode = mode; - } - - @Override - public final String name() { - return this.mode; - } - - @Override - @SuppressWarnings("PMD.OnlyOneReturn") - public final boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Mode)) { - return false; - } - final Mode that = (Mode) obj; - return Objects.equals(this.name(), that.name()); - } - - @Override - public final int hashCode() { - return Objects.hash(this.name()); - } - - @Override - public final String toString() { - return this.name(); + public Range(final Integer start, final Integer end) { + super(Mode.RANGE, new ArgOf("start", start.toString()), new ArgOf("end", end.toString())); } } diff --git a/src/main/java/io/github/dgroup/mbox4j/query/mode/Mode.java b/src/main/java/io/github/dgroup/mbox4j/query/mode/Recent.java similarity index 82% rename from src/main/java/io/github/dgroup/mbox4j/query/mode/Mode.java rename to src/main/java/io/github/dgroup/mbox4j/query/mode/Recent.java index 523856a..e98ed34 100644 --- a/src/main/java/io/github/dgroup/mbox4j/query/mode/Mode.java +++ b/src/main/java/io/github/dgroup/mbox4j/query/mode/Recent.java @@ -24,16 +24,20 @@ package io.github.dgroup.mbox4j.query.mode; +import io.github.dgroup.mbox4j.query.Mode; +import java.util.Collections; + /** - * The type of search mode within email folder. + * Find all recent emails within folder. * * @since 0.1.0 */ -public interface Mode { +public final class Recent extends ModeEnvelope { /** - * The name of type of search within email folder. - * @return The name of mode. + * Ctor. */ - String name(); + public Recent() { + super(Mode.RECENT, Collections.emptyMap()); + } } diff --git a/src/main/java/io/github/dgroup/mbox4j/query/mode/package-info.java b/src/main/java/io/github/dgroup/mbox4j/query/mode/package-info.java index 907dfc6..9afc9ff 100644 --- a/src/main/java/io/github/dgroup/mbox4j/query/mode/package-info.java +++ b/src/main/java/io/github/dgroup/mbox4j/query/mode/package-info.java @@ -23,8 +23,10 @@ */ /** - * The classes related to search procedure within the emails. + * The supported email search types. * * @since 0.1.0 + * @todo #/DEV Add documentation about package {@link io.github.dgroup.mbox4j.query.mode} + * to the readme.md. */ package io.github.dgroup.mbox4j.query.mode; diff --git a/src/test/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInboxTestIT.java b/src/test/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInboxTestIT.java index 4111de7..d7c5954 100644 --- a/src/test/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInboxTestIT.java +++ b/src/test/java/io/github/dgroup/mbox4j/inbox/javax/JavaxMailInboxTestIT.java @@ -26,20 +26,12 @@ import io.github.dgroup.mbox4j.EmailException; import io.github.dgroup.mbox4j.Msg; -import io.github.dgroup.mbox4j.Query; import io.github.dgroup.mbox4j.YandexIncomingSmtpProperties; -import io.github.dgroup.mbox4j.inbox.javax.search.mode.Modes; import io.github.dgroup.mbox4j.query.QueryOf; -import io.github.dgroup.mbox4j.query.mode.Mode; -import io.github.dgroup.mbox4j.query.mode.ModeOf; +import io.github.dgroup.mbox4j.query.mode.Range; import java.io.File; -import java.util.ArrayList; -import javax.mail.Folder; -import org.cactoos.Func; import org.cactoos.collection.Joined; import org.cactoos.collection.Mapped; -import org.cactoos.map.MapEntry; -import org.cactoos.map.MapOf; import org.hamcrest.Matchers; import org.junit.Test; import org.llorllale.cactoos.matchers.Assertion; @@ -96,24 +88,17 @@ public void attachments() { } /** - * Read range of emails from the dedicated SMTP server. + * Read the range of emails from the dedicated SMTP server. * @param start * @param end * @return The emails. * @throws EmailException In the case of connectivity issues. */ private Iterable read(final int start, final int end) throws EmailException { - final Mode mode = new ModeOf("first several emails"); - final Query query = new QueryOf("imaps", "INBOX", mode); - final Func> fnc = folder -> new ArrayList<>( - new Mapped<>( - new ToMsg(), folder.getMessages(start, end) - ) - ); return new JavaxMailInbox( - new YandexIncomingSmtpProperties(), - new Modes(new MapOf<>(new MapEntry<>(mode, fnc))) - ).read(query); + new YandexIncomingSmtpProperties() + ).read( + new QueryOf("imaps", "INBOX", new Range(start, end)) + ); } - }