mirror of
https://github.com/corda/corda.git
synced 2025-02-22 02:06:45 +00:00
Serialiser / Synthesiser work and cleanup
- Adding test case that shows it should work AS it works with concrete classes, not if we carpent up the back end - WIP - The current test fails because the carpenter is creating the map (for some reason) as a linked hash map and not a normal map that we can't serialise. Added a test to confirm that it's not the carpenter here. Two questions really, why are we creating it as a linked has map, AFAIK the carpenter should just be whipping up what it's told to and it's not being given a linked map Secondly, should we support serialisation of these objects - Remove debug - Remove yet more debug
This commit is contained in:
parent
92ba0c33e1
commit
45ed78b1a8
@ -219,8 +219,8 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeClassSerializer(clazz: Class<*>, type: Type, declaredType: Type): AMQPSerializer<Any> {
|
private fun makeClassSerializer(clazz: Class<*>, type: Type, declaredType: Type): AMQPSerializer<Any> =
|
||||||
return serializersByType.computeIfAbsent(type) {
|
serializersByType.computeIfAbsent(type) {
|
||||||
if (isPrimitive(clazz)) {
|
if (isPrimitive(clazz)) {
|
||||||
AMQPPrimitiveSerializer(clazz)
|
AMQPPrimitiveSerializer(clazz)
|
||||||
} else {
|
} else {
|
||||||
@ -238,7 +238,6 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer<Any>? {
|
internal fun findCustomSerializer(clazz: Class<*>, declaredType: Type): AMQPSerializer<Any>? {
|
||||||
@ -319,10 +318,10 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
|
|||||||
fun nameForType(type: Type) : String = when (type) {
|
fun nameForType(type: Type) : String = when (type) {
|
||||||
is Class<*> -> {
|
is Class<*> -> {
|
||||||
primitiveTypeName(type) ?: if (type.isArray) {
|
primitiveTypeName(type) ?: if (type.isArray) {
|
||||||
"${nameForType(type.componentType)}${if(type.componentType.isPrimitive)"[p]" else "[]"}"
|
"${nameForType(type.componentType)}${if (type.componentType.isPrimitive) "[p]" else "[]"}"
|
||||||
} else type.name
|
} else type.name
|
||||||
}
|
}
|
||||||
is ParameterizedType -> "${nameForType(type.rawType)}<${type.actualTypeArguments.joinToString { nameForType(it) }}>"
|
is ParameterizedType -> "${nameForType(type.rawType)ype.actualTypeArguments.joinToString { nameForType(it) }}>"
|
||||||
is GenericArrayType -> "${nameForType(type.genericComponentType)}[]"
|
is GenericArrayType -> "${nameForType(type.genericComponentType)}[]"
|
||||||
else -> throw NotSerializableException("Unable to render type $type to a string.")
|
else -> throw NotSerializableException("Unable to render type $type to a string.")
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ class ClassCarpenter {
|
|||||||
private fun generateClass(classSchema: Schema): Class<*> {
|
private fun generateClass(classSchema: Schema): Class<*> {
|
||||||
return generate(classSchema) { cw, schema ->
|
return generate(classSchema) { cw, schema ->
|
||||||
val superName = schema.superclass?.jvmName ?: "java/lang/Object"
|
val superName = schema.superclass?.jvmName ?: "java/lang/Object"
|
||||||
var interfaces = schema.interfaces.map { it.name.jvm }.toMutableList()
|
val interfaces = schema.interfaces.map { it.name.jvm }.toMutableList()
|
||||||
|
|
||||||
if (SimpleFieldAccess::class.java !in schema.interfaces) interfaces.add(SimpleFieldAccess::class.java.name.jvm)
|
if (SimpleFieldAccess::class.java !in schema.interfaces) interfaces.add(SimpleFieldAccess::class.java.name.jvm)
|
||||||
|
|
||||||
@ -309,7 +309,6 @@ class ClassCarpenter {
|
|||||||
// If we're trying to carpent a class that prior to serialisation / deserialisation
|
// If we're trying to carpent a class that prior to serialisation / deserialisation
|
||||||
// was made by a carpenter then we can ignore this (it will implement a plain get
|
// was made by a carpenter then we can ignore this (it will implement a plain get
|
||||||
// method from SimpleFieldAccess).
|
// method from SimpleFieldAccess).
|
||||||
// method from SimpleFieldAccess)
|
|
||||||
if (fieldNameFromItf.isEmpty() && SimpleFieldAccess::class.java in schema.interfaces) return@forEach
|
if (fieldNameFromItf.isEmpty() && SimpleFieldAccess::class.java in schema.interfaces) return@forEach
|
||||||
|
|
||||||
if ((schema is ClassSchema) and (fieldNameFromItf !in allFields))
|
if ((schema is ClassSchema) and (fieldNameFromItf !in allFields))
|
||||||
|
@ -10,8 +10,21 @@ interface I {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface II {
|
interface II {
|
||||||
|
fun returnName() : String
|
||||||
|
}
|
||||||
|
|
||||||
|
interface III {
|
||||||
|
fun returnAge() : Int
|
||||||
|
fun returnThingWithName(): II
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
fun getName() : String
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BB {
|
||||||
fun getAge() : Int
|
fun getAge() : Int
|
||||||
fun getThingWithName(): I
|
fun getThingWithName(): II
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,7 +34,6 @@ interface II {
|
|||||||
* replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath
|
* replicates the situation where a receiver doesn't have some or all elements of a schema present on it's classpath
|
||||||
*/
|
*/
|
||||||
class DeserializeNeedingCarpentryTests {
|
class DeserializeNeedingCarpentryTests {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* If you want to see the schema encoded into the envelope after serialisation change this to true
|
* If you want to see the schema encoded into the envelope after serialisation change this to true
|
||||||
@ -116,37 +128,85 @@ class DeserializeNeedingCarpentryTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// technically this test doesn't test anything (relevent to carpanter / serialiser interaction) since
|
||||||
|
// all the classes are knwon, what does do is replicate the test below to demonstrate it should
|
||||||
|
// all work
|
||||||
|
@Test
|
||||||
|
fun mapOfKnown() {
|
||||||
|
class lII (val name: String) : II {
|
||||||
|
override fun returnName() = name
|
||||||
|
}
|
||||||
|
|
||||||
|
class lIII (val age: Int, val thingWithName: II): III {
|
||||||
|
override fun returnAge(): Int = age
|
||||||
|
override fun returnThingWithName() = thingWithName
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Wrapper(val IIIs: MutableMap<String, III>)
|
||||||
|
val wrapper = Wrapper (mutableMapOf())
|
||||||
|
val testData = arrayOf(Pair ("Fred", 12), Pair ("Bob", 50), Pair ("Thirsty", 101))
|
||||||
|
|
||||||
|
testData.forEach {
|
||||||
|
wrapper.IIIs[it.first] = lIII(it.second, lII(it.first))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now do the actual test by serialising and deserialising [wrapper]
|
||||||
|
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(wrapper)
|
||||||
|
val deserializedObj = DeserializationInput(sf).deserialize(serialisedBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO This class shows that the problem isn't with the carpented class but a general
|
||||||
|
// TODO Bug / feature of the code...
|
||||||
|
/*
|
||||||
|
@Test
|
||||||
|
fun linkedHashMapTest() {
|
||||||
|
data class C(val c : LinkedHashMap<String, Int>)
|
||||||
|
val c = C (LinkedHashMap (mapOf("A" to 1, "B" to 2)))
|
||||||
|
|
||||||
|
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(c)
|
||||||
|
val deserializedObj = DeserializationInput(sf).deserialize(serialisedBytes)
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO the problem here is that the wrapper class as created by the serialiser
|
||||||
|
// TODO contains a [LinkedHashMap] and not a [Map] and we thus can't serialise
|
||||||
|
// TODO it - Talk to Rick about weather we should be able to or not
|
||||||
|
/*
|
||||||
@Test
|
@Test
|
||||||
fun mapOfInterfaces() {
|
fun mapOfInterfaces() {
|
||||||
val cc = ClassCarpenter()
|
val cc = ClassCarpenter()
|
||||||
|
|
||||||
val implementsI = cc.build(ClassSchema(
|
val implementsI = cc.build(ClassSchema(
|
||||||
"implementsI", mapOf("name" to NonNullableField(String::class.java)),
|
"implementsI", mapOf("name" to NonNullableField(String::class.java)),
|
||||||
interfaces = listOf (I::class.java)))
|
interfaces = listOf (B::class.java)))
|
||||||
|
|
||||||
val implementsII = cc.build(ClassSchema("ImplementsII", mapOf (
|
val implementsII = cc.build(ClassSchema("ImplementsII", mapOf (
|
||||||
"age" to NonNullableField(Int::class.java),
|
"age" to NonNullableField(Int::class.java),
|
||||||
"thingWithName" to NullableField(I::class.java)),
|
"thingWithName" to NullableField(B::class.java)),
|
||||||
interfaces = listOf (II::class.java)))
|
interfaces = listOf (BB::class.java)))
|
||||||
|
|
||||||
|
// inline fun getval(reified T : Any) : return T::class.java
|
||||||
|
|
||||||
val wrapper = cc.build(ClassSchema("wrapper", mapOf (
|
val wrapper = cc.build(ClassSchema("wrapper", mapOf (
|
||||||
"IIs" to NonNullableField(MutableMap::class.java))))
|
"BBs" to NonNullableField(mutableMapOf<String, BB>()::class.java
|
||||||
|
))))
|
||||||
|
|
||||||
val tmp: MutableMap<String, II> = mutableMapOf()
|
val tmp : MutableMap<String, BB> = mutableMapOf()
|
||||||
val toSerialise = wrapper.constructors.first().newInstance(tmp)
|
val toSerialise = wrapper.constructors.first().newInstance(tmp)
|
||||||
val testData = arrayOf(Pair ("Fred", 12), Pair ("Bob", 50), Pair ("Thirsty", 101))
|
val testData = arrayOf(Pair ("Fred", 12), Pair ("Bob", 50), Pair ("Thirsty", 101))
|
||||||
|
|
||||||
testData.forEach {
|
testData.forEach {
|
||||||
(wrapper.getMethod("getIIs").invoke(toSerialise) as MutableMap<String, II>)[it.first] =
|
(wrapper.getMethod("getBBs").invoke(toSerialise) as MutableMap<String, BB>)[it.first] =
|
||||||
implementsII.constructors.first().newInstance(it.second,
|
implementsII.constructors.first().newInstance(it.second,
|
||||||
implementsI.constructors.first().newInstance(it.first) as I) as II
|
implementsI.constructors.first().newInstance(it.first) as B) as BB
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now do the actual test by serialising and deserialising [wrapper]
|
// Now do the actual test by serialising and deserialising [wrapper]
|
||||||
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(wrapper)
|
val serialisedBytes = TestSerializationOutput(VERBOSE, sf).serialize(toSerialise)
|
||||||
val deserializedObj = DeserializationInput(sf).deserialize(serialisedBytes)
|
val deserializedObj = DeserializationInput(sf).deserialize(serialisedBytes)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun unknownInterface() {
|
fun unknownInterface() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user