Skip to content

Commit af3bc16

Browse files
committed
Update BeanAdapter.
1 parent 938753c commit af3bc16

3 files changed

Lines changed: 59 additions & 8 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
subprojects {
1616
group = 'org.httprpc'
17-
version = '6.1'
17+
version = '6.1.1'
1818

1919
repositories {
2020
mavenCentral()

kilo-client/src/main/java/org/httprpc/kilo/beans/BeanAdapter.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
import java.util.Map;
5353
import java.util.Objects;
5454
import java.util.Set;
55+
import java.util.SortedMap;
56+
import java.util.SortedSet;
57+
import java.util.TreeMap;
58+
import java.util.TreeSet;
5559
import java.util.UUID;
5660
import java.util.concurrent.ConcurrentHashMap;
5761
import java.util.function.Function;
@@ -687,6 +691,11 @@ public static Object coerceGeneric(Object value, Type type) {
687691
case Class<?> rawType -> toRawType(value, rawType);
688692
case ParameterizedType parameterizedType -> {
689693
var rawType = (Class<?>)parameterizedType.getRawType();
694+
695+
if (!rawType.isInterface()) {
696+
throw new IllegalArgumentException("Invalid parameterized type.");
697+
}
698+
690699
var actualTypeArguments = parameterizedType.getActualTypeArguments();
691700

692701
if (rawType == List.class) {
@@ -705,14 +714,14 @@ public static Object coerceGeneric(Object value, Type type) {
705714
} else {
706715
throw new IllegalArgumentException("Value is not a collection.");
707716
}
708-
} else if (rawType == Map.class) {
717+
} else if (Map.class.isAssignableFrom(rawType)) {
709718
if (value == null) {
710719
yield null;
711720
} else if (value instanceof Map<?, ?> map) {
712721
var keyType = actualTypeArguments[0];
713722
var valueType = actualTypeArguments[1];
714723

715-
var genericMap = new LinkedHashMap<>(map.size());
724+
var genericMap = (rawType == SortedMap.class) ? new TreeMap<>() : new LinkedHashMap<>(map.size());
716725

717726
for (var entry : map.entrySet()) {
718727
genericMap.put(coerceGeneric(entry.getKey(), keyType), coerceGeneric(entry.getValue(), valueType));
@@ -722,13 +731,13 @@ public static Object coerceGeneric(Object value, Type type) {
722731
} else {
723732
throw new IllegalArgumentException("Value is not a map.");
724733
}
725-
} else if (rawType == Set.class) {
734+
} else if (Set.class.isAssignableFrom(rawType)) {
726735
if (value == null) {
727736
yield null;
728737
} else if (value instanceof Collection<?> collection) {
729738
var elementType = actualTypeArguments[0];
730739

731-
var genericSet = new LinkedHashSet<>(collection.size());
740+
var genericSet = (rawType == SortedSet.class) ? new TreeSet<>() : new LinkedHashSet<>(collection.size());
732741

733742
for (var element : collection) {
734743
genericSet.add(coerceGeneric(element, elementType));

kilo-client/src/test/java/org/httprpc/kilo/beans/BeanAdapterTest.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.junit.jupiter.api.Test;
1919

2020
import java.lang.reflect.ParameterizedType;
21+
import java.lang.reflect.Type;
2122
import java.math.BigInteger;
2223
import java.net.URI;
2324
import java.nio.file.Path;
@@ -29,11 +30,16 @@
2930
import java.time.LocalDateTime;
3031
import java.time.LocalTime;
3132
import java.time.Period;
33+
import java.util.Arrays;
3234
import java.util.Date;
3335
import java.util.HashMap;
3436
import java.util.List;
3537
import java.util.Map;
38+
import java.util.SequencedMap;
39+
import java.util.SequencedSet;
3640
import java.util.Set;
41+
import java.util.SortedMap;
42+
import java.util.SortedSet;
3743
import java.util.UUID;
3844

3945
import static org.httprpc.kilo.util.Collections.*;
@@ -265,19 +271,32 @@ public void testPathCoercion() {
265271
@Test
266272
public void testListCoercion() {
267273
assertInstanceOf(List.class, BeanAdapter.coerce(listOf(), List.class));
268-
assertThrows(IllegalArgumentException.class, () -> BeanAdapter.coerce(123, List.class));
274+
275+
assertInstanceOf(List.class, BeanAdapter.coerceGeneric(listOf(), parameterizedTypeOf(List.class)));
276+
277+
assertThrows(IllegalArgumentException.class, () -> BeanAdapter.coerce(0, List.class));
269278
}
270279

271280
@Test
272281
public void testMapCoercion() {
273282
assertInstanceOf(Map.class, BeanAdapter.coerce(mapOf(), Map.class));
274-
assertThrows(IllegalArgumentException.class, () -> BeanAdapter.coerce(123, Map.class));
283+
284+
assertInstanceOf(Map.class, BeanAdapter.coerceGeneric(mapOf(), parameterizedTypeOf(Map.class)));
285+
assertInstanceOf(SequencedMap.class, BeanAdapter.coerceGeneric(mapOf(), parameterizedTypeOf(SequencedMap.class)));
286+
assertInstanceOf(SortedMap.class, BeanAdapter.coerceGeneric(mapOf(), parameterizedTypeOf(SortedMap.class)));
287+
288+
assertThrows(IllegalArgumentException.class, () -> BeanAdapter.coerce(0, Map.class));
275289
}
276290

277291
@Test
278292
public void testSetCoercion() {
279293
assertInstanceOf(Set.class, BeanAdapter.coerce(setOf(), Set.class));
280-
assertThrows(IllegalArgumentException.class, () -> BeanAdapter.coerce(123, Set.class));
294+
295+
assertInstanceOf(Set.class, BeanAdapter.coerceGeneric(setOf(), parameterizedTypeOf(Set.class)));
296+
assertInstanceOf(SequencedSet.class, BeanAdapter.coerceGeneric(setOf(), parameterizedTypeOf(SequencedSet.class)));
297+
assertInstanceOf(SortedSet.class, BeanAdapter.coerceGeneric(setOf(), parameterizedTypeOf(SortedSet.class)));
298+
299+
assertThrows(IllegalArgumentException.class, () -> BeanAdapter.coerce(0, Set.class));
281300
}
282301

283302
@Test
@@ -486,4 +505,27 @@ public void testToType() {
486505

487506
assertEquals(listOf(1, 2, 3), integers);
488507
}
508+
509+
private static Type parameterizedTypeOf(Class<?> rawType) {
510+
return new ParameterizedType() {
511+
@Override
512+
public Type[] getActualTypeArguments() {
513+
var actualTypeArguments = new Type[rawType.getTypeParameters().length];
514+
515+
Arrays.fill(actualTypeArguments, Object.class);
516+
517+
return actualTypeArguments;
518+
}
519+
520+
@Override
521+
public Type getRawType() {
522+
return rawType;
523+
}
524+
525+
@Override
526+
public Type getOwnerType() {
527+
return null;
528+
}
529+
};
530+
}
489531
}

0 commit comments

Comments
 (0)