StringToEnumConverter.java

1
package fr.sii.ogham.core.convert;
2
3
import static java.lang.annotation.ElementType.TYPE;
4
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5
6
import java.lang.annotation.Documented;
7
import java.lang.annotation.Inherited;
8
import java.lang.annotation.Retention;
9
import java.lang.annotation.Target;
10
import java.lang.reflect.InvocationTargetException;
11
import java.lang.reflect.Method;
12
13
import fr.sii.ogham.core.exception.convert.ConversionException;
14
15
/**
16
 * Converts a string to a {@link Enum} value. It uses
17
 * {@link Enum#valueOf(Class, String)} to get the enum value by default.
18
 * 
19
 * <p>
20
 * If the enum is annotated with {@link FactoryMethod}, the name of the static
21
 * method is used to create the enum instance:
22
 * 
23
 * <pre>
24
 * {@code
25
 * {@literal @}FactoryMethod(name="fromNameOrValue")
26
 * enum MyEnum {
27
 *   A("1"),
28
 *   B("2");
29
 *   
30
 *   private final String value;
31
 *   MyEnum(String value) {
32
 *     this.value = value;
33
 *   }
34
 *   
35
 *   public String value() {
36
 *     return value;
37
 *   }
38
 *   
39
 *   public static MyEnum fromNameOrValue(String nameOrValue) {
40
 *      for (MyEnum e : values()) {
41
 *        if (e.value().equals(nameOrValue))
42
 *          return e;
43
 *        if (e.name().equals(nameOrValue))
44
 *          return e;
45
 *        throw new IllegalArgumentException("Unknown name or value: "+nameOrValue);
46
 *      }
47
 *   }
48
 * }
49
 * }
50
 * </pre>
51
 * 
52
 * 
53
 * @author Aurélien Baudet
54
 *
55
 */
56
@SuppressWarnings("squid:S1192")
57
public class StringToEnumConverter implements SupportingConverter {
58
59
	/**
60
	 * Idicates which method to use to instantiate the {@link Enum} instead of
61
	 * using {@link Enum#valueOf(Class, String)}.
62
	 * 
63
	 * @author Aurélien Baudet
64
	 */
65
	@Target(TYPE)
66
	@Retention(RUNTIME)
67
	@Documented
68
	@Inherited
69
	public static @interface FactoryMethod {
70
		/**
71
		 * The name of the factory method to use for instantiating the
72
		 * {@link Enum} instead of {@link Enum#valueOf(Class, String)}.
73
		 * 
74
		 * @return the name of the factory method
75
		 */
76
		String name();
77
	}
78
79
	@Override
80
	public <T> T convert(Object source, Class<T> targetType) {
81
		String name = (String) source;
82 4 1. convert : negated conditional → NO_COVERAGE
2. convert : negated conditional → NO_COVERAGE
3. convert : negated conditional → KILLED
4. convert : negated conditional → KILLED
		if (name == null || name.isEmpty()) {
83
			return null;
84
		}
85
		FactoryMethod annotation = targetType.getAnnotation(FactoryMethod.class);
86 2 1. convert : negated conditional → NO_COVERAGE
2. convert : negated conditional → KILLED
		if (annotation != null) {
87 2 1. convert : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → NO_COVERAGE
2. convert : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → KILLED
			return create(targetType, annotation.name(), name);
88
		}
89 2 1. convert : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → NO_COVERAGE
2. convert : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → KILLED
		return valueOf(targetType, name);
90
	}
91
92
	@Override
93
	public boolean supports(Class<?> sourceType, Class<?> targetType) {
94 18 1. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → NO_COVERAGE
2. supports : negated conditional → NO_COVERAGE
3. supports : negated conditional → SURVIVED
4. supports : negated conditional → NO_COVERAGE
5. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → TIMED_OUT
6. supports : negated conditional → TIMED_OUT
7. supports : negated conditional → TIMED_OUT
8. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED
9. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED
10. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED
11. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED
12. supports : replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED
13. supports : negated conditional → KILLED
14. supports : negated conditional → KILLED
15. supports : negated conditional → KILLED
16. supports : negated conditional → KILLED
17. supports : negated conditional → KILLED
18. supports : negated conditional → KILLED
		return String.class.isAssignableFrom(sourceType) && Enum.class.isAssignableFrom(targetType);
95
	}
96
97
	@SuppressWarnings("unchecked")
98
	private static <T> T create(Class<T> targetType, String methodName, String value) {
99
		try {
100
			Method method = targetType.getMethod(methodName, String.class);
101 2 1. create : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::create → NO_COVERAGE
2. create : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::create → KILLED
			return (T) method.invoke(null, value);
102
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
103
			throw new ConversionException("Failed to convert " + value + " into Enum using custom factory method", e);
104
		}
105
	}
106
107
	@SuppressWarnings({ "unchecked", "rawtypes" })
108
	private static <T> T valueOf(Class<T> targetType, String name) {
109
		try {
110 2 1. valueOf : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::valueOf → NO_COVERAGE
2. valueOf : replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::valueOf → KILLED
			return (T) Enum.valueOf((Class<Enum>) targetType, name.trim());
111
		} catch (IllegalArgumentException e) {
112
			throw new ConversionException("Failed to convert " + name + " into Enum", e);
113
		}
114
	}
115
116
}

