Use maps for JSON output.

This commit is contained in:
akwizgran
2018-09-21 18:15:29 +01:00
committed by Torsten Grote
parent cf033dc29d
commit bda52ea548
12 changed files with 157 additions and 218 deletions

View File

@@ -1,21 +1,13 @@
package org.briarproject.bramble.identity package org.briarproject.bramble.identity
import org.briarproject.bramble.api.identity.Author import org.briarproject.bramble.api.identity.Author
import javax.annotation.concurrent.Immutable
@Immutable fun Author.output() = mapOf(
data class OutputAuthor( "formatVersion" to formatVersion,
val id: ByteArray, "id" to id.bytes,
val name: String, "name" to name,
val publicKey: ByteArray "publicKey" to publicKey
) { )
constructor(author: Author) : this(
id = author.id.bytes,
name = author.name,
publicKey = author.publicKey
)
}
fun Author.output() = OutputAuthor(this)
fun Author.Status.output() = name.toLowerCase() fun Author.Status.output() = name.toLowerCase()

View File

@@ -23,12 +23,10 @@ internal class BlogControllerImpl
) : BlogController { ) : BlogController {
override fun listPosts(ctx: Context): Context { override fun listPosts(ctx: Context): Context {
val posts = blogManager.blogs.flatMap { blog -> val posts = blogManager.blogs
blogManager.getPostHeaders(blog.id).map { header -> .flatMap { blog -> blogManager.getPostHeaders(blog.id) }
val body = blogManager.getPostBody(header.id) .sortedBy { it.timeReceived }
header.output(body) .map { header -> header.output(blogManager.getPostBody(header.id)) }
}
}.sortedBy { it.timestampReceived }
return ctx.json(posts) return ctx.json(posts)
} }

View File

@@ -1,38 +1,20 @@
package org.briarproject.briar.headless.blogs package org.briarproject.briar.headless.blogs
import org.briarproject.bramble.identity.OutputAuthor
import org.briarproject.bramble.identity.output import org.briarproject.bramble.identity.output
import org.briarproject.briar.api.blog.BlogPostHeader import org.briarproject.briar.api.blog.BlogPostHeader
import org.briarproject.briar.api.blog.MessageType import org.briarproject.briar.api.blog.MessageType
import javax.annotation.concurrent.Immutable
@Immutable internal fun BlogPostHeader.output(body: String) = mapOf(
internal data class OutputBlogPost( "body" to body,
val body: String, "author" to author.output(),
val author: OutputAuthor, "authorStatus" to authorStatus.output(),
val authorStatus: String, "type" to type.output(),
val type: String, "id" to id.bytes,
val id: ByteArray, "parentId" to parentId?.bytes,
val parentId: ByteArray?, "read" to isRead,
val read: Boolean, "rssFeed" to isRssFeed,
val rssFeed: Boolean, "timestamp" to timestamp,
val timestamp: Long, "timestampReceived" to timeReceived
val timestampReceived: Long )
) {
internal constructor(header: BlogPostHeader, body: String) : this(
body = body,
author = OutputAuthor(header.author),
authorStatus = header.authorStatus.output(),
type = header.type.output(),
id = header.id.bytes,
parentId = header.parentId?.bytes,
read = header.isRead,
rssFeed = header.isRssFeed,
timestamp = header.timestamp,
timestampReceived = header.timeReceived
)
}
internal fun BlogPostHeader.output(body: String) = OutputBlogPost(this, body)
internal fun MessageType.output() = name.toLowerCase() internal fun MessageType.output() = name.toLowerCase()

View File

@@ -1,21 +1,10 @@
package org.briarproject.briar.headless.contact package org.briarproject.briar.headless.contact
import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.Contact
import org.briarproject.bramble.identity.OutputAuthor
import org.briarproject.bramble.identity.output import org.briarproject.bramble.identity.output
import javax.annotation.concurrent.Immutable
@Immutable internal fun Contact.output() = mapOf(
internal data class OutputContact( "contactId" to id.int,
val contactId: Int, "author" to author.output(),
val author: OutputAuthor, "verified" to isVerified
val verified: Boolean )
) {
internal constructor(c: Contact) : this(
contactId = c.id.int,
author = c.author.output(),
verified = c.isVerified
)
}
internal fun Contact.output() = OutputContact(this)

View File

@@ -1,19 +1,10 @@
package org.briarproject.briar.headless.forums package org.briarproject.briar.headless.forums
import org.briarproject.briar.api.forum.Forum import org.briarproject.briar.api.forum.Forum
import javax.annotation.concurrent.Immutable
@Immutable internal fun Forum.output() = mapOf(
internal data class OutputForum( "name" to name,
val name: String, "id" to id.bytes
val id: ByteArray )
) {
constructor(forum: Forum) : this(
name = forum.name,
id = forum.id.bytes
)
}
internal fun Forum.output() = OutputForum(this)
internal fun Collection<Forum>.output() = map { it.output() } internal fun Collection<Forum>.output() = map { it.output() }

View File

@@ -40,16 +40,18 @@ internal class MessagingControllerImpl
override fun list(ctx: Context): Context { override fun list(ctx: Context): Context {
val contact = getContact(ctx) val contact = getContact(ctx)
val messages = conversationManager.getMessageHeaders(contact.id).map { header -> val messages = conversationManager.getMessageHeaders(contact.id)
when (header) { .sortedBy { it.timestamp }
is PrivateRequest<*> -> header.output(contact.id) .map { header ->
is PrivateResponse -> header.output(contact.id) when (header) {
else -> { is PrivateRequest<*> -> header.output(contact.id)
val body = messagingManager.getMessageBody(header.id) is PrivateResponse -> header.output(contact.id)
header.output(contact.id, body) else -> {
val body = messagingManager.getMessageBody(header.id)
header.output(contact.id, body)
}
} }
} }
}.sortedBy { it.timestamp }
return ctx.json(messages) return ctx.json(messages)
} }

View File

@@ -3,56 +3,32 @@ package org.briarproject.briar.headless.messaging
import org.briarproject.bramble.api.contact.ContactId import org.briarproject.bramble.api.contact.ContactId
import org.briarproject.briar.api.messaging.PrivateMessage import org.briarproject.briar.api.messaging.PrivateMessage
import org.briarproject.briar.api.messaging.PrivateMessageHeader import org.briarproject.briar.api.messaging.PrivateMessageHeader
import javax.annotation.concurrent.Immutable
@Immutable internal fun PrivateMessageHeader.output(contactId: ContactId, body: String?): Map<String, Any> {
internal abstract class OutputPrivateMessage( val map: HashMap<String, Any> = hashMapOf(
protected open val iHeader: PrivateMessageHeader, "type" to "org.briarproject.briar.api.messaging.PrivateMessageHeader",
protected open val iContactId: ContactId, "contactId" to contactId.int,
open val body: String? "timestamp" to timestamp,
) { "read" to isRead,
"seen" to isSeen,
abstract val type: String "sent" to isSent,
val contactId: Int get() = iContactId.int "local" to isLocal,
val timestamp: Long get() = iHeader.timestamp "id" to id.bytes,
val read: Boolean get() = iHeader.isRead "groupId" to groupId.bytes
val seen: Boolean get() = iHeader.isSeen
val sent: Boolean get() = iHeader.isSent
val local: Boolean get() = iHeader.isLocal
val id: ByteArray get() = iHeader.id.bytes
val groupId: ByteArray get() = iHeader.groupId.bytes
}
@Immutable
internal data class OutputPrivateMessageHeader(
override val iHeader: PrivateMessageHeader,
override val iContactId: ContactId,
override val body: String?
) : OutputPrivateMessage(iHeader, iContactId, body) {
override val type = "org.briarproject.briar.api.messaging.PrivateMessageHeader"
/**
* Only meant for own [PrivateMessage]s directly after creation.
*/
internal constructor(m: PrivateMessage, contactId: ContactId, body: String) : this(
PrivateMessageHeader(
m.message.id,
m.message.groupId,
m.message.timestamp,
true,
true,
true,
true
), contactId, body
) )
if (body != null) map.put("body", body)
return map
} }
internal fun PrivateMessageHeader.output( internal fun PrivateMessage.output(contactId: ContactId, body: String) = mapOf(
contactId: ContactId, "type" to "org.briarproject.briar.api.messaging.PrivateMessageHeader",
body: String? "contactId" to contactId.int,
) = OutputPrivateMessageHeader(this, contactId, body) "timestamp" to message.timestamp,
"read" to true,
internal fun PrivateMessage.output(contactId: ContactId, body: String) = "seen" to true,
OutputPrivateMessageHeader(this, contactId, body) "sent" to true,
"local" to true,
"id" to message.id.bytes,
"groupId" to message.groupId.bytes,
"body" to body
)

View File

@@ -6,54 +6,56 @@ import org.briarproject.bramble.api.contact.ContactId
import org.briarproject.briar.api.blog.BlogInvitationRequest import org.briarproject.briar.api.blog.BlogInvitationRequest
import org.briarproject.briar.api.forum.ForumInvitationRequest import org.briarproject.briar.api.forum.ForumInvitationRequest
import org.briarproject.briar.api.introduction.IntroductionRequest import org.briarproject.briar.api.introduction.IntroductionRequest
import org.briarproject.briar.api.messaging.PrivateMessageHeader
import org.briarproject.briar.api.messaging.PrivateRequest import org.briarproject.briar.api.messaging.PrivateRequest
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest
import org.briarproject.briar.api.sharing.InvitationRequest import org.briarproject.briar.api.sharing.InvitationRequest
import javax.annotation.concurrent.Immutable
@Immutable internal fun PrivateRequest<*>.output(contactId: ContactId): Map<String, Any> {
internal abstract class OutputPrivateRequest(header: PrivateRequest<*>, contactId: ContactId) : val map: HashMap<String, Any> = hashMapOf(
OutputPrivateMessage(header, contactId, header.message) { "sessionId" to sessionId.bytes,
"name" to name,
val sessionId: ByteArray = header.sessionId.bytes "answered" to wasAnswered()
val name: String = header.name )
val answered = header.wasAnswered() map.putAll((this as PrivateMessageHeader).output(contactId, null))
return map
} }
@Immutable internal fun IntroductionRequest.output(contactId: ContactId): Map<String, Any> {
internal data class OutputIntroductionRequest( val map: HashMap<String, Any> = hashMapOf(
override val iHeader: IntroductionRequest, "type" to "org.briarproject.briar.api.introduction.IntroductionRequest",
override val iContactId: ContactId "alreadyContact" to isContact
) : OutputPrivateRequest(iHeader, iContactId) { )
map.putAll((this as PrivateRequest<*>).output(contactId))
override val type = "org.briarproject.briar.api.introduction.IntroductionRequest" return map
val alreadyContact get() = iHeader.isContact
} }
@Immutable internal fun InvitationRequest<*>.output(contactId : ContactId): Map<String, Any> {
internal data class OutputInvitationRequest( val map: HashMap<String, Any> = hashMapOf("canBeOpened" to canBeOpened())
override val iHeader: InvitationRequest<*>, map.putAll((this as PrivateRequest<*>).output(contactId))
override val iContactId: ContactId return map
) : OutputPrivateRequest(iHeader, iContactId) {
override val type = when (iHeader) {
is ForumInvitationRequest -> "org.briarproject.briar.api.forum.ForumInvitationRequest"
is BlogInvitationRequest -> "org.briarproject.briar.api.blog.BlogInvitationRequest"
is GroupInvitationRequest -> "org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest"
else -> throw AssertionError("Unknown InvitationRequest")
}
val canBeOpened get() = iHeader.canBeOpened()
} }
internal fun PrivateRequest<*>.output(contactId: ContactId): OutputPrivateMessage { internal fun BlogInvitationRequest.output(contactId : ContactId): Map<String, Any> {
return when (this) { val map: HashMap<String, Any> = hashMapOf(
is IntroductionRequest -> OutputIntroductionRequest(this, contactId) "type" to "org.briarproject.briar.api.blog.BlogInvitationRequest"
is InvitationRequest -> OutputInvitationRequest(this, contactId) )
else -> throw AssertionError("Unknown PrivateRequest") map.putAll((this as InvitationRequest<*>).output(contactId))
} return map
} }
internal fun IntroductionRequest.output(contactId: ContactId) = internal fun ForumInvitationRequest.output(contactId: ContactId): Map<String, Any> {
OutputIntroductionRequest(this, contactId) val map: HashMap<String, Any> = hashMapOf(
"type" to "org.briarproject.briar.api.forum.ForumInvitationRequest"
)
map.putAll((this as InvitationRequest<*>).output(contactId))
return map
}
internal fun GroupInvitationRequest.output(contactId : ContactId): Map<String, Any> {
val map: HashMap<String, Any> = hashMapOf(
"type" to "org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest"
)
map.putAll((this as InvitationRequest<*>).output(contactId))
return map
}

View File

@@ -7,49 +7,56 @@ import org.briarproject.bramble.identity.output
import org.briarproject.briar.api.blog.BlogInvitationResponse import org.briarproject.briar.api.blog.BlogInvitationResponse
import org.briarproject.briar.api.forum.ForumInvitationResponse import org.briarproject.briar.api.forum.ForumInvitationResponse
import org.briarproject.briar.api.introduction.IntroductionResponse import org.briarproject.briar.api.introduction.IntroductionResponse
import org.briarproject.briar.api.messaging.PrivateMessageHeader
import org.briarproject.briar.api.messaging.PrivateResponse import org.briarproject.briar.api.messaging.PrivateResponse
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse
import org.briarproject.briar.api.sharing.InvitationResponse import org.briarproject.briar.api.sharing.InvitationResponse
import javax.annotation.concurrent.Immutable
@Immutable internal fun PrivateResponse.output(contactId: ContactId): Map<String, Any> {
internal abstract class OutputPrivateResponse(header: PrivateResponse, contactId: ContactId) : val map: HashMap<String, Any> = hashMapOf(
OutputPrivateMessage(header, contactId, null) { "sessionId" to sessionId.bytes,
"accepted" to wasAccepted()
val sessionId: ByteArray = header.sessionId.bytes )
val accepted = header.wasAccepted() map.putAll((this as PrivateMessageHeader).output(contactId, null))
return map
} }
@Immutable internal fun IntroductionResponse.output(contactId: ContactId): Map<String, Any> {
internal data class OutputIntroductionResponse( val map: HashMap<String, Any> = hashMapOf(
override val iHeader: IntroductionResponse, "type" to "org.briarproject.briar.api.introduction.IntroductionResponse",
override val iContactId: ContactId "introducedAuthor" to introducedAuthor.output(),
) : OutputPrivateResponse(iHeader, iContactId) { "introducer" to isIntroducer
)
override val type = "org.briarproject.briar.api.introduction.IntroductionResponse" map.putAll((this as PrivateResponse).output(contactId))
val introducedAuthor get() = iHeader.introducedAuthor.output() return map
val introducer get() = iHeader.isIntroducer
} }
@Immutable internal fun InvitationResponse.output(contactId: ContactId): Map<String, Any> {
internal data class OutputInvitationResponse( val map: HashMap<String, Any> = hashMapOf("shareableId" to shareableId.bytes)
override val iHeader: InvitationResponse, map.putAll((this as PrivateResponse).output(contactId))
override val iContactId: ContactId return map
) : OutputPrivateResponse(iHeader, iContactId) {
override val type = when (iHeader) {
is ForumInvitationResponse -> "org.briarproject.briar.api.forum.ForumInvitationResponse"
is BlogInvitationResponse -> "org.briarproject.briar.api.blog.BlogInvitationResponse"
is GroupInvitationResponse -> "org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse"
else -> throw AssertionError("Unknown InvitationResponse")
}
val shareableId: ByteArray get() = iHeader.shareableId.bytes
} }
internal fun PrivateResponse.output(contactId: ContactId): OutputPrivateMessage { internal fun BlogInvitationResponse.output(contactId: ContactId): Map<String, Any> {
return when (this) { val map: HashMap<String, Any> = hashMapOf(
is IntroductionResponse -> OutputIntroductionResponse(this, contactId) "type" to "org.briarproject.briar.api.blog.BlogInvitationResponse"
is InvitationResponse -> OutputInvitationResponse(this, contactId) )
else -> throw AssertionError("Unknown PrivateResponse") map.putAll((this as InvitationResponse).output(contactId))
} return map
} }
internal fun ForumInvitationResponse.output(contactId: ContactId): Map<String, Any> {
val map: HashMap<String, Any> = hashMapOf(
"type" to "org.briarproject.briar.api.blog.BlogInvitationResponse"
)
map.putAll((this as InvitationResponse).output(contactId))
return map
}
internal fun GroupInvitationResponse.output(contactId: ContactId): Map<String, Any> {
val map: HashMap<String, Any> = hashMapOf(
"type" to "org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse"
)
map.putAll((this as InvitationResponse).output(contactId))
return map
}

View File

@@ -101,7 +101,7 @@ internal class BlogControllerTest : ControllerTest() {
fun testEmptyList() { fun testEmptyList() {
every { blogManager.blogs } returns listOf(blog) every { blogManager.blogs } returns listOf(blog)
every { blogManager.getPostHeaders(group.id) } returns emptyList() every { blogManager.getPostHeaders(group.id) } returns emptyList()
every { ctx.json(emptyList<OutputBlogPost>()) } returns ctx every { ctx.json(emptyList<Any>()) } returns ctx
controller.listPosts(ctx) controller.listPosts(ctx)
} }

View File

@@ -14,7 +14,7 @@ internal class ContactControllerTest : ControllerTest() {
@Test @Test
fun testEmptyContactList() { fun testEmptyContactList() {
every { contactManager.activeContacts } returns emptyList<Contact>() every { contactManager.activeContacts } returns emptyList<Contact>()
every { ctx.json(emptyList<OutputContact>()) } returns ctx every { ctx.json(emptyList<Any>()) } returns ctx
controller.list(ctx) controller.list(ctx)
} }

View File

@@ -55,7 +55,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
every { ctx.pathParam("contactId") } returns contact.id.int.toString() every { ctx.pathParam("contactId") } returns contact.id.int.toString()
every { contactManager.getContact(contact.id) } returns contact every { contactManager.getContact(contact.id) } returns contact
every { conversationManager.getMessageHeaders(contact.id) } returns emptyList<PrivateMessageHeader>() every { conversationManager.getMessageHeaders(contact.id) } returns emptyList<PrivateMessageHeader>()
every { ctx.json(emptyList<OutputPrivateMessageHeader>()) } returns ctx every { ctx.json(emptyList<Any>()) } returns ctx
controller.list(ctx) controller.list(ctx)
} }
@@ -73,7 +73,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
@Test @Test
fun write() { fun write() {
val privateMessage = PrivateMessage(message) val privateMessage = PrivateMessage(message)
val slot = CapturingSlot<OutputPrivateMessageHeader>() val slot = CapturingSlot<Map<String, Any>>()
expectGetContact() expectGetContact()
every { ctx.formParam("text") } returns body every { ctx.formParam("text") } returns body
@@ -92,9 +92,9 @@ internal class MessagingControllerImplTest : ControllerTest() {
controller.write(ctx) controller.write(ctx)
val output = slot.captured val output = slot.captured
assertEquals(contact.id.int, output.contactId) assertEquals(contact.id.int, output.get("contactId"))
assertEquals(body, output.body) assertEquals(body, output.get("body"))
assertEquals(message.id.bytes, output.id) assertEquals(message.id.bytes, output.get("id"))
} }
@Test @Test