Return a nullable PostReply instead of an Optional
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 15 Oct 2017 11:06:10 +0000 (13:06 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 15 Oct 2017 11:06:10 +0000 (13:06 +0200)
18 files changed:
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.java
src/main/java/net/pterodactylus/sone/fcp/AbstractSoneCommand.java
src/main/kotlin/net/pterodactylus/sone/database/PostReplyProvider.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DeleteReplyAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetLikesAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetReplyAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/LikeAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/MarkAsKnownAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteReplyPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/MarkAsKnownPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/SearchPage.kt
src/test/java/net/pterodactylus/sone/database/memory/MemoryDatabaseTest.java
src/test/kotlin/net/pterodactylus/sone/fcp/DeleteReplyCommandTest.kt
src/test/kotlin/net/pterodactylus/sone/fcp/LikeReplyCommandTest.kt
src/test/kotlin/net/pterodactylus/sone/fcp/SoneCommandTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/TestObjects.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/WebPageTest.kt

index a2a400b..508d167 100644 (file)
@@ -459,8 +459,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        /**
         * {@inheritDoc}
         */
+       @Nullable
        @Override
-       public Optional<PostReply> getPostReply(String replyId) {
+       public PostReply getPostReply(String replyId) {
                return database.getPostReply(replyId);
        }
 
index 6f9d246..248592c 100644 (file)
@@ -38,6 +38,7 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import net.pterodactylus.sone.data.Album;
 import net.pterodactylus.sone.data.Image;
@@ -409,12 +410,12 @@ public class MemoryDatabase extends AbstractService implements Database {
        // POSTREPLYPROVIDER METHODS
        //
 
-       /** {@inheritDocs} */
+       @Nullable
        @Override
-       public Optional<PostReply> getPostReply(String id) {
+       public PostReply getPostReply(String id) {
                lock.readLock().lock();
                try {
-                       return fromNullable(allPostReplies.get(id));
+                       return allPostReplies.get(id);
                } finally {
                        lock.readLock().unlock();
                }
index 93b5d32..a47bde3 100644 (file)
@@ -210,11 +210,11 @@ public abstract class AbstractSoneCommand extends AbstractCommand {
        protected PostReply getReply(SimpleFieldSet simpleFieldSet, String parameterName) throws FcpException {
                try {
                        String replyId = simpleFieldSet.getString(parameterName);
-                       Optional<PostReply> reply = core.getPostReply(replyId);
-                       if (!reply.isPresent()) {
+                       PostReply reply = core.getPostReply(replyId);
+                       if (reply == null) {
                                throw new FcpException("Could not load reply from “" + replyId + "”.");
                        }
-                       return reply.get();
+                       return reply;
                } catch (FSParseException fspe1) {
                        throw new FcpException("Could not reply ID from “" + parameterName + "”.", fspe1);
                }
index 57e8df7..7e09017 100644 (file)
@@ -25,7 +25,7 @@ import net.pterodactylus.sone.data.PostReply
  */
 interface PostReplyProvider {
 
-       fun getPostReply(id: String): Optional<PostReply>
+       fun getPostReply(id: String): PostReply?
 
        /**
         * Returns all replies for the given post, order ascending by time.
index 2108daf..d01c077 100644 (file)
@@ -14,7 +14,7 @@ class DeleteReplyAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("delete
 
        override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
                        request.parameters["reply"]
-                                       .let(core::getPostReply)
+                                       ?.let(core::getPostReply)
                                        ?.let { reply ->
                                                reply.sone.isLocal.ifTrue {
                                                        createSuccessJsonObject().also {
index 335f269..cff9408 100644 (file)
@@ -25,7 +25,7 @@ class GetLikesAjaxPage(webInterface: WebInterface) : JsonPage("getLikes.ajax", w
                                                ?.toReply()
                                                ?: createErrorJsonObject("invalid-post-id")
                                "reply" -> request.parameters["reply"]
-                                               .let(core::getPostReply)
+                                               ?.let(core::getPostReply)
                                                ?.let(core::getLikes)
                                                ?.toReply()
                                                ?: createErrorJsonObject("invalid-reply-id")
index fc4b482..b02b85b 100644 (file)
@@ -19,7 +19,7 @@ class GetReplyAjaxPage(webInterface: WebInterface, private val template: Templat
 
        override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
                        request.parameters["reply"]
-                                       .let(core::getPostReply)
+                                       ?.let(core::getPostReply)
                                        ?.let { it.toJson(currentSone, request) }
                                        ?.let { replyJson ->
                                                createSuccessJsonObject().apply {
index 4257725..576bf90 100644 (file)
@@ -20,7 +20,7 @@ class LikeAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("like.ajax", w
                                                ?.let { createSuccessJsonObject() }
                                                ?: createErrorJsonObject("invalid-post-id")
                                "reply" -> request.parameters["reply"]
-                                               .let(core::getPostReply)
+                                               ?.let(core::getPostReply)
                                                ?.let { currentSone.addLikedReplyId(it.id) }
                                                ?.also { core.touchConfiguration() }
                                                ?.let { createSuccessJsonObject() }
index cca5cef..224007d 100644 (file)
@@ -18,7 +18,7 @@ class MarkAsKnownAjaxPage(webInterface: WebInterface) : JsonPage("markAsKnown.aj
        override fun createJsonObject(request: FreenetRequest) = when (request.parameters["type"]) {
                "sone" -> processIds(request, { core.getSone(it).asOptional() }, core::markSoneKnown)
                "post" -> processIds(request, core::getPost, core::markPostKnown)
-               "reply" -> processIds(request, core::getPostReply, core::markReplyKnown)
+               "reply" -> processIds(request, { core.getPostReply(it).asOptional() }, core::markReplyKnown)
                else -> createErrorJsonObject("invalid-type")
        }
 
index c67d620..ddaaf5e 100644 (file)
@@ -15,7 +15,7 @@ class DeleteReplyPage(template: Template, webInterface: WebInterface):
        override fun handleRequest(freenetRequest: FreenetRequest, templateContext: TemplateContext) {
                if (freenetRequest.isPOST) {
                        val replyId = freenetRequest.httpRequest.getPartAsStringFailsafe("reply", 36)
-                       val reply = webInterface.core.getPostReply(replyId).orNull() ?: throw RedirectException("noPermission.html")
+                       val reply = webInterface.core.getPostReply(replyId) ?: throw RedirectException("noPermission.html")
                        if (!reply.sone.isLocal) {
                                throw RedirectException("noPermission.html")
                        }
index bc96af5..31e70fc 100644 (file)
@@ -20,7 +20,7 @@ class MarkAsKnownPage(template: Template, webInterface: WebInterface):
                when (freenetRequest.parameters["type", 5]) {
                        "sone" -> ids.mapNotNull(webInterface.core::getSone).forEach(webInterface.core::markSoneKnown)
                        "post" -> ids.mapPresent(webInterface.core::getPost).forEach(webInterface.core::markPostKnown)
-                       "reply" -> ids.mapPresent(webInterface.core::getPostReply).forEach(webInterface.core::markReplyKnown)
+                       "reply" -> ids.mapNotNull(webInterface.core::getPostReply).forEach(webInterface.core::markReplyKnown)
                        else -> throw RedirectException("invalid.html")
                }
                throw RedirectException(freenetRequest.parameters["returnPage", 256]!!)
index 5f40238..d021dfb 100644 (file)
@@ -44,7 +44,7 @@ class SearchPage @JvmOverloads constructor(template: Template, webInterface: Web
                                when {
                                        word.removePrefix("sone://").let(webInterface.core::getSone) != null -> redirect("viewSone.html?sone=${word.removePrefix("sone://")}")
                                        word.removePrefix("post://").let(webInterface.core::getPost).isPresent -> redirect("viewPost.html?post=${word.removePrefix("post://")}")
-                                       word.removePrefix("reply://").let(webInterface.core::getPostReply).isPresent -> redirect("viewPost.html?post=${word.removePrefix("reply://").let(webInterface.core::getPostReply).get().postId}")
+                                       word.removePrefix("reply://").let(webInterface.core::getPostReply) != null -> redirect("viewPost.html?post=${word.removePrefix("reply://").let(webInterface.core::getPostReply)?.postId}")
                                        word.removePrefix("album://").let(webInterface.core::getAlbum) != null -> redirect("imageBrowser.html?album=${word.removePrefix("album://")}")
                                        word.removePrefix("image://").let { webInterface.core.getImage(it, false) } != null -> redirect("imageBrowser.html?image=${word.removePrefix("image://")}")
                                }
index 352b3b2..daa5e4d 100644 (file)
@@ -30,6 +30,7 @@ import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.emptyIterable;
+import static org.hamcrest.Matchers.nullValue;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -183,14 +184,13 @@ public class MemoryDatabaseTest {
                assertThat(memoryDatabase.getPost("post2").get(),
                                isPost(secondPost.getId(), 2000L, "post2", of(RECIPIENT_ID)));
                assertThat(memoryDatabase.getPost("post3").isPresent(), is(false));
-               assertThat(memoryDatabase.getPostReply("reply1").get(),
+               assertThat(memoryDatabase.getPostReply("reply1"),
                                isPostReply("reply1", "post1", 3000L, "reply1"));
-               assertThat(memoryDatabase.getPostReply("reply2").get(),
+               assertThat(memoryDatabase.getPostReply("reply2"),
                                isPostReply("reply2", "post2", 4000L, "reply2"));
-               assertThat(memoryDatabase.getPostReply("reply3").get(),
+               assertThat(memoryDatabase.getPostReply("reply3"),
                                isPostReply("reply3", "post1", 5000L, "reply3"));
-               assertThat(memoryDatabase.getPostReply("reply4").isPresent(),
-                               is(false));
+               assertThat(memoryDatabase.getPostReply("reply4"), nullValue());
                assertThat(memoryDatabase.getAlbum("album1").get(),
                                isAlbum("album1", null, "album1", "album-description1"));
                assertThat(memoryDatabase.getAlbum("album2").get(),
index 013b1c1..6920a33 100644 (file)
@@ -39,7 +39,7 @@ class DeleteReplyCommandTest : SoneCommandTest() {
        @Test
        fun `request with remote post reply parameter results in error response`() {
            parameters += "Reply" to "RemoteReplyId"
-               whenever(core.getPostReply("RemoteReplyId")).thenReturn(of(remotePostReply))
+               whenever(core.getPostReply("RemoteReplyId")).thenReturn(remotePostReply)
                val response = command.execute(parameters)
                assertThat(response.replyParameters["Message"], equalTo("Error"))
                assertThat(response.replyParameters["ErrorCode"], equalTo("401"))
@@ -48,7 +48,7 @@ class DeleteReplyCommandTest : SoneCommandTest() {
        @Test
        fun `request with local post reply parameter deletes reply`() {
            parameters += "Reply" to "RemoteReplyId"
-               whenever(core.getPostReply("RemoteReplyId")).thenReturn(of(localPostReply))
+               whenever(core.getPostReply("RemoteReplyId")).thenReturn(localPostReply)
                val response = command.execute(parameters)
                assertThat(response.replyParameters["Message"], equalTo("ReplyDeleted"))
                verify(core).deleteReply(localPostReply)
index 8705815..7b9256a 100644 (file)
@@ -24,7 +24,7 @@ class LikeReplyCommandTest : SoneCommandTest() {
 
        @Before
        fun setupRepliesAndSones() {
-               whenever(core.getPostReply("ReplyId")).thenReturn(reply.asOptional())
+               whenever(core.getPostReply("ReplyId")).thenReturn(reply)
                whenever(core.getSone("RemoteSoneId")).thenReturn(remoteSone)
                whenever(core.getSone("LocalSoneId")).thenReturn(localSone)
        }
index 6370acc..5397683 100644 (file)
@@ -40,7 +40,7 @@ abstract class SoneCommandTest {
        fun setupCore() {
                whenever(core.getSone(anyString())).thenReturn(null)
                whenever(core.getPost(anyString())).thenReturn(absent())
-               whenever(core.getPostReply(anyString())).thenReturn(absent())
+               whenever(core.getPostReply(anyString())).thenReturn(null)
        }
 
        protected fun createSone(id: String, name: String, firstName: String, lastName: String, time: Long) = mock<Sone>().apply {
index 96474ed..0dbbeaf 100644 (file)
@@ -96,7 +96,7 @@ open class TestObjects {
                whenever(core.getPost(ArgumentMatchers.anyString())).thenAnswer { (posts + newPosts)[it[0]].asOptional() }
                whenever(core.getLikes(ArgumentMatchers.any<Post>())).then { postLikes[it[0]] ?: emptySet<Sone>() }
                whenever(core.getLikes(ArgumentMatchers.any<PostReply>())).then { replyLikes[it[0]] ?: emptySet<Sone>() }
-               whenever(core.getPostReply(ArgumentMatchers.anyString())).then { replies[it[0]].asOptional() }
+               whenever(core.getPostReply(ArgumentMatchers.anyString())).then { replies[it[0]] }
                whenever(core.getAlbum(ArgumentMatchers.anyString())).then { albums[it[0]] }
                whenever(core.getImage(ArgumentMatchers.anyString())).then { images[it[0]] }
                whenever(core.getImage(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean())).then { images[it[0]] }
index 1bf75c0..2687963 100644 (file)
@@ -93,7 +93,7 @@ open class WebPageTest(pageSupplier: (Template, WebInterface) -> SoneTemplatePag
                whenever(core.localSones).then { localSones.values }
                whenever(core.getLocalSone(anyString())).then { localSones[it[0]] }
                whenever(core.getPost(anyString())).then { allPosts[it[0]].asOptional() }
-               whenever(core.getPostReply(anyString())).then { allPostReplies[it[0]].asOptional() }
+               whenever(core.getPostReply(anyString())).then { allPostReplies[it[0]] }
                whenever(core.getReplies(anyString())).then { perPostReplies[it[0]].asList() }
                whenever(core.getAlbum(anyString())).then { allAlbums[it[0]] }
                whenever(core.getImage(anyString())).then { allImages[it[0]]}