Skip to content

Commit

Permalink
Undo changes to mutability as the original implementation of MapBacke…
Browse files Browse the repository at this point in the history
…d was broken for sub objects
  • Loading branch information
daviddenton committed Apr 24, 2024
1 parent 2ba5428 commit f15f51c
Show file tree
Hide file tree
Showing 9 changed files with 25 additions and 21 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
This list is not intended to be all-encompassing - it will document major and breaking API changes with their rationale
when appropriate:

### v2.18.0.0
- **data4k** Make DataContainer contents mutable as chaining does not work otherwise.
- **data4k** Added updateWith() method to DataContainer to allow making a update of objects with an updated field

### v2.17.0.0
- **data4k** [Possible Break] DataContainers make a copy of their content data on construction.
- **data4k** Added copy() method to DataContainer to allow making a copy of objects with an updated field
Expand Down
6 changes: 3 additions & 3 deletions data4k/src/main/kotlin/dev/forkhandles/data/DataContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ abstract class DataContainer<DATA>(
}

/**
* Make a copy of this container with the given property updated to the given value
* Update container with the given property updated to the given value
*/
inline fun <reified NEXT : DataContainer<DATA>, PROP> copy(property: KProperty1<NEXT, PROP>, value: PROP): NEXT {
inline fun <reified NEXT : DataContainer<DATA>, PROP> updateWith(property: KProperty1<NEXT, PROP>, value: PROP) {
property.isAccessible = true
val newContainer = NEXT::class.constructors.first().call(unwrap())
return newContainer.also {
newContainer.also {
@Suppress("UNCHECKED_CAST")
(property.getDelegate(it) as ReadWriteProperty<NEXT, PROP>).setValue(it, property, value)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import java.math.BigInteger
*/
open class JsonNodeDataContainer(input: JsonNode) :
DataContainer<JsonNode>(
input.deepCopy(),
input,
{ content, it -> content.has(it) },
{ content, it -> content[it]?.let(::nodeToValue) },
{ node, name, value ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package dev.forkhandles.data
/**
* Map-based implementation of the DataContainer
*/
open class MapDataContainer(input: Map<String, Any?> = emptyMap()) :
DataContainer<MutableMap<String, Any?>>(input.toMutableMap(), { content, it -> content.containsKey(it) },
open class MapDataContainer(input: MutableMap<String, Any?> = mutableMapOf()) :
DataContainer<MutableMap<String, Any?>>(input, { content, it -> content.containsKey(it) },
{ content, it -> content[it] },
{ map, name, value -> map[name] = value }
)
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,7 @@ abstract class DataContainerContract<C : ChildFields<G>, G : GrandchildFields, C
prop.set(value)
expectThat(prop.get()).isEqualTo(value)
}

@Test
abstract fun `can update an arbitrary value`(approver: Approver)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"stringValue":"123"}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import dev.forkhandles.data.JsonNodeDataContainer
import dev.forkhandles.lens.ContainerMeta.bar
import dev.forkhandles.lens.ContainerMeta.foo
import org.junit.jupiter.api.Test
import strikt.api.expectThat
import strikt.assertions.isEqualTo
import java.math.BigDecimal
import java.math.BigInteger

Expand Down Expand Up @@ -72,10 +70,9 @@ class JsonNodeDataContainerTest : DataContainerContract<ChildNode, GrandchildNod
GrandchildNode(data(input))

@Test
fun `can update an arbitrary value by copy`(approver: Approver) {
override fun `can update an arbitrary value`(approver: Approver) {
val input = childContainer(emptyMap())
val updated = input.copy(TopNode::stringValue, StringType.of("123"))
expectThat(input).isEqualTo(childContainer(emptyMap()))
approver.assertApproved(updated.toString())
input.updateWith(TopNode::stringValue, StringType.of("123"))
approver.assertApproved(input.toString())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{stringValue=123}
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@ import dev.forkhandles.data.MapDataContainer
import dev.forkhandles.lens.ContainerMeta.bar
import dev.forkhandles.lens.ContainerMeta.foo
import org.junit.jupiter.api.Test
import strikt.api.expectThat
import strikt.assertions.isEqualTo
import java.math.BigDecimal
import java.math.BigInteger

class GrandchildMap(propertySet: Map<String, Any?>) : MapDataContainer(propertySet), GrandchildFields {
class GrandchildMap(propertySet: MutableMap<String, Any?>) : MapDataContainer(propertySet), GrandchildFields {
override var long by required<Long>()
}

class ChildMap(propertySet: Map<String, Any?>) : MapDataContainer(propertySet), ChildFields<GrandchildMap> {
class ChildMap(propertySet: MutableMap<String, Any?>) : MapDataContainer(propertySet), ChildFields<GrandchildMap> {
override var string by required<String>()
override var noSuch by required<String>()
override var grandchild by requiredObj(::GrandchildMap)
}

class MapBacked(map: Map<String, Any?>) : MapDataContainer(map), MainClassFields<ChildMap, GrandchildMap, MutableMap<String, Any?>> {
class MapBacked(map: MutableMap<String, Any?>) : MapDataContainer(map),
MainClassFields<ChildMap, GrandchildMap, MutableMap<String, Any?>> {
override var standardField = "foobar"
override var string by required<String>(foo, bar)
override var boolean by required<Boolean>(foo, bar)
Expand Down Expand Up @@ -67,10 +66,9 @@ class MapDataContainerTest : DataContainerContract<ChildMap, GrandchildMap, Muta
override fun grandchildContainer(input: Map<String, Any?>) = GrandchildMap(data(input))

@Test
fun `can update an arbitrary value by copy`(approver: Approver) {
override fun `can update an arbitrary value`(approver: Approver) {
val input = childContainer(emptyMap())
val updated = input.copy(MapBacked::stringValue, StringType.of("123"))
expectThat(input).isEqualTo(childContainer(emptyMap()))
approver.assertApproved(updated.toString())
input.updateWith(MapBacked::stringValue, StringType.of("123"))
approver.assertApproved(input.toString())
}
}

0 comments on commit f15f51c

Please sign in to comment.