Skip to content

Commit

Permalink
Merge 4bd9805 into 45be5aa
Browse files Browse the repository at this point in the history
  • Loading branch information
krasched committed Nov 20, 2020
2 parents 45be5aa + 4bd9805 commit 9f408f9
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 29 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ This order can be customized, see [§5 (Change the order in which annotations ar
Fields don't have to be Strings. You can configure collection fields or even any type you wish (or a collection of that type).

Some simple transformers are included and used by default, e.g. a String will automatically be converted to an integer, a
boolean value or even a collection as needed.
boolean value, an enum value, or even a collection as needed.

If you need more complex transformers, you can also implement your own by extending the `TypeTransformer` class, and specifying them in the `@TypeTransformers` annotation.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ public StringToEnumTypeTransformer(Class<E> enumClass) {
this.enumClass = enumClass;
}

@Override
public boolean isMatching(Class<?> sourceClass, Class<?> targetClass) {
return sourceClass.equals(String.class) && targetClass.equals(enumClass);
}

@Override
public E transform(final String value) {
return E.valueOf(enumClass, value.trim().replace(' ', '_').toUpperCase());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public boolean isMatching(Class<?> sourceClass, Class<?> targetClass) {
targetClass.isAssignableFrom(getTransformerTargetClass());
}

protected Class<?> getTransformerSourceClass() {
private Class<?> getTransformerSourceClass() {
Type[] genericTypes = determineTypeArguments();
return genericsAndCastingHelper.castTypeToClass(genericTypes[0]);
}

protected Class<?> getTransformerTargetClass() {
private Class<?> getTransformerTargetClass() {
Type[] genericTypes = determineTypeArguments();
return genericsAndCastingHelper.castTypeToClass(genericTypes[1]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ private void initialize(Field field) {
for(Class<? extends TypeTransformer> transformerClass : getAllTransformers(field)) {
availableTransformers.add(configBuilderFactory.getInstance(transformerClass));
}
genericsAndCastingHelper.getEnumTypeOrParameterIfApplicable(field)
.map(StringToEnumTypeTransformer::new)
.ifPresent(availableTransformers::add);

additionalOptions = field.isAnnotationPresent(Separator.class)? new Object[]{field.getAnnotation(Separator.class).value()} : new Object[]{","};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import com.google.common.collect.ImmutableMap;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;

public class GenericsAndCastingHelper {

Expand Down Expand Up @@ -60,4 +62,19 @@ else if(Collection.class.isAssignableFrom((Class<?>)((ParameterizedType)targetTy
public boolean isPrimitiveOrWrapper(Class targetClass) {
return primitiveToWrapperMapping.containsKey(targetClass) || primitiveToWrapperMapping.containsValue(targetClass);
}

public <E extends Enum<E>> Optional<Class<E>> getEnumTypeOrParameterIfApplicable(Field field) {
if (field.getType().isEnum()) {
return Optional.of((Class<E>) field.getType());
}

if (!Collection.class.isAssignableFrom(field.getType())) {
return Optional.empty();
}

Type collectionParameterType = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
return collectionParameterType instanceof Class && ((Class<?>) collectionParameterType).isEnum()
? Optional.of((Class<E>) collectionParameterType)
: Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,5 @@ public void testTransform() {
public void testIsMatching() {
assertThat(transformer.isMatching(String.class, TestEnum.class)).isTrue();
assertThat(transformer.isMatching(String.class, Integer.class)).isFalse();
assertThat(transformer.isMatching(String.class, Enum.class)).isTrue();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.tngtech.configbuilder.util;

import com.tngtech.configbuilder.annotation.typetransformer.*;
import com.tngtech.configbuilder.configuration.BuilderConfiguration;
import com.tngtech.configbuilder.configuration.ErrorMessageSetup;
import com.tngtech.configbuilder.exception.PrimitiveParsingException;
import org.junit.Before;
Expand All @@ -14,30 +13,31 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import static com.google.common.collect.Lists.newArrayList;
import static com.tngtech.configbuilder.util.FieldValueTransformerComponentTest.TestEnum.BAR;
import static com.tngtech.configbuilder.util.FieldValueTransformerComponentTest.TestEnum.FOO;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class FieldValueTransformerComponentTest {

public class TestTransformer extends TypeTransformer<String, Integer> {
public static class TestTransformer extends TypeTransformer<String, Integer> {
@Override
public Integer transform(String argument) {
return 1472;
}
}

public static class AnotherTestTransformer extends TypeTransformer<String, Integer> {
@Override
public Integer transform(String argument) {
return 1472;
}
enum TestEnum {
FOO, BAR
}

private class TestConfigClass {
private static class TestConfigClass {

@TypeTransformers({CharacterSeparatedStringToStringListTransformer.class})
private Collection<String> stringCollectionField;
Expand All @@ -46,31 +46,32 @@ private class TestConfigClass {
private Boolean boolField;
@TypeTransformers({TestTransformer.class})
private int otherIntField;
@TypeTransformers({AnotherTestTransformer.class})
private Integer integerField;
private Collection<Path> pathCollectionField;
private Collection<Integer> integerCollectionField;
private Collection<Object> objectCollectionField;
private TestEnum enumField;
private List<TestEnum> enumListField;
private Set<TestEnum> enumSetField;
}

@Mock
private ConfigBuilderFactory configBuilderFactory;
@Mock
private ErrorMessageSetup errorMessageSetup;
@Mock
private BuilderConfiguration builderConfiguration;

private FieldValueTransformer fieldValueTransformer;

private Field stringCollectionField;
private Field intField;
private Field doubleField;
private Field boolField;
private Field otherIntField;
private Field integerField;
private Field pathCollectionField;
private Field integerCollectionField;
private Field objectCollectionField;

private FieldValueTransformer fieldValueTransformer;
private Field enumField;
private Field enumListField;
private Field enumSetField;

@Before
public void setUp() throws Exception {
Expand All @@ -86,23 +87,25 @@ public void setUp() throws Exception {
when(configBuilderFactory.getInstance(StringOrPrimitiveToPrimitiveTransformer.class)).thenReturn(new StringOrPrimitiveToPrimitiveTransformer());
when(configBuilderFactory.getInstance(TestTransformer.class)).thenReturn(new TestTransformer());

this.fieldValueTransformer = new FieldValueTransformer(configBuilderFactory);

stringCollectionField = TestConfigClass.class.getDeclaredField("stringCollectionField");
intField = TestConfigClass.class.getDeclaredField("intField");
boolField = TestConfigClass.class.getDeclaredField("boolField");
otherIntField = TestConfigClass.class.getDeclaredField("otherIntField");
integerField = TestConfigClass.class.getDeclaredField("integerField");
pathCollectionField = TestConfigClass.class.getDeclaredField("pathCollectionField");
integerCollectionField = TestConfigClass.class.getDeclaredField("integerCollectionField");
doubleField = TestConfigClass.class.getDeclaredField("doubleField");
objectCollectionField = TestConfigClass.class.getDeclaredField("objectCollectionField");

this.fieldValueTransformer = new FieldValueTransformer(configBuilderFactory);
enumField = TestConfigClass.class.getDeclaredField("enumField");
enumListField = TestConfigClass.class.getDeclaredField("enumListField");
enumSetField = TestConfigClass.class.getDeclaredField("enumSetField");
}

@Test
public void testTransformingStringToStringCollection() {
List<String> actualResult = (List<String>) fieldValueTransformer.transformFieldValue(stringCollectionField, "Alpha,Beta,Gamma");
assertThat(actualResult).containsExactly("Alpha", "Beta", "Gamma");
Object actualResult = fieldValueTransformer.transformFieldValue(stringCollectionField, "Alpha,Beta,Gamma");
assertThat(actualResult).isEqualTo(newArrayList("Alpha", "Beta", "Gamma"));
}

@Test
Expand Down Expand Up @@ -136,25 +139,43 @@ public void testThatTransformersInAnnotationArePrioritized() {

@Test
public void testTransformingStringToPathCollection() {
Collection<Path> actualResult = (Collection<Path>) fieldValueTransformer.transformFieldValue(pathCollectionField, "/etc,/usr");
Object actualResult = fieldValueTransformer.transformFieldValue(pathCollectionField, "/etc,/usr");
assertThat(actualResult).isEqualTo(newArrayList(Paths.get("/etc"), Paths.get("/usr")));
}

@Test
public void testTransformingStringToIntegerCollection() {
Collection<Integer> actualResult = (Collection<Integer>) fieldValueTransformer.transformFieldValue(integerCollectionField, "3,4");
Object actualResult = fieldValueTransformer.transformFieldValue(integerCollectionField, "3,4");
assertThat(actualResult).isEqualTo(newArrayList(3, 4));
}

@Test
public void testTransformingStringToObjectCollection() {
Collection<Object> actualResult = (Collection<Object>) fieldValueTransformer.transformFieldValue(objectCollectionField, "someString,anotherString");
Object actualResult = fieldValueTransformer.transformFieldValue(objectCollectionField, "someString,anotherString");
assertThat(actualResult).isEqualTo(newArrayList("someString", "anotherString"));
}

@Test
public void testTransformingStringToEnum() {
Object actualResult = fieldValueTransformer.transformFieldValue(enumField, "FOO");
assertThat(actualResult).isEqualTo(FOO);
}

@Test
public void testTransformingStringToEnumList() {
Object actualResult = fieldValueTransformer.transformFieldValue(enumListField, "FOO, BAR, FOO");
assertThat(actualResult).isEqualTo(newArrayList(FOO, BAR, FOO));
}

@Test
public void testTransformingStringToEnumSet() {
Object actualResult = fieldValueTransformer.transformFieldValue(enumSetField, "BAR, FOO");
assertThat(actualResult).isEqualTo(EnumSet.allOf(TestEnum.class));
}

@Test
public void testThatValueTransformerIgnoresNull() {
Collection<Path> actualResult = (Collection<Path>) fieldValueTransformer.transformFieldValue(pathCollectionField, null);
Object actualResult = fieldValueTransformer.transformFieldValue(pathCollectionField, null);
assertThat(actualResult).isNull();
}
}
}

0 comments on commit 9f408f9

Please sign in to comment.