Skip to content

Commit b28dbbe

Browse files
authored
Merge pull request #5 from rschluesselbauer/bug/GAIA-1691
Support conversion of arrays nested in maps
2 parents 4c1d5cf + da6dbfa commit b28dbbe

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

src/main/kotlin/implicit/Implicit.kt

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,20 +122,33 @@ class Implicit(val namingStrategy: (TypeDescription) -> CharSequence) {
122122
fun <T> setMapValueInInstance(instance: T, method: Method, fieldValue: Any?) {
123123
if (fieldValue != null) {
124124
val clazz = method.parameterTypes[0]
125-
if (isNestedImplicitObject(clazz, fieldValue))
126-
invoke(instance, method, instantiateNestedObject(clazz, fieldValue as Map<*, *>))
127-
else
128-
invoke(instance, method, TypeConversion.convert(fieldValue, method.parameterTypes[0]))
125+
val convertedFieldValue = when {
126+
isNestedImplicitObject(clazz, fieldValue) -> instantiateNestedObject(clazz, fieldValue as Map<*, *>)
127+
isNestedMap(clazz, fieldValue) -> convertCollectionsInMaps(fieldValue as Map<*, *>)
128+
else -> TypeConversion.convert(fieldValue, method.parameterTypes[0])
129+
}
130+
invoke(instance, method, convertedFieldValue)
129131
} else {
130132
initializeField(instance, method, method.parameterTypes[0])
131133
}
132134
}
133135

136+
private fun convertCollectionsInMaps(map: Map<*, *>): Map<*, *> {
137+
return map.mapValues {
138+
val valueAsCollection = convertToCollection(it.value)
139+
when {
140+
valueAsCollection != null -> return@mapValues valueAsCollection
141+
it.value is Map<*, *> -> return@mapValues convertCollectionsInMaps(it.value as Map<*, *>)
142+
else -> return@mapValues it.value
143+
}
144+
}
145+
}
146+
134147
private fun <T> handleGenerics(type: Class<T>, method: Method, value: Any?): Any? {
135148
val valuesInACollection = convertToCollection(value)
136-
if (valuesInACollection!=null) {
149+
if (valuesInACollection != null) {
137150
val genericType = getGenericType(type, method)
138-
if(genericType!=null){
151+
if (genericType != null) {
139152
if (method.parameterTypes.first().isAssignableFrom(List::class.java)) {
140153
return instantiateGenericNestedObject(valuesInACollection, genericType).toList()
141154
}
@@ -147,8 +160,8 @@ class Implicit(val namingStrategy: (TypeDescription) -> CharSequence) {
147160
return value
148161
}
149162

150-
private fun convertToCollection(value: Any?) : Collection<*>?{
151-
if(value!=null){
163+
private fun convertToCollection(value: Any?): Collection<*>? {
164+
if (value != null) {
152165
if (value is Collection<*>)
153166
return value
154167
else if (value is Array<*>)
@@ -157,7 +170,7 @@ class Implicit(val namingStrategy: (TypeDescription) -> CharSequence) {
157170
return null
158171
}
159172

160-
private fun instantiateGenericNestedObject(value : Collection<*>, clazz: KClass<*>) = value.stream().map { instantiateNestedObject(clazz.java, it as Map<*, *>) }
173+
private fun instantiateGenericNestedObject(value: Collection<*>, clazz: KClass<*>) = value.stream().map { instantiateNestedObject(clazz.java, it as Map<*, *>) }
161174

162175
private fun <T> getGenericType(type: Class<T>, method: Method): KClass<*>? {
163176
return type.declaredMethods
@@ -169,6 +182,7 @@ class Implicit(val namingStrategy: (TypeDescription) -> CharSequence) {
169182

170183
fun getFieldNameFromSetterMethod(setter: Method): String = setter.name.substring(3).decapitalize()
171184
fun isNestedImplicitObject(objClass: Class<*>, fieldValue: Any?): Boolean = objClass.isInterface && objClass != Map::class.java && fieldValue is Map<*, *>
185+
fun isNestedMap(objClass: Class<*>, fieldValue: Any?): Boolean = objClass == Map::class.java && fieldValue is Map<*, *>
172186
fun isSetter(method: Method): Boolean = method.name.startsWith("set")
173187
fun isGetter(method: Method): Boolean = method.name.startsWith("get") || method.name.startsWith("is")
174188
fun <T> instantiateNestedObject(clazz: Class<T>, map: Map<*, *>) = instantiate(clazz, map)

src/test/kotlin/implicit/ImplicitTest.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package implicit;
1818

1919
import org.junit.jupiter.api.Assertions
2020
import org.junit.jupiter.api.Assertions.assertNotNull
21+
import org.junit.jupiter.api.Assertions.assertTrue
2122
import org.junit.jupiter.api.Test
2223
import java.util.*
2324

@@ -63,6 +64,19 @@ class ImplicitTest {
6364
assertNotNull(pojo.getLabelSet())
6465
}
6566

67+
@Test
68+
fun `map initialization with array as value of map`() {
69+
val factory = Implicit { "implicit.test.implicit.${it.simpleName}" }
70+
val function = factory.getFunction(IPojo::class.java)
71+
72+
val pojo = function.apply(mapOf("utterances" to mapOf("de" to arrayOf("hello", "world"))))
73+
74+
assertNotNull(pojo.getUtterances())
75+
assertNotNull(pojo.getUtterances()["de"])
76+
assert(pojo.getUtterances()["de"] is List)
77+
assertTrue(pojo.getUtterances()["de"] == listOf("hello", "world"))
78+
}
79+
6680
@Test
6781
fun `map initialization with list and set input`() {
6882
val factory = Implicit { "implicit.test.implicit.${it.simpleName}" }
@@ -111,5 +125,9 @@ class ImplicitTest {
111125

112126
fun getLabelSet(): Set<String?>
113127
fun setLabelSet(labelList: Set<String?>)
128+
129+
fun getUtterances(): Map<String?, List<String?>>
130+
fun setUtterances(utterances : Map<String?, List<String?>>)
131+
114132
}
115133
}

0 commit comments

Comments
 (0)