mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Merge OS 4.4 into OS 4.5
This commit is contained in:
commit
33943032fb
@ -79,7 +79,7 @@ interface ObjectBuilder {
|
||||
* Create an [ObjectBuilderProvider] for the given [LocalTypeInformation.Composable].
|
||||
*/
|
||||
fun makeProvider(typeInformation: LocalTypeInformation.Composable): ObjectBuilderProvider =
|
||||
makeProvider(typeInformation.typeIdentifier, typeInformation.constructor, typeInformation.properties)
|
||||
makeProvider(typeInformation.typeIdentifier, typeInformation.constructor, typeInformation.properties, false)
|
||||
|
||||
/**
|
||||
* Create an [ObjectBuilderProvider] for the given type, constructor and set of properties.
|
||||
@ -90,15 +90,17 @@ interface ObjectBuilder {
|
||||
fun makeProvider(
|
||||
typeIdentifier: TypeIdentifier,
|
||||
constructor: LocalConstructorInformation,
|
||||
properties: Map<String, LocalPropertyInformation>
|
||||
properties: Map<String, LocalPropertyInformation>,
|
||||
includeAllConstructorParameters: Boolean
|
||||
): ObjectBuilderProvider =
|
||||
if (constructor.hasParameters) makeConstructorBasedProvider(properties, typeIdentifier, constructor)
|
||||
if (constructor.hasParameters) makeConstructorBasedProvider(properties, typeIdentifier, constructor, includeAllConstructorParameters)
|
||||
else makeSetterBasedProvider(properties, typeIdentifier, constructor)
|
||||
|
||||
private fun makeConstructorBasedProvider(
|
||||
properties: Map<String, LocalPropertyInformation>,
|
||||
typeIdentifier: TypeIdentifier,
|
||||
constructor: LocalConstructorInformation
|
||||
constructor: LocalConstructorInformation,
|
||||
includeAllConstructorParameters: Boolean
|
||||
): ObjectBuilderProvider {
|
||||
requireForSer(properties.values.all {
|
||||
when (it) {
|
||||
@ -119,6 +121,10 @@ interface ObjectBuilder {
|
||||
"but property $name is not constructor-paired"
|
||||
)
|
||||
}
|
||||
}.toMutableMap()
|
||||
|
||||
if (includeAllConstructorParameters) {
|
||||
addMissingConstructorParameters(constructorIndices, constructor)
|
||||
}
|
||||
|
||||
val propertySlots = constructorIndices.keys.mapIndexed { slot, name -> name to slot }.toMap()
|
||||
@ -128,6 +134,15 @@ interface ObjectBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addMissingConstructorParameters(constructorIndices: MutableMap<String, Int>, constructor: LocalConstructorInformation) {
|
||||
// Add constructor parameters not in the list of properties
|
||||
// so we can use them in object evolution
|
||||
for ((parameterIndex, parameter) in constructor.parameters.withIndex()) {
|
||||
// Only use the parameters not already matched to properties
|
||||
constructorIndices.putIfAbsent(parameter.name, parameterIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeSetterBasedProvider(
|
||||
properties: Map<String, LocalPropertyInformation>,
|
||||
typeIdentifier: TypeIdentifier,
|
||||
@ -254,7 +269,7 @@ class EvolutionObjectBuilder(
|
||||
remoteTypeInformation: RemoteTypeInformation.Composable,
|
||||
mustPreserveData: Boolean
|
||||
): () -> ObjectBuilder {
|
||||
val localBuilderProvider = ObjectBuilder.makeProvider(typeIdentifier, constructor, localProperties)
|
||||
val localBuilderProvider = ObjectBuilder.makeProvider(typeIdentifier, constructor, localProperties, true)
|
||||
|
||||
val remotePropertyNames = remoteTypeInformation.properties.keys.sorted()
|
||||
val reroutedIndices = remotePropertyNames.map { propertyName ->
|
||||
|
@ -0,0 +1,90 @@
|
||||
package net.corda.serialization.internal.amqp
|
||||
|
||||
import net.corda.core.contracts.BelongsToContract
|
||||
import net.corda.core.contracts.Contract
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.serialization.internal.amqp.testutils.deserialize
|
||||
import net.corda.serialization.internal.amqp.testutils.serialize
|
||||
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
|
||||
import net.corda.serialization.internal.amqp.testutils.writeTestResource
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.junit.Test
|
||||
|
||||
class EvolutionObjectBuilderRenamedPropertyTests
|
||||
{
|
||||
private val cordappVersionTestValue = 38854445
|
||||
private val dataTestValue = "d7af8af0-c10e-45bc-a5f7-92de432be0ef"
|
||||
private val xTestValue = 7568055
|
||||
private val yTestValue = 4113687
|
||||
|
||||
class TemplateContract : Contract {
|
||||
override fun verify(tx: LedgerTransaction) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1
|
||||
*
|
||||
* This is the original class definition in object evolution.
|
||||
*/
|
||||
// @BelongsToContract(TemplateContract::class)
|
||||
// data class TemplateState(val cordappVersion: Int, val data: String, val x : Int?, override val participants: List<AbstractParty> = listOf()) : ContractState
|
||||
|
||||
/**
|
||||
* Step 2
|
||||
*
|
||||
* This is an intermediate class definition in object evolution.
|
||||
* The y property has been added and a constructor copies the value of x into y. x is now set to null by the constructor.
|
||||
*/
|
||||
// @BelongsToContract(TemplateContract::class)
|
||||
// data class TemplateState(val cordappVersion: Int, val data: String, val x : Int?, val y : String?, override val participants: List<AbstractParty> = listOf()) : ContractState {
|
||||
// @DeprecatedConstructorForDeserialization(1)
|
||||
// constructor(cordappVersion: Int, data : String, x : Int?, participants: List<AbstractParty>)
|
||||
// : this(cordappVersion, data, null, x?.toString(), participants)
|
||||
// }
|
||||
|
||||
/**
|
||||
* Step 3
|
||||
*
|
||||
* This is the final class definition in object evolution.
|
||||
* The x property has been removed but the constructor that copies values of x into y still exists. We expect previous versions of this
|
||||
* object to pass the value of x to the constructor when deserialized.
|
||||
*/
|
||||
@BelongsToContract(TemplateContract::class)
|
||||
data class TemplateState(val cordappVersion: Int, val data: String, val y : String?, override val participants: List<AbstractParty> = listOf()) : ContractState {
|
||||
@DeprecatedConstructorForDeserialization(1)
|
||||
constructor(cordappVersion: Int, data : String, x : Int?, participants: List<AbstractParty>) : this(cordappVersion, data, x?.toString(), participants)
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `Step 1 to Step 3`() {
|
||||
|
||||
// The next two commented lines are how the serialized data is generated. To regenerate the data, uncomment these along
|
||||
// with the correct version of the class and rerun the test. This will generate a new file in the project resources.
|
||||
|
||||
// val step1 = TemplateState(cordappVersionTestValue, dataTestValue, xTestValue)
|
||||
// saveSerializedObject(step1)
|
||||
|
||||
// serialization/src/test/resources/net/corda/serialization/internal/amqp/EvolutionObjectBuilderRenamedPropertyTests.Step1
|
||||
val bytes = this::class.java.getResource("EvolutionObjectBuilderRenamedPropertyTests.Step1").readBytes()
|
||||
|
||||
val serializerFactory: SerializerFactory = testDefaultFactory()
|
||||
val deserializedObject = DeserializationInput(serializerFactory)
|
||||
.deserialize(SerializedBytes<TemplateState>(bytes))
|
||||
|
||||
Assertions.assertThat(deserializedObject.cordappVersion).isEqualTo(cordappVersionTestValue)
|
||||
Assertions.assertThat(deserializedObject.data).isEqualTo(dataTestValue)
|
||||
// Assertions.assertThat(deserializedObject.x).isEqualTo(xTestValue)
|
||||
Assertions.assertThat(deserializedObject.y).isEqualTo(xTestValue.toString())
|
||||
Assertions.assertThat(deserializedObject).isInstanceOf(TemplateState::class.java)
|
||||
}
|
||||
|
||||
/**
|
||||
* Write serialized object to resources folder
|
||||
*/
|
||||
@Suppress("unused")
|
||||
fun <T : Any> saveSerializedObject(obj : T) = writeTestResource(SerializationOutput(testDefaultFactory()).serialize(obj))
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user