Skip to content

Commit e30758d

Browse files
committed
#39 Support PrimitiveTypeSerializer to handle multi-part form data
1 parent f04ee3f commit e30758d

File tree

7 files changed

+76
-21
lines changed

7 files changed

+76
-21
lines changed

reference-cordapp/src/genericApiTest/kotlin/tech/b180/cordaptor_test/CordaptorAPITestSuite.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ class CordaptorAPITestSuite(
244244
val req = client.POST("$baseUrl/node/reference/TestFileFlow")
245245

246246
val multiPartContentProvider = MultiPartContentProvider()
247+
multiPartContentProvider.addFieldPart("testString", StringContentProvider("test"), null)
248+
multiPartContentProvider.addFieldPart("testInt", StringContentProvider("2"), null)
247249
multiPartContentProvider.addFilePart("file", "testData.csv",
248250
PathContentProvider(Paths.get(CordaptorAPITestSuite::class.java.classLoader.getResource("testData.csv").toURI())), null)
249251
multiPartContentProvider.close()

reference-cordapp/src/genericApiTest/resources/ReferenceCordapp.api.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,16 @@
326326
"file": {
327327
"type": "string",
328328
"format": "binary"
329+
},
330+
"testInt": {
331+
"type": "number",
332+
"format": "int32"
333+
},
334+
"testString": {
335+
"type": "string"
329336
}
330337
},
331-
"required": ["file"]
338+
"required": ["file", "testInt", "testString"]
332339
},
333340
"CordaFlowProgress": {
334341
"type": "object",

reference-cordapp/src/main/kotlin/tech/b180/ref_cordapp/ReferenceCordapp.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ data class TestFileFlowResult(
185185
@StartableByService
186186
@Suppress("UNUSED")
187187
class TestFileFlow(
188-
private val file: ByteArray
188+
private val file: ByteArray,
189+
private val testInt: Int,
190+
private val testString: String
189191
) : FlowLogic<TestFileFlowResult>() {
190192

191193
companion object {

rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ class BigDecimalSerializer
9696
override fun toJson(obj: BigDecimal, generator: JsonGenerator) {
9797
generator.write(obj)
9898
}
99+
100+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): BigDecimal {
101+
return when(formValue.value.isNotEmpty()) {
102+
true -> formValue.value.toBigDecimal()
103+
false -> BigDecimal(0)
104+
}
105+
}
99106
}
100107

101108
class CordaNodeAttachmentSerializer : MultiPartFormDataSerializer<CordaNodeAttachment> {

rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/SerializationFactory.kt

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ class SerializationFactory(
7474
val map = ConcurrentHashMap<SerializerKey, JsonSerializer<Any>>()
7575

7676
map[SerializerKey(String::class.java)] = StringSerializer as JsonSerializer<Any>
77-
map[SerializerKey(ByteArray::class.java)] = ByteArraySerializer as JsonSerializer<Any>
7877
map[SerializerKey(Int::class.java)] = IntSerializer as JsonSerializer<Any>
7978
map[SerializerKey(Long::class.java)] = LongSerializer as JsonSerializer<Any>
8079
map[SerializerKey(Double::class.java)] = DoubleSerializer as JsonSerializer<Any>
@@ -137,6 +136,8 @@ class SerializationFactory(
137136

138137
override val valueType = SerializerKey.fromSuperclassTypeArgument(PrimitiveTypeSerializer::class, this::class)
139138
override fun generateSchema(generator: JsonSchemaGenerator) = schema
139+
140+
abstract fun fromMultiPartFormValue(formValue: FormData.FormValue) : T
140141
}
141142

142143
/** Built-in serializer for atomic value of type [String] */
@@ -156,25 +157,13 @@ class SerializationFactory(
156157
override fun toJson(obj: String, generator: JsonGenerator) {
157158
generator.write(obj)
158159
}
159-
}
160160

161-
/** Built-in serializer for atomic value of type [ByteArray] */
162-
object ByteArraySerializer : PrimitiveTypeSerializer<ByteArray>("string") {
163-
override fun fromJson(value: JsonValue): ByteArray {
164-
return when (value.valueType) {
165-
// provide limited number of type conversions
166-
JsonValue.ValueType.TRUE -> true.toString().base64ToByteArray()
167-
JsonValue.ValueType.FALSE -> false.toString().base64ToByteArray()
168-
JsonValue.ValueType.NULL -> "".base64ToByteArray()
169-
JsonValue.ValueType.NUMBER -> value.toString().base64ToByteArray()
170-
JsonValue.ValueType.STRING -> (value as JsonString).string.base64ToByteArray()
171-
else -> throw AssertionError("Expected string, got ${value.valueType} with value $value")
161+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): String {
162+
return when(formValue.value.isNotEmpty()) {
163+
true -> formValue.value
164+
false -> ""
172165
}
173166
}
174-
175-
override fun toJson(obj: ByteArray, generator: JsonGenerator) {
176-
generator.write(String(obj))
177-
}
178167
}
179168

180169
/** Built-in serializer for atomic value of type [Int] */
@@ -191,6 +180,13 @@ class SerializationFactory(
191180
override fun toJson(obj: Int, generator: JsonGenerator) {
192181
generator.write(obj)
193182
}
183+
184+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): Int {
185+
return when(formValue.value.isNotEmpty()) {
186+
true -> Integer.parseInt(formValue.value)
187+
false -> 0
188+
}
189+
}
194190
}
195191

196192
/** Built-in serializer for atomic value of type [Long] */
@@ -207,6 +203,13 @@ class SerializationFactory(
207203
override fun toJson(obj: Long, generator: JsonGenerator) {
208204
generator.write(obj)
209205
}
206+
207+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): Long {
208+
return when(formValue.value.isNotEmpty()) {
209+
true -> formValue.value.toLong()
210+
false -> 0
211+
}
212+
}
210213
}
211214

212215
/** Built-in serializer for atomic value of type [Double] */
@@ -223,6 +226,13 @@ class SerializationFactory(
223226
override fun toJson(obj: Double, generator: JsonGenerator) {
224227
generator.write(obj)
225228
}
229+
230+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): Double {
231+
return when(formValue.value.isNotEmpty()) {
232+
true -> formValue.value.toDouble()
233+
false -> 0.0
234+
}
235+
}
226236
}
227237

228238
/** Built-in serializer for atomic value of type [Float] */
@@ -239,6 +249,13 @@ class SerializationFactory(
239249
override fun toJson(obj: Float, generator: JsonGenerator) {
240250
generator.write(obj.toDouble())
241251
}
252+
253+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): Float {
254+
return when(formValue.value.isNotEmpty()) {
255+
true -> formValue.value.toFloat()
256+
false -> 0.0.toFloat()
257+
}
258+
}
242259
}
243260

244261
/** Built-in serializer for atomic value of type [Boolean] */
@@ -255,6 +272,13 @@ class SerializationFactory(
255272
override fun toJson(obj: Boolean, generator: JsonGenerator) {
256273
generator.write(obj)
257274
}
275+
276+
override fun fromMultiPartFormValue(formValue: FormData.FormValue): Boolean {
277+
return when (formValue.value.isNotEmpty()) {
278+
true -> formValue.value.toBoolean()
279+
else -> throw AssertionError("Expected , boolean got ${formValue.value}")
280+
}
281+
}
258282
}
259283

260284
/** Serializer for Kotlin type [Unit] */
@@ -269,6 +293,13 @@ class SerializationFactory(
269293
override fun toJson(obj: Unit, generator: JsonGenerator) {
270294
generator.write(obj.toString())
271295
}
296+
297+
override fun fromMultiPartFormValue(formValue: FormData.FormValue) {
298+
return when (formValue.value.isNullOrEmpty()) {
299+
true -> Unit
300+
else -> throw AssertionError("Expected unit, got ${formValue.value}")
301+
}
302+
}
272303
}
273304

274305
// FIXME use url format for the schema

rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/SerializationFramework.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ abstract class StructuredObjectSerializer<T: Any>(
203203
is MultiPartFormValueSerializer -> {
204204
prop.serializer.fromMultiPartFormValue(it.first)
205205
}
206+
is SerializationFactory.PrimitiveTypeSerializer -> {
207+
prop.serializer.fromMultiPartFormValue(it.first)
208+
}
206209
is MultiPartFormTransformValueSerializer<*,*> -> {
207210
prop.serializer.transformValue(it.first)
208211
}

rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ class CordaTypesTest : KoinTest {
289289
fun `test multi part form data corda flow instruction serialization`() {
290290
val serializer = getKoin().getSerializer(CordaFlowInstruction::class, TestFileFlow::class) as MultiPartFormDataSerializer
291291
val testPath = Paths.get(CordaTypesTest::class.java.classLoader.getResource("testData.csv").toURI())
292-
val formData = FormData(1)
292+
val formData = FormData(3)
293293
formData.add("file", testPath, "testData.csv", null)
294-
294+
formData.add("testString", "test")
295+
formData.add("testInt", "2")
295296
println("Serializer Schema: " + serializer.generateRecursiveSchema(getKoin().get()))
296297

297298
assertTrue { testPath.toFile().readBytes().contentEquals(
@@ -412,6 +413,8 @@ data class TestNonComposableFlow(
412413

413414
data class TestFileFlow(
414415
val file: ByteArray,
416+
val testInt: Int,
417+
val testString: String,
415418
override val progressTracker: ProgressTracker
416419
) : FlowLogic<ByteArray>() {
417420

0 commit comments

Comments
 (0)