Mutations

82

1.1
Location : convert
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : convert
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
negated conditional → KILLED

3.3
Location : convert
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
negated conditional → KILLED

4.4
Location : convert
Killed by : none
negated conditional → NO_COVERAGE

86

1.1
Location : convert
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
negated conditional → KILLED

2.2
Location : convert
Killed by : none
negated conditional → NO_COVERAGE

87

1.1
Location : convert
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → KILLED

2.2
Location : convert
Killed by : none
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → NO_COVERAGE

89

1.1
Location : convert
Killed by : none
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → NO_COVERAGE

2.2
Location : convert
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::convert → KILLED

94

1.1
Location : supports
Killed by : oghamall.it.configuration.EmptyBuilderTest.emailSenderManuallyRegisteredButUnconfiguredTemplateParsersCantHandleMultiTemplateContent(oghamall.it.configuration.EmptyBuilderTest)
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED

2.2
Location : supports
Killed by : oghamcloudhopper.it.ConnectionFailureTest.invalidSystemId(oghamcloudhopper.it.ConnectionFailureTest)
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED

3.3
Location : supports
Killed by : oghamjavamail.it.builder.OverridePropertiesTest.overrideProperties(oghamjavamail.it.builder.OverridePropertiesTest)
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED

4.4
Location : supports
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED

5.5
Location : supports
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → KILLED

6.6
Location : supports
Killed by : none
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → TIMED_OUT

7.7
Location : supports
Killed by : none
replaced boolean return with true for fr/sii/ogham/core/convert/StringToEnumConverter::supports → NO_COVERAGE

8.8
Location : supports
Killed by : none
negated conditional → NO_COVERAGE

9.9
Location : supports
Killed by : none
negated conditional → TIMED_OUT

10.10
Location : supports
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
negated conditional → KILLED

11.11
Location : supports
Killed by : none
negated conditional → SURVIVED

12.12
Location : supports
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
negated conditional → KILLED

13.13
Location : supports
Killed by : none
negated conditional → NO_COVERAGE

14.14
Location : supports
Killed by : none
negated conditional → TIMED_OUT

15.15
Location : supports
Killed by : oghamcloudhopper.it.ConnectionFailureTest.invalidSystemId(oghamcloudhopper.it.ConnectionFailureTest)
negated conditional → KILLED

16.16
Location : supports
Killed by : oghamjavamail.it.builder.OverridePropertiesTest.overrideProperties(oghamjavamail.it.builder.OverridePropertiesTest)
negated conditional → KILLED

17.17
Location : supports
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
negated conditional → KILLED

18.18
Location : supports
Killed by : oghamall.it.configuration.EmptyBuilderTest.emailSenderManuallyRegisteredButUnconfiguredTemplateParsersCantHandleMultiTemplateContent(oghamall.it.configuration.EmptyBuilderTest)
negated conditional → KILLED

101

1.1
Location : create
Killed by : none
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::create → NO_COVERAGE

2.2
Location : create
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::create → KILLED

110

1.1
Location : valueOf
Killed by : none
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::valueOf → NO_COVERAGE

2.2
Location : valueOf
Killed by : oghamcore.ut.core.convert.StringToEnumConverterSpec
replaced return value with null for fr/sii/ogham/core/convert/StringToEnumConverter::valueOf → KILLED

Active mutators

Tests examined


Report generated by PIT OGHAM