NOTICK: Better use of generics for DJVM Collection and Map serializers.

This commit is contained in:
Chris Rankin 2020-03-08 20:14:22 +00:00
parent 19eff00b80
commit 00b55399cb
5 changed files with 47 additions and 41 deletions

View File

@ -1,14 +1,18 @@
package net.corda.serialization.djvm.deserializers package net.corda.serialization.djvm.deserializers
import net.corda.core.utilities.NonEmptySet import net.corda.core.utilities.NonEmptySet
import java.util.Collections import java.util.Collections.unmodifiableCollection
import java.util.Collections.unmodifiableList
import java.util.Collections.unmodifiableNavigableSet
import java.util.Collections.unmodifiableSet
import java.util.Collections.unmodifiableSortedSet
import java.util.NavigableSet import java.util.NavigableSet
import java.util.SortedSet import java.util.SortedSet
import java.util.TreeSet import java.util.TreeSet
import java.util.function.Function import java.util.function.Function
class CreateCollection : Function<Array<Any?>, Collection<Any?>> { class CreateCollection : Function<Array<out Any?>, Collection<Any?>> {
private val concreteConstructors: Map<Class<out Collection<*>>, (Array<Any?>) -> Collection<Any?>> = mapOf( private val concreteConstructors: Map<Class<out Collection<*>>, (Array<out Any?>) -> Collection<Any?>> = mapOf(
List::class.java to ::createList, List::class.java to ::createList,
Set::class.java to ::createSet, Set::class.java to ::createSet,
SortedSet::class.java to ::createSortedSet, SortedSet::class.java to ::createSortedSet,
@ -17,34 +21,34 @@ class CreateCollection : Function<Array<Any?>, Collection<Any?>> {
NonEmptySet::class.java to ::createNonEmptySet NonEmptySet::class.java to ::createNonEmptySet
) )
private fun createList(values: Array<Any?>): List<Any?> { private fun createList(values: Array<out Any?>): List<Any?> {
return Collections.unmodifiableList(values.toCollection(ArrayList())) return unmodifiableList(values.toCollection(ArrayList()))
} }
private fun createSet(values: Array<Any?>): Set<Any?> { private fun createSet(values: Array<out Any?>): Set<Any?> {
return Collections.unmodifiableSet(values.toCollection(LinkedHashSet())) return unmodifiableSet(values.toCollection(LinkedHashSet()))
} }
private fun createSortedSet(values: Array<Any?>): SortedSet<Any?> { private fun createSortedSet(values: Array<out Any?>): SortedSet<Any?> {
return Collections.unmodifiableSortedSet(values.toCollection(TreeSet())) return unmodifiableSortedSet(values.toCollection(TreeSet()))
} }
private fun createNavigableSet(values: Array<Any?>): NavigableSet<Any?> { private fun createNavigableSet(values: Array<out Any?>): NavigableSet<Any?> {
return Collections.unmodifiableNavigableSet(values.toCollection(TreeSet())) return unmodifiableNavigableSet(values.toCollection(TreeSet()))
} }
private fun createCollection(values: Array<Any?>): Collection<Any?> { private fun createCollection(values: Array<out Any?>): Collection<Any?> {
return Collections.unmodifiableCollection(values.toCollection(ArrayList())) return unmodifiableCollection(values.toCollection(ArrayList()))
} }
private fun createNonEmptySet(values: Array<Any?>): NonEmptySet<Any?> { private fun createNonEmptySet(values: Array<out Any?>): NonEmptySet<Any?> {
return NonEmptySet.copyOf(values.toCollection(ArrayList())) return NonEmptySet.copyOf(values.toCollection(ArrayList()))
} }
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
override fun apply(inputs: Array<Any?>): Collection<Any?> { override fun apply(inputs: Array<out Any?>): Collection<Any?> {
val collectionClass = inputs[0] as Class<out Collection<Any?>> val collectionClass = inputs[0] as Class<out Collection<Any?>>
val args = inputs[1] as Array<Any?> val args = inputs[1] as Array<out Any?>
return concreteConstructors[collectionClass]?.invoke(args)!! return concreteConstructors[collectionClass]?.invoke(args)!!
} }
} }

View File

@ -1,14 +1,16 @@
package net.corda.serialization.djvm.deserializers package net.corda.serialization.djvm.deserializers
import java.util.Collections import java.util.Collections.unmodifiableMap
import java.util.Collections.unmodifiableNavigableMap
import java.util.Collections.unmodifiableSortedMap
import java.util.EnumMap import java.util.EnumMap
import java.util.NavigableMap import java.util.NavigableMap
import java.util.SortedMap import java.util.SortedMap
import java.util.TreeMap import java.util.TreeMap
import java.util.function.Function import java.util.function.Function
class CreateMap : Function<Array<Any>, Map<Any?, Any?>> { class CreateMap : Function<Array<out Any>, Map<Any?, Any?>> {
private val concreteConstructors: Map<Class<out Map<*, *>>, (Array<Array<Any>>) -> Map<Any?, Any?>> = mapOf( private val concreteConstructors: Map<Class<out Map<*, *>>, (Array<Array<out Any>>) -> Map<Any?, Any?>> = mapOf(
Map::class.java to ::createMap, Map::class.java to ::createMap,
SortedMap::class.java to ::createSortedMap, SortedMap::class.java to ::createSortedMap,
LinkedHashMap::class.java to ::createLinkedHashMap, LinkedHashMap::class.java to ::createLinkedHashMap,
@ -17,36 +19,36 @@ class CreateMap : Function<Array<Any>, Map<Any?, Any?>> {
EnumMap::class.java to ::createEnumMap EnumMap::class.java to ::createEnumMap
) )
private fun createMap(values: Array<Array<Any>>): Map<Any?, Any?> { private fun createMap(values: Array<Array<out Any>>): Map<Any?, Any?> {
return Collections.unmodifiableMap(values.map { it[0] to it[1] }.toMap()) return unmodifiableMap(values.associate { it[0] to it[1] })
} }
private fun createSortedMap(values: Array<Array<Any>>): SortedMap<Any?, out Any?> { private fun createSortedMap(values: Array<Array<out Any>>): SortedMap<Any?, out Any?> {
return Collections.unmodifiableSortedMap(createTreeMap(values)) return unmodifiableSortedMap(createTreeMap(values))
} }
private fun createNavigableMap(values: Array<Array<Any>>): NavigableMap<Any?, out Any?> { private fun createNavigableMap(values: Array<Array<out Any>>): NavigableMap<Any?, out Any?> {
return Collections.unmodifiableNavigableMap(createTreeMap(values)) return unmodifiableNavigableMap(createTreeMap(values))
} }
private fun createLinkedHashMap(values: Array<Array<Any>>): LinkedHashMap<Any?, out Any?> { private fun createLinkedHashMap(values: Array<Array<out Any>>): LinkedHashMap<Any?, out Any?> {
return values.map { it[0] to it[1] }.toMap(LinkedHashMap()) return values.associateTo(LinkedHashMap()) { it[0] to it[1] }
} }
private fun createTreeMap(values: Array<Array<Any>>): TreeMap<Any?, out Any?> { private fun createTreeMap(values: Array<Array<out Any>>): TreeMap<Any?, out Any?> {
return values.map { it[0] to it[1] }.toMap(TreeMap()) return values.associateTo(TreeMap()) { it[0] to it[1] }
} }
private fun createEnumMap(values: Array<Array<Any>>): Map<Any?, Any?> { private fun createEnumMap(values: Array<Array<out Any>>): Map<Any?, Any?> {
val map = values.map { it[0] to it[1] }.toMap() val map = values.associate { it[0] to it[1] }
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
return EnumMap(map as Map<JustForCasting, Any?>) as Map<Any?, Any?> return EnumMap(map as Map<JustForCasting, Any?>) as Map<Any?, Any?>
} }
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
override fun apply(inputs: Array<Any>): Map<Any?, Any?> { override fun apply(inputs: Array<out Any>): Map<Any?, Any?> {
val mapClass = inputs[0] as Class<out Map<Any?, Any?>> val mapClass = inputs[0] as Class<out Map<Any?, Any?>>
val args = inputs[1] as Array<Array<Any>> val args = inputs[1] as Array<Array<out Any>>
return concreteConstructors[mapClass]?.invoke(args)!! return concreteConstructors[mapClass]?.invoke(args)!!
} }
} }

View File

@ -4,8 +4,8 @@ import net.corda.serialization.internal.amqp.custom.OptionalSerializer.OptionalP
import java.util.Optional import java.util.Optional
import java.util.function.Function import java.util.function.Function
class OptionalDeserializer : Function<OptionalProxy, Optional<Any>> { class OptionalDeserializer : Function<OptionalProxy, Optional<out Any>> {
override fun apply(proxy: OptionalProxy): Optional<Any> { override fun apply(proxy: OptionalProxy): Optional<out Any> {
return Optional.ofNullable(proxy.item) return Optional.ofNullable(proxy.item)
} }
} }

View File

@ -30,8 +30,8 @@ class SandboxCollectionSerializer(
private val localFactory: LocalSerializerFactory private val localFactory: LocalSerializerFactory
) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Collection::class.java)) { ) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Collection::class.java)) {
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
private val creator: Function<Array<Any>, out Any?> private val creator: Function<Array<out Any>, out Any?>
= taskFactory.apply(CreateCollection::class.java) as Function<Array<Any>, out Any?> = taskFactory.apply(CreateCollection::class.java) as Function<Array<out Any>, out Any?>
private val unsupportedTypes: Set<Class<Any>> = listOf( private val unsupportedTypes: Set<Class<Any>> = listOf(
EnumSet::class.java EnumSet::class.java
@ -87,7 +87,7 @@ class SandboxCollectionSerializer(
private class ConcreteCollectionSerializer( private class ConcreteCollectionSerializer(
declaredType: ParameterizedType, declaredType: ParameterizedType,
private val matchingType: Map.Entry<Class<Any>, Class<out Collection<*>>>, private val matchingType: Map.Entry<Class<Any>, Class<out Collection<*>>>,
private val creator: Function<Array<Any>, out Any?>, private val creator: Function<Array<out Any>, out Any?>,
factory: LocalSerializerFactory factory: LocalSerializerFactory
) : AMQPSerializer<Any> { ) : AMQPSerializer<Any> {
override val type: ParameterizedType = declaredType override val type: ParameterizedType = declaredType

View File

@ -30,8 +30,8 @@ class SandboxMapSerializer(
private val localFactory: LocalSerializerFactory private val localFactory: LocalSerializerFactory
) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Map::class.java)) { ) : CustomSerializer.Implements<Any>(clazz = classLoader.toSandboxAnyClass(Map::class.java)) {
@Suppress("unchecked_cast") @Suppress("unchecked_cast")
private val creator: Function<Array<Any>, out Any?> private val creator: Function<Array<out Any>, out Any?>
= taskFactory.apply(CreateMap::class.java) as Function<Array<Any>, out Any?> = taskFactory.apply(CreateMap::class.java) as Function<Array<out Any>, out Any?>
// The order matters here - the first match should be the most specific one. // The order matters here - the first match should be the most specific one.
// Kotlin preserves the ordering for us by associating into a LinkedHashMap. // Kotlin preserves the ordering for us by associating into a LinkedHashMap.
@ -77,7 +77,7 @@ class SandboxMapSerializer(
private class ConcreteMapSerializer( private class ConcreteMapSerializer(
declaredType: ParameterizedType, declaredType: ParameterizedType,
private val matchingType: Map.Entry<Class<Any>, Class<out Map<*, *>>>, private val matchingType: Map.Entry<Class<Any>, Class<out Map<*, *>>>,
private val creator: Function<Array<Any>, out Any?>, private val creator: Function<Array<out Any>, out Any?>,
factory: LocalSerializerFactory factory: LocalSerializerFactory
) : AMQPSerializer<Any> { ) : AMQPSerializer<Any> {
override val type: ParameterizedType = declaredType override val type: ParameterizedType = declaredType