Skip to content

Commit

Permalink
forward port #2519
Browse files Browse the repository at this point in the history
fixes #2531
  • Loading branch information
evanchooly committed Sep 9, 2023
1 parent e09b3e3 commit e01f689
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public <T> Codec<T> get(TypeWithTypeParameters<T> type, PropertyCodecRegistry re
} catch (CodecConfigurationException e) {
if (valueType.getType().equals(Object.class)) {
try {
return (Codec<T>) registry.get(TypeData.builder(Collection.class).build());
return (Codec<T>) registry.get(TypeData.get(Collection.class));
} catch (CodecConfigurationException e1) {
// Ignore and return original exception
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public <T> Codec<T> get(TypeWithTypeParameters<T> type, PropertyCodecRegistry re
} catch (CodecConfigurationException e) {
if (valueType.getType().equals(Object.class)) {
try {
return (Codec<T>) registry.get(TypeData.builder(Map.class).build());
return (Codec<T>) registry.get(TypeData.get(Map.class));
} catch (CodecConfigurationException e1) {
// Ignore and return original exception
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ public abstract class MorphiaPropertyCodecProvider implements PropertyCodecProvi
protected TypeWithTypeParameters<?> getType(List<? extends TypeWithTypeParameters<?>> typeParameters, int position) {
return typeParameters.size() > position
? typeParameters.get(position)
: TypeData.builder(Object.class).build();
: TypeData.get(Object.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public TypeData<?> getTypeData(Class<?> type, TypeData<?> suggested, Type generi
if (map != null) {
Type mapped = map.get(((TypeVariable<?>) genericType).getName());
if (mapped != null) {
suggested = TypeData.newInstance(mapped);
suggested = TypeData.get(mapped);
}
}
}
Expand Down
43 changes: 30 additions & 13 deletions core/src/main/java/dev/morphia/mapping/codec/pojo/TypeData.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,26 @@
public class TypeData<T> implements TypeWithTypeParameters<T> {

private final Class<T> type;
private final List<TypeData<?>> typeParameters;
private final List<TypeData<?>> typeParameters = new ArrayList<>();
private boolean array;

/**
* Creates a new TypeData with the concrete type and type parameters around it.
* <p>
* e.g., List&lt;Address&gt; would be
*
* <pre>
* <code>
* new TypeData(Address.class, TypeData.builder(List.class).build())
* </code>
* </pre>
*
* @param type the type
*/
public TypeData(Class<T> type) {
this.type = type;
}

/**
* Creates a new TypeData with the concrete type and type parameters around it.
* <p>
Expand All @@ -54,7 +71,7 @@ public class TypeData<T> implements TypeWithTypeParameters<T> {
*/
public TypeData(Class<T> type, List<TypeData<?>> typeParameters) {
this.type = type;
this.typeParameters = typeParameters;
this.typeParameters.addAll(typeParameters);
}

/**
Expand All @@ -69,13 +86,13 @@ public static <T> Builder<T> builder(Class<T> type) {
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private static TypeData<?> getTypeData(Type type) {
public static TypeData<?> get(Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
TypeParameters parameters = TypeParameters.of(pType);
Builder paramBuilder = TypeData.builder((Class) pType.getRawType());
for (Type argType : parameters) {
paramBuilder.addTypeParameter(getTypeData(argType));
paramBuilder.addTypeParameter(get(argType));
}
return paramBuilder.build();
} else if (type instanceof WildcardType) {
Expand All @@ -84,18 +101,18 @@ private static TypeData<?> getTypeData(Type type) {
Type[] bounds = upperBounds != null
? upperBounds
: wildcardType.getLowerBounds();
return WildCardTypeData.builder(getTypeData(bounds[0]), upperBounds != null).build();
return new WildCardTypeData(get(bounds[0]), upperBounds != null);
} else if (type instanceof TypeVariable) {
return TypeData.builder(Object.class).build();
} else if (type instanceof Class) {
Builder builder = TypeData.builder((Class) type);
var typeData = new TypeData((Class) type);
for (Type argType : TypeParameters.of(type)) {
builder.addTypeParameter(getTypeData(argType));
typeData.typeParameters.add(argType.equals(type) ? type : get(argType));
}
return builder.build();
return typeData;
} else if (type instanceof GenericArrayType) {
GenericArrayType arrayType = (GenericArrayType) type;
TypeData<?> typeData = getTypeData(arrayType.getGenericComponentType());
TypeData<?> typeData = get(arrayType.getGenericComponentType());
typeData.setArray(true);
return typeData;
}
Expand Down Expand Up @@ -211,8 +228,8 @@ private static String nestedTypeParameters(List<TypeData<?>> typeParameters) {
* @param field the field to analyze
* @return the new TypeData information
*/
public static TypeData<?> newInstance(Field field) {
return newInstance(field.getGenericType());
public static TypeData<?> get(Field field) {
return get(field.getGenericType());
}

/**
Expand All @@ -221,7 +238,7 @@ public static TypeData<?> newInstance(Field field) {
* @param method the method to analyze
* @return the new TypeData information
*/
public static TypeData<?> newInstance(Method method) {
public static TypeData<?> get(Method method) {
return newInstance(method.getGenericReturnType());
}

Expand All @@ -243,7 +260,7 @@ public static <T> TypeData<T> newInstance(Type genericType) {
* }
* return builder.build();
*/
return (TypeData<T>) getTypeData(genericType);
return (TypeData<T>) get(genericType);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,6 @@ public class WildCardTypeData<T> extends TypeData<T> {
this.upperBound = upperBound;
}

/**
* Creates a builder
*
* @param bound
* @param upperBound true if the type parameters represent an upper bound
* @return the new builder
*/
public static Builder builder(TypeData<?> bound, boolean upperBound) {
return new Builder(bound, upperBound);
}

@Override
public int hashCode() {
return Objects.hash(super.hashCode(), upperBound);
Expand All @@ -52,52 +41,8 @@ public boolean equals(Object o) {
return upperBound == that.upperBound;
}

/**
* @return true if the type parameters represent an upper bound
*/
public boolean isUpperBound() {
return upperBound;
}

@Override
public String toString() {
/*
* String value = type.getSimpleName();
* if (!typeParameters.isEmpty()) {
* StringJoiner joiner = new StringJoiner(", ", "<", ">");
* typeParameters.forEach(t -> {
* joiner.add(t.toString());
* });
* value += joiner;
* }
*/

return (upperBound ? "? extends " : "? super ") + super.toString();
}

/**
* A builder for WildCardTypeData
*/
public static class Builder {
private final boolean upperBound;
private final TypeData typeData;

/**
* Creates a builder
*
* @param bound
* @param upperBound true if the type parameters represent an upper bound
*/
public Builder(TypeData bound, boolean upperBound) {
this.typeData = bound;
this.upperBound = upperBound;
}

/**
* @return the new WildCardTypeData
*/
public WildCardTypeData build() {
return new WildCardTypeData(typeData, upperBound);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void apply(Mapper mapper, EntityModelBuilder builder) {
for (Class<?> type : list) {
for (Field field : type.getDeclaredFields()) {

TypeData<?> typeData = builder.getTypeData(type, TypeData.newInstance(field), field.getGenericType());
TypeData<?> typeData = builder.getTypeData(type, TypeData.get(field), field.getGenericType());
try {
builder.addProperty()
.name(field.getName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private List<Methods> processMethods(Class<?> type) {

private void addProperties(EntityModelBuilder builder, Set<Methods> properties) {
for (Methods methods : properties) {
TypeData<?> typeData = entityModelBuilder.getTypeData(methods.type, TypeData.newInstance(methods.getter),
TypeData<?> typeData = entityModelBuilder.getTypeData(methods.type, TypeData.get(methods.getter),
methods.getter.getGenericReturnType());

entityModelBuilder.addProperty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.util.List;
import java.util.Locale;

import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.mapping.codec.pojo.TypeData;
import dev.morphia.test.TestBase;
import dev.morphia.test.mapping.codec.pojo.generics.FullHashMap;
Expand All @@ -22,7 +24,7 @@
public class TypeDataTest extends TestBase {
@Test
public void testWildcards() throws NoSuchFieldException {
TypeData<?> typeData = TypeData.newInstance(WildCard.class.getDeclaredField("listOfLists"));
TypeData<?> typeData = TypeData.get(WildCard.class.getDeclaredField("listOfLists"));

assertEquals(typeData.getType(), List.class);
List<TypeData<?>> typeParameters = typeData.getTypeParameters();
Expand Down Expand Up @@ -64,10 +66,16 @@ public void testSubtypes() {
});
}

@Test
public void testRecursiveTypes() {
TypeData.get(MyEntity.class);
TypeData.get(MyEmbeddedEntity.class);
}

private static void typeData(Class<?> owner, String fieldName, Class<?> fieldType, Class<?>... parameterTypes)
throws NoSuchFieldException {
Field field = owner.getDeclaredField(fieldName);
TypeData<?> typeData = TypeData.newInstance(field);
TypeData<?> typeData = TypeData.get(field);
assertEquals(typeData.getType(), fieldType);
List<TypeData<?>> typeParameters = typeData.getTypeParameters();
assertEquals(typeParameters.size(), parameterTypes.length);
Expand All @@ -79,4 +87,19 @@ private static void typeData(Class<?> owner, String fieldName, Class<?> fieldTyp
private static class WildCard {
private List<? extends List<String>> listOfLists;
}

private static class MongoEntity<T> {
}

@Entity
private static class MyEmbeddedEntity extends MongoEntity<MyEmbeddedEntity> {
}

@Entity
private static class MyEntity {
@Id
private String id;
private String address;
List<MyEmbeddedEntity> embeddedEntities;
}
}

0 comments on commit e01f689

Please sign in to comment.