From f049280a40ddf05f02400e7f0d93a24dea4545c2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sat, 22 Feb 2020 23:37:38 +0100 Subject: [PATCH] =?utf8?q?=F0=9F=8E=A8=20Replace=20reply=20comparator=20wi?= =?utf8?q?th=20Kotlin=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../net/pterodactylus/sone/core/SoneInserter.java | 3 +- .../java/net/pterodactylus/sone/data/Reply.java | 13 ------ .../net/pterodactylus/sone/data/impl/SoneImpl.java | 3 +- .../kotlin/net/pterodactylus/sone/data/Reply.kt | 27 ++++++++++++ .../sone/database/memory/MemoryDatabase.kt | 6 +-- .../net/pterodactylus/sone/data/ReplyTest.kt | 50 ++++++++++++++++++++++ .../kotlin/net/pterodactylus/sone/test/Mocks.kt | 4 +- 7 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 src/main/kotlin/net/pterodactylus/sone/data/Reply.kt create mode 100644 src/test/kotlin/net/pterodactylus/sone/data/ReplyTest.kt diff --git a/src/main/java/net/pterodactylus/sone/core/SoneInserter.java b/src/main/java/net/pterodactylus/sone/core/SoneInserter.java index ffbed4d..670b2c8 100644 --- a/src/main/java/net/pterodactylus/sone/core/SoneInserter.java +++ b/src/main/java/net/pterodactylus/sone/core/SoneInserter.java @@ -23,6 +23,7 @@ import static java.util.concurrent.TimeUnit.*; import static java.util.logging.Logger.getLogger; import static java.util.stream.Collectors.toList; import static net.pterodactylus.sone.data.PostKt.newestPostFirst; +import static net.pterodactylus.sone.data.ReplyKt.newestReplyFirst; import java.io.*; import java.nio.charset.Charset; @@ -310,7 +311,7 @@ public class SoneInserter extends AbstractService { soneProperties.put("time", currentTimeMillis()); soneProperties.put("profile", sone.getProfile()); soneProperties.put("posts", Ordering.from(newestPostFirst()).sortedCopy(sone.getPosts())); - soneProperties.put("replies", Ordering.from(Reply.TIME_COMPARATOR).reverse().sortedCopy(sone.getReplies())); + soneProperties.put("replies", Ordering.from(newestReplyFirst()).sortedCopy(sone.getReplies())); soneProperties.put("likedPostIds", new HashSet<>(sone.getLikedPostIds())); soneProperties.put("likedReplyIds", new HashSet<>(sone.getLikedReplyIds())); soneProperties.put("albums", SoneKt.getAllAlbums(sone).stream().filter(AlbumKt.notEmpty()::invoke).collect(toList())); diff --git a/src/main/java/net/pterodactylus/sone/data/Reply.java b/src/main/java/net/pterodactylus/sone/data/Reply.java index 120575e..705b1e4 100644 --- a/src/main/java/net/pterodactylus/sone/data/Reply.java +++ b/src/main/java/net/pterodactylus/sone/data/Reply.java @@ -29,19 +29,6 @@ import com.google.common.base.Predicate; */ public interface Reply> extends Identified { - /** Comparator that sorts replies ascending by time. */ - public static final Comparator> TIME_COMPARATOR = new Comparator>() { - - /** - * {@inheritDoc} - */ - @Override - public int compare(Reply leftReply, Reply rightReply) { - return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, leftReply.getTime() - rightReply.getTime())); - } - - }; - /** Filter for replies with timestamps from the future. */ public static final Predicate> FUTURE_REPLY_FILTER = new Predicate>() { diff --git a/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java b/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java index 9baaba9..a197c46 100644 --- a/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java +++ b/src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java @@ -22,6 +22,7 @@ import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.logging.Logger.getLogger; import static net.pterodactylus.sone.data.PostKt.newestPostFirst; +import static net.pterodactylus.sone.data.ReplyKt.newestReplyFirst; import static net.pterodactylus.sone.data.SoneKt.*; import java.net.MalformedURLException; @@ -626,7 +627,7 @@ public class SoneImpl implements Sone { hash.putString(")", UTF_8); List replies = new ArrayList<>(getReplies()); - Collections.sort(replies, Reply.TIME_COMPARATOR); + replies.sort(newestReplyFirst().reversed()); hash.putString("Replies(", UTF_8); for (PostReply reply : replies) { hash.putString("Reply(", UTF_8).putString(reply.getId(), UTF_8).putString(")", UTF_8); diff --git a/src/main/kotlin/net/pterodactylus/sone/data/Reply.kt b/src/main/kotlin/net/pterodactylus/sone/data/Reply.kt new file mode 100644 index 0000000..9a3ec64 --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/sone/data/Reply.kt @@ -0,0 +1,27 @@ +/** + * Sone - Reply.kt - Copyright © 2020 David ‘Bombe’ Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.pterodactylus.sone.data + +import java.util.Comparator.comparing + +/** + * Comparator that orders replies by their time, newest replies first. + */ +@get:JvmName("newestReplyFirst") +val newestReplyFirst: Comparator> = + comparing(Reply<*>::getTime).reversed() diff --git a/src/main/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabase.kt b/src/main/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabase.kt index 5c32486..e943b38 100644 --- a/src/main/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabase.kt +++ b/src/main/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabase.kt @@ -28,12 +28,12 @@ import net.pterodactylus.sone.data.Album import net.pterodactylus.sone.data.Image import net.pterodactylus.sone.data.Post import net.pterodactylus.sone.data.PostReply -import net.pterodactylus.sone.data.Reply.TIME_COMPARATOR import net.pterodactylus.sone.data.Sone import net.pterodactylus.sone.data.allAlbums import net.pterodactylus.sone.data.allImages import net.pterodactylus.sone.data.impl.AlbumBuilderImpl import net.pterodactylus.sone.data.impl.ImageBuilderImpl +import net.pterodactylus.sone.data.newestReplyFirst import net.pterodactylus.sone.database.AlbumBuilder import net.pterodactylus.sone.database.Database import net.pterodactylus.sone.database.DatabaseException @@ -62,7 +62,7 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio private val sonePosts: Multimap = HashMultimap.create() private val knownPosts = mutableSetOf() private val allPostReplies = mutableMapOf() - private val sonePostReplies: Multimap = TreeMultimap.create(Comparator { leftString, rightString -> leftString.compareTo(rightString) }, TIME_COMPARATOR) + private val sonePostReplies: Multimap = TreeMultimap.create(Comparator { leftString, rightString -> leftString.compareTo(rightString) }, newestReplyFirst) private val knownPostReplies = mutableSetOf() private val allAlbums = mutableMapOf() private val soneAlbums: Multimap = HashMultimap.create() @@ -227,7 +227,7 @@ class MemoryDatabase @Inject constructor(private val configuration: Configuratio readLock.withLock { allPostReplies.values .filter { it.postId == postId } - .sortedWith(TIME_COMPARATOR) + .sortedWith(newestReplyFirst.reversed()) } override fun newPostReplyBuilder(): PostReplyBuilder = diff --git a/src/test/kotlin/net/pterodactylus/sone/data/ReplyTest.kt b/src/test/kotlin/net/pterodactylus/sone/data/ReplyTest.kt new file mode 100644 index 0000000..3289b7d --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/sone/data/ReplyTest.kt @@ -0,0 +1,50 @@ +/** + * Sone - ReplyTest.kt - Copyright © 2020 David ‘Bombe’ Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.pterodactylus.sone.data + +import net.pterodactylus.sone.test.emptyPostReply +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.greaterThan +import org.hamcrest.Matchers.lessThan +import kotlin.test.Test + +class ReplyTest { + + @Test + fun `newestReplyFirst comparator returns less-than 0 is first reply is newer than second`() { + val newerReply = emptyPostReply(time = 2000) + val olderReply = emptyPostReply(time = 1000) + assertThat(newestReplyFirst.compare(newerReply, olderReply), lessThan(0)) + } + + @Test + fun `newestReplyFirst comparator returns greater-than 0 is first reply is older than second`() { + val newerReply = emptyPostReply(time = 2000) + val olderReply = emptyPostReply(time = 1000) + assertThat(newestReplyFirst.compare(olderReply, newerReply), greaterThan(0)) + } + + @Test + fun `newestReplyFirst comparator returns 0 is first and second reply have same age`() { + val reply1 = emptyPostReply(time = 1000) + val reply2 = emptyPostReply(time = 1000) + assertThat(newestReplyFirst.compare(reply1, reply2), equalTo(0)) + } + +} diff --git a/src/test/kotlin/net/pterodactylus/sone/test/Mocks.kt b/src/test/kotlin/net/pterodactylus/sone/test/Mocks.kt index 17eae9a..ae2ecd6 100644 --- a/src/test/kotlin/net/pterodactylus/sone/test/Mocks.kt +++ b/src/test/kotlin/net/pterodactylus/sone/test/Mocks.kt @@ -52,12 +52,12 @@ fun createPost(text: String = "", sone: Sone = remoteSone1, known: Boolean = fal } } -fun emptyPostReply(text: String = "", post: Post? = createPost(), sone: Sone = remoteSone1, known: Boolean = false) = object : PostReply { +fun emptyPostReply(text: String = "", post: Post? = createPost(), sone: Sone = remoteSone1, known: Boolean = false, time: Long = 1) = object : PostReply { override val id = "reply-id" override fun getSone() = sone override fun getPostId() = post!!.id override fun getPost(): Optional = Optional.fromNullable(post) - override fun getTime() = 1L + override fun getTime() = time override fun getText() = text override fun isKnown() = known override fun setKnown(known: Boolean): PostReply = this -- 2.7.4