Skip to content

Commit bfc32c2

Browse files
committed
Support wildcard types in the PojoCodec
JAVA-3390
1 parent 3c895dc commit bfc32c2

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

bson/src/main/org/bson/codecs/pojo/TypeData.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.lang.reflect.ParameterizedType;
2222
import java.lang.reflect.Type;
2323
import java.lang.reflect.TypeVariable;
24+
import java.lang.reflect.WildcardType;
2425
import java.util.ArrayList;
2526
import java.util.Collections;
2627
import java.util.HashMap;
@@ -79,6 +80,8 @@ private static <T> void getNestedTypeData(final TypeData.Builder<T> builder, fin
7980
getNestedTypeData(paramBuilder, argType);
8081
}
8182
builder.addTypeParameter(paramBuilder.build());
83+
} else if (type instanceof WildcardType) {
84+
builder.addTypeParameter(TypeData.builder((Class) ((WildcardType) type).getUpperBounds()[0]).build());
8285
} else if (type instanceof TypeVariable) {
8386
builder.addTypeParameter(TypeData.builder(Object.class).build());
8487
} else if (type instanceof Class) {

bson/src/test/unit/org/bson/codecs/pojo/ClassModelTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.bson.codecs.pojo;
1818

1919
import org.bson.codecs.pojo.entities.CollectionNestedPojoModel;
20+
import org.bson.codecs.pojo.entities.ConcreteAndNestedAbstractInterfaceModel;
2021
import org.bson.codecs.pojo.entities.GenericHolderModel;
22+
import org.bson.codecs.pojo.entities.InterfaceBasedModel;
2123
import org.bson.codecs.pojo.entities.NestedGenericHolderMapModel;
2224
import org.bson.codecs.pojo.entities.PropertySelectionModel;
2325
import org.bson.codecs.pojo.entities.ShapeHolderCircleModel;
@@ -94,6 +96,15 @@ public void testCollectionNestedPojoModelPropertyTypes() {
9496
assertEquals(listMapSet, classModel.getPropertyModel("listMapSetSimple").getTypeData());
9597
}
9698

99+
@Test
100+
@SuppressWarnings("rawtypes")
101+
public void testWildcardModel() {
102+
TypeData<InterfaceBasedModel> model = TypeData.builder(InterfaceBasedModel.class).build();
103+
TypeData<List> wildcard = TypeData.builder(List.class).addTypeParameter(model).build();
104+
ClassModel<?> classModel = ClassModel.builder(ConcreteAndNestedAbstractInterfaceModel.class).build();
105+
assertEquals(wildcard, classModel.getPropertyModel("wildcardList").getTypeData());
106+
}
107+
97108
@Test
98109
public void testPropertySelection() {
99110
ClassModel<PropertySelectionModel> classModel = ClassModel.builder(PropertySelectionModel.class).build();

bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@
2626
import org.bson.codecs.MapCodec;
2727
import org.bson.codecs.configuration.CodecConfigurationException;
2828
import org.bson.codecs.configuration.CodecRegistry;
29+
import org.bson.codecs.pojo.entities.AbstractInterfaceModel;
2930
import org.bson.codecs.pojo.entities.AsymmetricalCreatorModel;
3031
import org.bson.codecs.pojo.entities.AsymmetricalIgnoreModel;
3132
import org.bson.codecs.pojo.entities.AsymmetricalModel;
33+
import org.bson.codecs.pojo.entities.ConcreteAndNestedAbstractInterfaceModel;
3234
import org.bson.codecs.pojo.entities.ConcreteCollectionsModel;
35+
import org.bson.codecs.pojo.entities.ConcreteStandAloneAbstractInterfaceModel;
3336
import org.bson.codecs.pojo.entities.ConstructorNotPublicModel;
3437
import org.bson.codecs.pojo.entities.ConventionModel;
3538
import org.bson.codecs.pojo.entities.ConverterModel;
3639
import org.bson.codecs.pojo.entities.CustomPropertyCodecOptionalModel;
3740
import org.bson.codecs.pojo.entities.GenericTreeModel;
41+
import org.bson.codecs.pojo.entities.InterfaceBasedModel;
3842
import org.bson.codecs.pojo.entities.InvalidCollectionModel;
3943
import org.bson.codecs.pojo.entities.InvalidGetterAndSetterModel;
4044
import org.bson.codecs.pojo.entities.InvalidMapModel;
@@ -77,6 +81,7 @@
7781

7882
import static java.lang.String.format;
7983
import static java.util.Arrays.asList;
84+
import static java.util.Collections.singletonList;
8085
import static org.bson.codecs.configuration.CodecRegistries.fromCodecs;
8186
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
8287
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
@@ -253,6 +258,23 @@ public void testUseGettersForSettersConvention() {
253258
roundTrip(builder, new MapGetterMutableModel(Collections.singletonMap("a", 3)), "{mapField: {a: 3}}");
254259
}
255260

261+
@Test
262+
public void testWithWildcardListField() {
263+
ClassModel<InterfaceBasedModel> interfaceBasedModelClassModel =
264+
ClassModel.builder(InterfaceBasedModel.class).enableDiscriminator(true).build();
265+
PojoCodecProvider.Builder builder = PojoCodecProvider.builder().automatic(true)
266+
.register(interfaceBasedModelClassModel)
267+
.register(AbstractInterfaceModel.class, ConcreteStandAloneAbstractInterfaceModel.class,
268+
ConcreteAndNestedAbstractInterfaceModel.class);
269+
270+
roundTrip(builder,
271+
new ConcreteAndNestedAbstractInterfaceModel("A",
272+
singletonList(new ConcreteStandAloneAbstractInterfaceModel("B"))),
273+
"{'_t': 'org.bson.codecs.pojo.entities.ConcreteAndNestedAbstractInterfaceModel', 'name': 'A', "
274+
+ " 'wildcardList': [{'_t': 'org.bson.codecs.pojo.entities.ConcreteStandAloneAbstractInterfaceModel', "
275+
+ "'name': 'B'}]}");
276+
}
277+
256278
@Test(expected = CodecConfigurationException.class)
257279
public void testUseGettersForSettersConventionInvalidTypeForCollection() {
258280
PojoCodecProvider.Builder builder = getPojoCodecProviderBuilder(CollectionsGetterMutableModel.class)

bson/src/test/unit/org/bson/codecs/pojo/entities/ConcreteAndNestedAbstractInterfaceModel.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919

2020
import org.bson.codecs.pojo.annotations.BsonProperty;
2121

22+
import java.util.List;
23+
2224
public final class ConcreteAndNestedAbstractInterfaceModel extends AbstractInterfaceModel {
2325
@BsonProperty(useDiscriminator = true)
2426
private InterfaceBasedModel child;
27+
private List<? extends InterfaceBasedModel> wildcardList;
2528

2629
public ConcreteAndNestedAbstractInterfaceModel() {
2730
super();
@@ -32,6 +35,12 @@ public ConcreteAndNestedAbstractInterfaceModel(final String name, final Interfac
3235
this.child = child;
3336
}
3437

38+
public ConcreteAndNestedAbstractInterfaceModel(final String name, final List<? extends InterfaceBasedModel> wildcardList) {
39+
super(name);
40+
this.child = null;
41+
this.wildcardList = wildcardList;
42+
}
43+
3544
public InterfaceBasedModel getChild() {
3645
return child;
3746
}
@@ -40,6 +49,14 @@ public void setChild(final InterfaceBasedModel child) {
4049
this.child = child;
4150
}
4251

52+
public List<? extends InterfaceBasedModel> getWildcardList() {
53+
return wildcardList;
54+
}
55+
56+
public void setWildcardList(final List<? extends InterfaceBasedModel> wildcardList) {
57+
this.wildcardList = wildcardList;
58+
}
59+
4360
@Override
4461
public boolean equals(final Object o) {
4562
if (this == o) {

0 commit comments

Comments
 (0)