Skip to content

Commit

Permalink
Improved Json API
Browse files Browse the repository at this point in the history
  • Loading branch information
prange committed May 8, 2019
1 parent e91fe37 commit 88f9587
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 3 deletions.
12 changes: 12 additions & 0 deletions niagara-data/src/main/kotlin/org/kantega/niagara/data/monoid.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.kantega.niagara.data

interface Monoid<A>{

fun zero():A

fun append(one:A,other:A):A

fun mappend(one:A,other:A) =
append(one,other)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.kantega.niagara.data

typealias Semigroup<A> = (A,A)->A
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.kantega.niagara.json

import io.vavr.collection.List
import org.kantega.niagara.data.Monoid
import org.kantega.niagara.data.NonEmptyList
import org.kantega.niagara.data.Semigroup


sealed class JsonResult<out A> {
Expand Down Expand Up @@ -74,17 +77,21 @@ fun <A, B> jLift(f: (A) -> B) =
jOk(f)

infix fun <A> JsonResult<A>.getOrElse(a: A): A =
this.fold({ a }, { c -> c })
this.fold({ a }, { it })

infix fun <A> JsonResult<A>.getOrElse(f: (NonEmptyList<String>) -> A): A =
this.fold({ f(it) }, { c -> c })
this.fold({ f(it) }, { it })

infix fun <A> JsonResult<A>.getOrElseThrow(f: (NonEmptyList<String>) -> Throwable): A =
this.fold({ nel -> throw f(nel) }, { it })

infix fun <A> JsonResult<A>.orElse(a: JsonResult<A>): JsonResult<A> =
this.fold({ a }, { this })

infix fun <A> JsonResult<A>.orElse(f: (NonEmptyList<String>) -> JsonResult<A>): JsonResult<A> =
this.fold({ nel -> f(nel) }, { this })


fun JsonResult<JsonValue>.field(path: String): JsonResult<JsonValue> =
this.field(JsonPath(path))

Expand All @@ -94,8 +101,43 @@ fun JsonResult<JsonValue>.field(path: JsonPath): JsonResult<JsonValue> =
fun JsonResult<JsonValue>.asArray(): JsonResult<JsonArray> =
this.bind { v -> v.asArray() }

fun JsonResult<JsonArray>.mapJsonArray(f: (JsonValue) -> JsonResult<JsonValue>): JsonResult<JsonArray> =
this.bind { array ->
array.a.map(f).sequence().map { JsonArray(it) }
}

fun <A> List<JsonResult<A>>.sequence(): JsonResult<List<A>> =
this.foldLeft(
JsonResult.success(List.empty<A>()),
{ accum, elem ->
accum.fold(
{ accumFail ->
elem.fold(
{ fail -> JsonResult.fail(accumFail + fail) },
{ JsonResult.fail(accumFail) })
},
{ list ->
elem.fold(
{ fail -> JsonResult.fail(fail) },
{ value -> JsonResult.success(list.append(value)) })
})
}
)

fun JsonResult<JsonValue>.asString(): JsonResult<String> =
this.bind { it.asString() }

fun JsonResult<JsonValue>.asInt(): JsonResult<Int> =
this.bind { it.asNumber() }.map { bd -> bd.toInt() }
this.bind { it.asNumber() }.map { bd -> bd.toInt() }

data class JsonResultSemigroup<A>(val aSemigroup: Semigroup<A>) : Semigroup<JsonResult<A>> {
override fun invoke(p1: JsonResult<A>, p2: JsonResult<A>): JsonResult<A> {
return when {
p1 is JsonSuccess && p2 is JsonSuccess -> jOk(aSemigroup(p1.a, p2.a))
p1 is JsonFail && p2 is JsonFail -> JsonResult.fail(p1.failNel + p2.failNel)
p1 is JsonFail && p2 is JsonSuccess -> JsonResult.fail(p1.failNel)
p1 is JsonSuccess && p2 is JsonFail -> JsonResult.fail(p2.failNel)
else -> throw Error("unreachable code")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ data class JsonObject(val m: TreeMap<String,JsonValue>) : JsonValue {
}

data class JsonArray(val a: List<JsonValue>) : JsonValue {

fun update(f:(List<JsonValue>)->List<JsonValue>) =
copy(a = f(a))

override fun asArray(): JsonResult<JsonArray> =
JsonResult.success(this)

Expand Down

0 comments on commit 88f9587

Please sign in to comment.