Finalise which map containers to serialize

This commit is contained in:
Katelyn Baker 2017-08-10 11:59:10 +01:00
parent de05a11511
commit d2933ca8a3
4 changed files with 52 additions and 22 deletions

View File

@ -18,18 +18,23 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact
override val typeDescriptor = "$DESCRIPTOR_DOMAIN:${fingerprintForType(type, factory)}"
companion object {
private val supportedTypes: Map<Class<out Any>, (Map<*, *>) -> Map<*, *>> = mapOf(
private val supportedTypes: Map<Class<out Any?>, (Map<*, *>) -> Map<*, *>> = mapOf(
// Interfaces
Map::class.java to { map -> map },
SortedMap::class.java to { map -> TreeMap(map) },
NavigableMap::class.java to { map -> TreeMap(map) },
// Sub types
Dictionary::class.java to { map -> Hashtable(map) },
// concrete types for user convienience
HashMap::class.java to { map -> LinkedHashMap(map) },
AbstractMap::class.java to { map -> LinkedHashMap(map) },
// concrete types
LinkedHashMap::class.java to { map -> LinkedHashMap(map) },
TreeMap::class.java to { map -> TreeMap(map) },
Hashtable::class.java to { map -> Hashtable(map) }
Hashtable::class.java to { map -> Hashtable(map) },
WeakHashMap::class.java to { map -> WeakHashMap(map) }
// Explicitly disallowed
// - HashMap::class.java
// - EnumMap::class.java
)
private fun findConcreteType(clazz: Class<*>): (Map<*, *>) -> Map<*, *> {
return supportedTypes[clazz] ?: throw NotSerializableException("Unsupported map type $clazz.")
}

View File

@ -35,6 +35,7 @@ internal fun constructorForDeserialization(type: Type): KFunction<Any>? {
val kotlinConstructors = clazz.kotlin.constructors
val hasDefault = kotlinConstructors.any { it.parameters.isEmpty() }
for (kotlinConstructor in kotlinConstructors) {
println (kotlinConstructor)
if (preferredCandidate == null && kotlinConstructors.size == 1 && !hasDefault) {
preferredCandidate = kotlinConstructor
} else if (preferredCandidate == null && kotlinConstructors.size == 2 && hasDefault && kotlinConstructor.parameters.isNotEmpty()) {
@ -44,6 +45,7 @@ internal fun constructorForDeserialization(type: Type): KFunction<Any>? {
throw NotSerializableException("More than one constructor for $clazz is annotated with @CordaConstructor.")
}
preferredCandidate = kotlinConstructor
println (" -> $preferredCandidate")
}
}
return preferredCandidate ?: throw NotSerializableException("No constructor for deserialization found for $clazz.")

View File

@ -5,6 +5,7 @@ import java.util.*
import org.apache.qpid.proton.codec.Data
class DeserializeCollectionTests {
class TestSerializationOutput(
private val verbose: Boolean,
serializerFactory: SerializerFactory = SerializerFactory()) : SerializationOutput(serializerFactory) {
@ -32,6 +33,23 @@ class TestSerializationOutput(
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun abstractMapFromMapOf() {
data class C(val c: AbstractMap<String, Int>)
val c = C (mapOf("A" to 1, "B" to 2) as AbstractMap)
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun abstractMapFromTreeMap() {
data class C(val c: AbstractMap<String, Int>)
val c = C (TreeMap(mapOf("A" to 1, "B" to 2)))
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun sortedMapTest() {
data class C(val c: SortedMap<String, Int>)
@ -40,6 +58,15 @@ class TestSerializationOutput(
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun navigableMapTest() {
data class C(val c: NavigableMap<String, Int>)
val c = C(TreeMap (mapOf("A" to 1, "B" to 2)).descendingMap())
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun dictionaryTest() {
data class C(val c: Dictionary<String, Int>)
@ -51,17 +78,8 @@ class TestSerializationOutput(
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun navigableMapTest() {
data class C(val c: NavigableMap<String, Int>)
val c = C(TreeMap (mapOf("A" to 1, "B" to 3)).descendingMap())
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test(expected=java.lang.IllegalArgumentException::class)
fun HashMapTest() {
fun hashMapTest() {
data class C(val c : HashMap<String, Int>)
val c = C (HashMap (mapOf("A" to 1, "B" to 2)))
@ -69,6 +87,15 @@ class TestSerializationOutput(
TestSerializationOutput(VERBOSE, sf).serialize(c)
}
@Test
fun weakHashMapTest() {
data class C(val c : WeakHashMap<String, Int>)
val c = C (WeakHashMap (mapOf("A" to 1, "B" to 2)))
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
DeserializationInput(sf).deserialize(serialisedBytes)
}
@Test
fun concreteTreeMapTest() {
data class C(val c: TreeMap<String, Int>)
@ -84,10 +111,6 @@ class TestSerializationOutput(
val c = C (LinkedHashMap (mapOf("A" to 1, "B" to 2)))
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
val deserializedObj = DeserializationInput(sf).deserialize(serialisedBytes)
DeserializationInput(sf).deserialize(serialisedBytes)
}
}

View File

@ -356,7 +356,7 @@ class SerializationOutputTests {
serdes(obj)
}
@Test(expected = NotSerializableException::class)
@Test
fun `test TreeMap property`() {
val obj = TreeMapWrapper(TreeMap<Int, Foo>())
obj.tree[456] = Foo("Fred", 123)