diff --git a/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractWrapper.kt b/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractWrapper.kt index 0a8e26a..64ce529 100644 --- a/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractWrapper.kt +++ b/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractWrapper.kt @@ -1,2 +1,19 @@ -package dev.forkhandles.lens +package dev.forkhandles.lens +@Suppress("UNCHECKED_CAST") +abstract class AbstractWrapper( + private val contents: CONTENT, + existsFn: (CONTENT, String) -> Boolean, + getFn: (CONTENT, String) -> Any? +) { + private val exists: AbstractWrapper.(String) -> Boolean = { existsFn(contents, it) } + private val get: AbstractWrapper.(String) -> Any? = { getFn(contents, it) } + + inner class Field : LensProp, OUT>(exists, get) + + inner class ListField(mapFn: (IN) -> OUT) : + LensProp, List>(exists, { (get(it) as List).map(mapFn) }) + + inner class ObjectField>(mapFn: (CONTENT) -> OUT) : + LensProp, OUT>(exists, { mapFn(get(it) as CONTENT) }) +} diff --git a/lens4k/src/main/kotlin/dev/forkhandles/lens/JacksonWrapper.kt b/lens4k/src/main/kotlin/dev/forkhandles/lens/JacksonWrapper.kt index 0a8e26a..7941020 100644 --- a/lens4k/src/main/kotlin/dev/forkhandles/lens/JacksonWrapper.kt +++ b/lens4k/src/main/kotlin/dev/forkhandles/lens/JacksonWrapper.kt @@ -1,2 +1,28 @@ -package dev.forkhandles.lens +package dev.forkhandles.lens +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.* + +abstract class JacksonWrapper(node: JsonNode) : + AbstractWrapper( + node, + { content, it -> content.has(it) }, + { content, it -> content[it]?.let(::asValue) } + ) { + + companion object { + private fun asValue(jsonNode: JsonNode): Any? = when (jsonNode) { + is BooleanNode -> jsonNode.booleanValue() + is IntNode -> jsonNode.intValue() + is LongNode -> jsonNode.longValue() + is DecimalNode -> jsonNode.decimalValue() + is DoubleNode -> jsonNode.doubleValue() + is TextNode -> jsonNode.textValue() + is ArrayNode -> jsonNode.map { asValue(it) } + is ObjectNode -> jsonNode + is NullNode -> null + else -> error("Invalid node type $jsonNode") + } + + } +} diff --git a/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt b/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt index 8f16337..d200f01 100644 --- a/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt +++ b/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt @@ -1,27 +1,6 @@ package dev.forkhandles.lens -import com.fasterxml.jackson.databind.JsonNode - -@Suppress("UNCHECKED_CAST") -abstract class AbstractWrapper( - private val contents: CONTENT, - existsFn: CONTENT.(String) -> Boolean, - getFn: CONTENT.(String) -> Any? -) { - private val exists: AbstractWrapper.(String) -> Boolean = { contents.existsFn(it) } - private val get: AbstractWrapper.(String) -> Any? = { contents.getFn(it) } - - inner class Field : LensProp, OUT>(exists, get) - - inner class ListField(mapFn: (IN) -> OUT) : - LensProp, List>(exists, { (get(it) as List).map(mapFn) }) - - inner class ObjectField>(mapFn: (CONTENT) -> OUT) : - LensProp, OUT>(exists, { mapFn(get(it) as CONTENT) }) -} - abstract class MapWrapper(map: Map) : - AbstractWrapper>(map, { map.containsKey(it) }, { map[it] }) + AbstractWrapper>(map, { content, it -> content.containsKey(it) }, { content, it -> content[it] }) + -abstract class JacksonWrapper(node: JsonNode) : - AbstractWrapper(node, { node.has(it) }, { node[it] }) diff --git a/lens4k/src/test/kotlin/dev/forkhandles/lens/JacksonWrapperTest.kt b/lens4k/src/test/kotlin/dev/forkhandles/lens/JacksonWrapperTest.kt index 0a4b144..5a167b0 100644 --- a/lens4k/src/test/kotlin/dev/forkhandles/lens/JacksonWrapperTest.kt +++ b/lens4k/src/test/kotlin/dev/forkhandles/lens/JacksonWrapperTest.kt @@ -29,24 +29,26 @@ class JacksonWrapperTest { @Test fun `can get values from properties`() { + val map = mapOf( + "stringField" to "string", + "booleanField" to true, + "intField" to 123, + "longField" to Long.MAX_VALUE, + "decimalField" to 1.1234, + "notAStringField" to 123, + "listField" to listOf( + mapOf("stringField" to "string1"), + mapOf("stringField" to "string2"), + ), + "listField2" to listOf("string1", "string2"), + "objectField" to mapOf( + "stringField" to "string" + ) + ) + val mapBacked = NodeBacked( ObjectMapper().valueToTree( - mapOf( - "stringField" to "string", - "booleanField" to true, - "intField" to 123, - "longField" to Long.MAX_VALUE, - "decimalField" to 1.1234, - "notAStringField" to 123, - "listField" to listOf( - mapOf("stringField" to "string1"), - mapOf("stringField" to "string2"), - ), - "listField2" to listOf("string1", "string2"), - "objectField" to mapOf( - "stringField" to "string" - ) - ) + map ) )