From 77b39bd77c4264d89b8096e47dbc3bbe8222c167 Mon Sep 17 00:00:00 2001 From: David Denton Date: Wed, 3 Jan 2024 10:46:58 +0000 Subject: [PATCH] add objects --- .../dev/forkhandles/lens/AbstractLensProp.kt | 5 ++-- .../kotlin/dev/forkhandles/lens/MapWrapper.kt | 9 +++++++ .../dev/forkhandles/lens/PropertySet.kt | 4 --- .../dev/forkhandles/lens/MapWrapperTest.kt | 27 ++++++++++++------- 4 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt diff --git a/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractLensProp.kt b/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractLensProp.kt index d0459d9..c2f1449 100644 --- a/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractLensProp.kt +++ b/lens4k/src/main/kotlin/dev/forkhandles/lens/AbstractLensProp.kt @@ -16,9 +16,10 @@ abstract class AbstractLensProp( thisRef.existsFn(property.name) -> throw NoSuchElementException("Value for field <${property.name}> is null") else -> throw NoSuchElementException("Field <${property.name}> is missing") } - (property.returnType.jvmErasure == result.javaClass.kotlin) -> result as OUT + property.returnType.jvmErasure.isInstance(result) -> result as OUT - else -> throw NoSuchElementException("Value for field <${property.name}> is not a ${property.returnType.jvmErasure}") + else -> throw NoSuchElementException("Value for field <${property.name}> is not a ${property.returnType.jvmErasure} but ${result.javaClass.kotlin}") } } } + diff --git a/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt b/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt new file mode 100644 index 0000000..bb47c64 --- /dev/null +++ b/lens4k/src/main/kotlin/dev/forkhandles/lens/MapWrapper.kt @@ -0,0 +1,9 @@ +package dev.forkhandles.lens + +abstract class MapWrapper(private val map: Map) { + class Field : AbstractLensProp({ map.containsKey(it) }, { map[it] }) + class ListField(mapFn: (IN) -> OUT) : AbstractLensProp>({ map.containsKey(it) }, { + @Suppress("UNCHECKED_CAST") + (map[it] as List).map(mapFn) + }) +} diff --git a/lens4k/src/main/kotlin/dev/forkhandles/lens/PropertySet.kt b/lens4k/src/main/kotlin/dev/forkhandles/lens/PropertySet.kt index b384a0a..30cf1ab 100644 --- a/lens4k/src/main/kotlin/dev/forkhandles/lens/PropertySet.kt +++ b/lens4k/src/main/kotlin/dev/forkhandles/lens/PropertySet.kt @@ -30,7 +30,3 @@ object PropertySets { injector = { subject, value -> subject.toMutableMap().apply { this[propertyName] = value } } ) } - -abstract class MapWrapper(private val map: Map) { - class Primitive : AbstractLensProp({ map.containsKey(it) }, { map[it] }) -} diff --git a/lens4k/src/test/kotlin/dev/forkhandles/lens/MapWrapperTest.kt b/lens4k/src/test/kotlin/dev/forkhandles/lens/MapWrapperTest.kt index 0d39a05..890e2ae 100644 --- a/lens4k/src/test/kotlin/dev/forkhandles/lens/MapWrapperTest.kt +++ b/lens4k/src/test/kotlin/dev/forkhandles/lens/MapWrapperTest.kt @@ -8,14 +8,19 @@ import strikt.assertions.message class MapWrapperTest { + class SubMap(propertySet: Map) : MapWrapper(propertySet) { + val stringField by Field() + } + class MapBacked(propertySet: Map) : MapWrapper(propertySet) { - val stringField by Primitive() - val booleanField by Primitive() - val intField by Primitive() - val longField by Primitive() - val decimalField by Primitive() - val notAStringField by Primitive() - val noSuchField by Primitive() + val stringField by Field() + val booleanField by Field() + val intField by Field() + val longField by Field() + val decimalField by Field() + val notAStringField by Field() + val noSuchField by Field() + val listField by ListField(::SubMap) } @Test @@ -28,8 +33,9 @@ class MapWrapperTest { "longField" to Long.MAX_VALUE, "decimalField" to 1.1234, "notAStringField" to 123, - "objectField" to mapOf( - "stringField" to "string" + "listField" to listOf( + mapOf("stringField" to "string1"), + mapOf("stringField" to "string2"), ) ) ) @@ -39,7 +45,8 @@ class MapWrapperTest { expectThat(mapBacked.intField).isEqualTo(123) expectThat(mapBacked.longField).isEqualTo(Long.MAX_VALUE) expectThat(mapBacked.decimalField).isEqualTo(1.1234) - expectThrows { mapBacked.notAStringField }.message.isEqualTo("Value for field is not a class kotlin.String") + expectThat(mapBacked.listField.map { it.stringField }).isEqualTo(listOf("string1", "string2")) + expectThrows { mapBacked.notAStringField }.message.isEqualTo("Value for field is not a class kotlin.String but class kotlin.Int") expectThrows { mapBacked.noSuchField }.message.isEqualTo("Field is missing") } }