Skip to content

Commit

Permalink
NO MERGE - rename some mapper methods, ...
Browse files Browse the repository at this point in the history
  • Loading branch information
ljacqu committed Aug 21, 2023
1 parent 9702206 commit 0a102d1
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 43 deletions.
9 changes: 4 additions & 5 deletions src/main/java/ch/jalu/configme/beanmapper/Mapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ public interface Mapper {
* is a Map of values.
*
* @param value the value to convert (typically a Map)
* @param typeInformation the required type
* @param targetType the required type
* @param errorRecorder error recorder to register errors even if a valid value is returned
* @return object of the given type, or null if not possible
*/
@Nullable Object convertToBean(@Nullable Object value, @NotNull TypeInfo typeInformation,
@Nullable Object convertToBean(@Nullable Object value, @NotNull TypeInfo targetType,
@NotNull ConvertErrorRecorder errorRecorder);

/**
Expand All @@ -35,10 +35,9 @@ public interface Mapper {
* @param <T> the class type
* @return object of the given type, or null if not possible
*/
@Nullable
@SuppressWarnings("unchecked")
default <T> T convertToBean(@Nullable Object value, @NotNull Class<T> clazz,
@NotNull ConvertErrorRecorder errorRecorder) {
default <T> @Nullable T convertToBean(@Nullable Object value, @NotNull Class<T> clazz,
@NotNull ConvertErrorRecorder errorRecorder) {
return (T) convertToBean(value, new TypeInfo(clazz), errorRecorder);
}

Expand Down
55 changes: 25 additions & 30 deletions src/main/java/ch/jalu/configme/beanmapper/MapperImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,13 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
// ---------

@Override
public @Nullable Object convertToBean(@Nullable Object value, @NotNull TypeInfo beanType,
public @Nullable Object convertToBean(@Nullable Object value, @NotNull TypeInfo targetType,
@NotNull ConvertErrorRecorder errorRecorder) {
if (value == null) {
return null;
}

return convertValueForType(createRootMappingContext(beanType, errorRecorder), value);
return convertValueForType(createRootMappingContext(targetType, errorRecorder), value);
}

/**
Expand All @@ -198,20 +198,14 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
* @return object whose type matches the one in the mapping context, or null if not applicable
*/
protected @Nullable Object convertValueForType(@NotNull MappingContext context, @Nullable Object value) {
Class<?> rawClass = context.getTypeInformation().toClass();
if (rawClass == null) {
throw new ConfigMeMapperException(context, "Cannot determine required type");
}

// Step 1: check if a value transformer can perform a simple conversion
Optional<Object> conversionAsLeafValue =
leafValueHandler.convert(value, context);
// Step 1: check if the value is a leaf
Optional<Object> conversionAsLeafValue = leafValueHandler.convert(value, context);
if (conversionAsLeafValue.isPresent()) {
return conversionAsLeafValue.get();
}

// Step 2: check if we have a special type like List that is handled separately
Object result = handleSpecialTypes(context, value);
Object result = convertSpecialTypes(context, value);
if (result != null) {
return result;
}
Expand All @@ -221,20 +215,20 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
}

/**
* Handles special types in the bean mapping process which require special handling.
* Converts types in the bean mapping process which require special handling.
*
* @param context the mapping context
* @param value the value to convert from
* @return object whose type matches the one in the mapping context, or null if not applicable
*/
protected @Nullable Object handleSpecialTypes(@NotNull MappingContext context, @Nullable Object value) {
final Class<?> rawClass = context.getTypeInformation().toClass();
if (Collection.class.isAssignableFrom(rawClass)) {
return createCollection(context, value);
protected @Nullable Object convertSpecialTypes(@NotNull MappingContext context, @Nullable Object value) {
final Class<?> rawClass = context.getTargetAsClassOrThrow();
if (Iterable.class.isAssignableFrom(rawClass)) {
return convertToCollection(context, value);
} else if (Map.class.isAssignableFrom(rawClass)) {
return createMap(context, value);
return convertToMap(context, value);
} else if (Optional.class.isAssignableFrom(rawClass)) {
return createOptional(context, value);
return convertOptional(context, value);
}
return null;
}
Expand All @@ -249,9 +243,9 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
* @return Collection property from the value, or null if not applicable
*/
@SuppressWarnings({"unchecked", "rawtypes"})
protected @Nullable Collection<?> createCollection(@NotNull MappingContext context, @Nullable Object value) {
protected @Nullable Collection<?> convertToCollection(@NotNull MappingContext context, @Nullable Object value) {
if (value instanceof Iterable<?>) {
TypeInfo entryType = context.getGenericTypeInfoOrFail(0);
TypeInfo entryType = context.getTargetTypeArgumentOrThrow(0);
Collection result = createCollectionMatchingType(context);

int index = 0;
Expand All @@ -275,7 +269,7 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
* @return Collection of matching type
*/
protected @NotNull Collection<?> createCollectionMatchingType(@NotNull MappingContext mappingContext) {
Class<?> collectionType = mappingContext.getTypeInformation().toClass();
Class<?> collectionType = mappingContext.getTargetAsClassOrThrow();
if (collectionType.isAssignableFrom(ArrayList.class)) {
return new ArrayList<>();
} else if (collectionType.isAssignableFrom(LinkedHashSet.class)) {
Expand All @@ -295,12 +289,12 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
* @return Map property, or null if not applicable
*/
@SuppressWarnings({"unchecked", "rawtypes"})
protected @Nullable Map<?, ?> createMap(@NotNull MappingContext context, @Nullable Object value) {
protected @Nullable Map<?, ?> convertToMap(@NotNull MappingContext context, @Nullable Object value) {
if (value instanceof Map<?, ?>) {
if (context.getGenericTypeInfoOrFail(0).toClass() != String.class) {
if (context.getTargetTypeArgumentOrThrow(0).toClass() != String.class) {
throw new ConfigMeMapperException(context, "The key type of maps may only be of String type");
}
TypeInfo mapValueType = context.getGenericTypeInfoOrFail(1);
TypeInfo mapValueType = context.getTargetTypeArgumentOrThrow(1);

Map<String, ?> entries = (Map<String, ?>) value;
Map result = createMapMatchingType(context);
Expand All @@ -325,7 +319,7 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
* @return Map of matching type
*/
protected @NotNull Map<?, ?> createMapMatchingType(@NotNull MappingContext mappingContext) {
Class<?> mapType = mappingContext.getTypeInformation().toClass();
Class<?> mapType = mappingContext.getTargetAsClassOrThrow();
if (mapType.isAssignableFrom(LinkedHashMap.class)) {
return new LinkedHashMap<>();
} else if (mapType.isAssignableFrom(TreeMap.class)) {
Expand All @@ -337,8 +331,9 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,

// -- Optional

protected @NotNull Object createOptional(@NotNull MappingContext context, @Nullable Object value) {
MappingContext childContext = context.createChild("[v]", context.getGenericTypeInfoOrFail(0));
// Return value is never null, but if someone wants to override this, it's fine for it to be null
protected @Nullable Object convertOptional(@NotNull MappingContext context, @Nullable Object value) {
MappingContext childContext = context.createChild("$opt", context.getTargetTypeArgumentOrThrow(0));
Object result = convertValueForType(childContext, value);
return Optional.ofNullable(result);
}
Expand All @@ -358,8 +353,8 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
return null;
}

Collection<BeanPropertyDescription> properties = beanDescriptionFactory.getAllProperties(
context.getTypeInformation().toClass());
Collection<BeanPropertyDescription> properties =
beanDescriptionFactory.getAllProperties(context.getTargetAsClassOrThrow());
// Check that we have properties (or else we don't have a bean)
if (properties.isEmpty()) {
return null;
Expand Down Expand Up @@ -391,7 +386,7 @@ public MapperImpl(@NotNull BeanDescriptionFactory beanDescriptionFactory,
*/
protected @NotNull Object createBeanMatchingType(@NotNull MappingContext mappingContext) {
// clazz is never null given the only path that leads to this method already performs that check
final Class<?> clazz = mappingContext.getTypeInformation().toClass();
final Class<?> clazz = mappingContext.getTargetAsClassOrThrow();
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (ReflectiveOperationException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ public interface MappingContext {
/**
* @return the required type the value needs to be mapped to
*/
@NotNull TypeInfo getTypeInformation();
@NotNull TypeInfo getTargetType();

default @NotNull Class<?> getTargetAsClassOrThrow() {
Class<?> targetClass = getTargetType().toClass();
if (targetClass == null) {
throw new ConfigMeMapperException(this,
"The target type '" + getTargetType() + "' cannot be converted to a class");
}
return targetClass;
}

/**
* Convenience method: gets the generic type info for the given index and ensures that the generic type information
Expand All @@ -31,8 +40,8 @@ public interface MappingContext {
* @param index the index to get generic type info for
* @return the generic type info (throws exception if absent or not precise enough)
*/
default @NotNull TypeInfo getGenericTypeInfoOrFail(int index) {
TypeInfo typeArgument = getTypeInformation().getTypeArgumentInfo(index);
default @NotNull TypeInfo getTargetTypeArgumentOrThrow(int index) {
TypeInfo typeArgument = getTargetType().getTypeArgumentInfo(index);
if (typeArgument == null || typeArgument.toClass() == null) {
throw new ConfigMeMapperException(this,
"The generic type " + index + " is not well defined");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected MappingContextImpl(@NotNull String path, @NotNull TypeInfo typeInforma
}

@Override
public @NotNull TypeInfo getTypeInformation() {
public @NotNull TypeInfo getTargetType() {
return typeInformation;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static List<MapperTypeHandler> createDefaultHandlers() {
public @NotNull Optional<Object> convert(@Nullable Object value,
@NotNull MappingContext mappingContext) {
Object result;
TypeInfo targetType = mappingContext.getTypeInformation();
TypeInfo targetType = mappingContext.getTargetType();
ConvertErrorRecorder errorRecorder = mappingContext.getErrorRecorder();

for (MapperTypeHandler typeHandler : typeHandlers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
public class SingleValueToCollectionMapper extends MapperImpl {

@Override
protected Collection<?> createCollection(@NotNull MappingContext context, Object value) {
protected Collection<?> convertToCollection(@NotNull MappingContext context, Object value) {
if (!(value instanceof Iterable)) {
Collection<?> coll = super.createCollection(context, Collections.singleton(value));
Collection<?> coll = super.convertToCollection(context, Collections.singleton(value));
// Register error to trigger a rewrite with the proper structure
context.registerError("Found single value where a collection is expected");
return isCollectionWithOneElement(coll) ? coll : null;
}
return super.createCollection(context, value);
return super.convertToCollection(context, value);
}

private static boolean isCollectionWithOneElement(Collection<?> coll) {
Expand Down

0 comments on commit 0a102d1

Please sign in to comment.