メインコンテンツへスキップ

ActivityStreamsをKotlinでいい感じに扱いたい(DSL編)

·129 文字·1 分
技術 ActivityPub Kotlin ActivityStreams ActivityVocabulary
目次

前回(ActivityStreamsをKotlinでいい感じに扱いたい(デシリアライズ編) · usbharu - blog)デシリアライズの実装をした際にシリアライズの部分も作ってしまっていたのでDSLのついでに紹介します。

シリアライズ
#

シリアライズというかマッピングのほうが正しいような気もする

usbharu/activity-streams-serialization at 00dc4f7939655fb9a1c4276016040821569e4f9a https://github.com/usbharu/activity-streams-serialization/tree/00dc4f7939655fb9a1c4276016040821569e4f9a

(注) CollectionはKotlinのCollectionではなくて独自のCollection

    var replies: Collection?
        get() = replies()
        set(value) {
            jsonObject.setOrRemove(Properties.REPLIES, value?.json)
        }

    fun Object?.replies(objectFactory: ObjectFactory? = this?.objectFactory): Collection? {
    if (this == null) {
        return null
    }
    requireNotNull(objectFactory)
    val jsonNode = jsonObject.obtain(Properties.REPLIES)?.asArray()?.firstOrNull() ?: return null
    require(jsonNode.isObject)
    return objectFactory.create(jsonNode) as Collection
}

シリアライズの方もデシリアライズと同じで、SetterでJsonNodeを直接弄っています。

DSL
#

テストがすっげぇ~~~面倒なのでDSLを作り始めました。

DSL

        val object1 = JsonLdBuilder().Note {
            attachment {
                listOf(
                    Image {
                        content("This is what he looks like.")
                        url("http://example.org/cat.jpeg")
                    })
            }
            name("Have you seen my cat?")
        }

こんな感じでオブジェクトを組み立てることができます。attachmentのlistOfをなくせるように作ることも考えたんですが、仕組みが複雑になる割にメリット無いのでやめました。

KotlinでDSL作るのって簡単そうに見えて意外とややこしいですよね

実装
#

オブジェクトの作成

class JsonLdBuilder(var objectFactory: ObjectFactory = DefaultObjectFactory) {
    fun Object(block: ObjectBuilder.() -> Unit = {}): Object {
        val objectBuilder = ObjectBuilder(objectFactory, this)
        objectBuilder.block()
        return objectBuilder.Object
    }

プロパティの設定

    fun attachment(objectOrLink: ObjectOrLink?): ObjectBuilder {
        Object.attachment += objectOrLink ?: return this
        return this
    }