This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-cli.git
commit c6605dcb97f50c78a2fdc14af5aaea67777fbed5 Author: Gary Gregory <[email protected]> AuthorDate: Sun Apr 7 14:48:04 2024 -0400 Don't use a global variable Simplify new APIs --- src/main/java/org/apache/commons/cli/Option.java | 2 +- .../java/org/apache/commons/cli/OptionBuilder.java | 2 +- .../apache/commons/cli/PatternOptionBuilder.java | 21 +-- .../java/org/apache/commons/cli/TypeHandler.java | 84 ++++----- .../java/org/apache/commons/cli/OptionTest.java | 22 +-- .../commons/cli/PatternOptionBuilderTest.java | 13 +- .../org/apache/commons/cli/TypeHandlerTest.java | 197 +++++++++------------ 7 files changed, 143 insertions(+), 198 deletions(-) diff --git a/src/main/java/org/apache/commons/cli/Option.java b/src/main/java/org/apache/commons/cli/Option.java index 8c54ce2..593a418 100644 --- a/src/main/java/org/apache/commons/cli/Option.java +++ b/src/main/java/org/apache/commons/cli/Option.java @@ -582,7 +582,7 @@ public class Option implements Cloneable, Serializable { * @since 1.7.0 */ public Converter<?, ?> getConverter() { - return converter == null ? TypeHandler.getConverter(type) : converter; + return converter == null ? TypeHandler.getDefault().getConverter(type) : converter; } /** diff --git a/src/main/java/org/apache/commons/cli/OptionBuilder.java b/src/main/java/org/apache/commons/cli/OptionBuilder.java index 4a377f4..fb98545 100644 --- a/src/main/java/org/apache/commons/cli/OptionBuilder.java +++ b/src/main/java/org/apache/commons/cli/OptionBuilder.java @@ -109,7 +109,7 @@ public final class OptionBuilder { option.setOptionalArg(optionalArg); option.setArgs(argCount); option.setType(type); - option.setConverter(TypeHandler.getConverter(type)); + option.setConverter(TypeHandler.getDefault().getConverter(type)); option.setValueSeparator(valueSeparator); option.setArgName(argName); } finally { diff --git a/src/main/java/org/apache/commons/cli/PatternOptionBuilder.java b/src/main/java/org/apache/commons/cli/PatternOptionBuilder.java index db5c3b7..e2286c9 100644 --- a/src/main/java/org/apache/commons/cli/PatternOptionBuilder.java +++ b/src/main/java/org/apache/commons/cli/PatternOptionBuilder.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.FileInputStream; import java.net.URL; import java.util.Date; +import java.util.Map; /** * Allows Options to be created from a single String. The pattern contains various single character flags and via an @@ -104,14 +105,10 @@ public class PatternOptionBuilder { public static final Class<URL> URL_VALUE = URL.class; /** The converter to use for Unimplemented data types */ - static final Converter<?, UnsupportedOperationException> UNSUPPORTED = s -> { + private static final Converter<?, UnsupportedOperationException> UNSUPPORTED = s -> { throw new UnsupportedOperationException("Not yet implemented"); }; - static { - registerTypes(); - } - /** * Retrieve the class that {@code ch} represents. * @@ -202,7 +199,10 @@ public class PatternOptionBuilder { required = true; } else { type = getValueType(ch); - converter = TypeHandler.getConverter(getValueType(ch)); + final Map<Class<?>, Converter<?, ? extends Throwable>> map = TypeHandler.createDefaultMap(); + // Backward compatibility (probably). + map.put(FILES_VALUE, unsupported()); + converter = new TypeHandler(map).getConverter(getValueType(ch)); } } @@ -216,15 +216,6 @@ public class PatternOptionBuilder { return options; } - /** - * Registers custom {@code Converter}s with the {@code TypeHandler}. - * - * @since 1.7.0 - */ - public static void registerTypes() { - TypeHandler.register(PatternOptionBuilder.FILES_VALUE, unsupported()); - } - @SuppressWarnings("unchecked") static <T> T unsupported() { return (T) UNSUPPORTED; diff --git a/src/main/java/org/apache/commons/cli/TypeHandler.java b/src/main/java/org/apache/commons/cli/TypeHandler.java index f663229..c2c5147 100644 --- a/src/main/java/org/apache/commons/cli/TypeHandler.java +++ b/src/main/java/org/apache/commons/cli/TypeHandler.java @@ -38,25 +38,13 @@ import java.util.Map; */ public class TypeHandler { - /** Value of hex conversion of strings */ - private static final int HEX_RADIX = 16; - /** - * Map of Class to Converter. - * <p> - * The Class type parameter matches the Converter's first generic type. - * </p> + * The default TypeHandler. */ - private static Map<Class<?>, Converter<?, ? extends Throwable>> converterMap = createDefaultMap(); + private static final TypeHandler DEFAULT = new TypeHandler(); - /** - * Unregisters all Converters. - * - * @since 1.7.0 - */ - public static void clear() { - converterMap.clear(); - } + /** Value of hex conversion of strings */ + private static final int HEX_RADIX = 16; /** * Returns the class whose name is {@code className}. @@ -82,7 +70,13 @@ public class TypeHandler { return createValueUnchecked(string, Date.class); } - private static Map<Class<?>, Converter<?, ? extends Throwable>> createDefaultMap() { + /** + * Creates a default converter map. + * + * @return a default converter map. + * @since 1.7.0 + */ + public static Map<Class<?>, Converter<?, ? extends Throwable>> createDefaultMap() { return putDefaultMap(new HashMap<>()); } @@ -162,7 +156,7 @@ public class TypeHandler { */ public static <T> T createValue(final String string, final Class<T> clazz) throws ParseException { try { - return getConverter(clazz).apply(string); + return getDefault().getConverter(clazz).apply(string); } catch (final Throwable e) { throw ParseException.wrap(e); } @@ -200,16 +194,13 @@ public class TypeHandler { } /** - * Gets the registered converter for the the Class, or {@link Converter#DEFAULT} if absent. + * Gets the default TypeHandler. * - * @param <T> The Class parameter type. - * @param clazz The Class to get the Converter for. - * @return the registered converter if any, {@link Converter#DEFAULT} otherwise. + * @return the default TypeHandler. * @since 1.7.0 */ - @SuppressWarnings("unchecked") // returned value will have type T because it is fixed by clazz - public static <T> Converter<T, ?> getConverter(final Class<T> clazz) { - return (Converter<T, ?>) converterMap.getOrDefault(clazz, Converter.DEFAULT); + public static TypeHandler getDefault() { + return DEFAULT; } /** @@ -247,38 +238,41 @@ public class TypeHandler { } /** - * Registers a Converter for a Class. If {@code converter} is null registration is cleared for {@code clazz}, and no converter will be used in processing. - * - * @param <T> The Class parameter type. - * @param clazz the Class to register the Converter for. - * @param converter The Converter to associate with Class. May be null. - * @since 1.7.0 + * Map of Class to Converter. + * <p> + * The Class type parameter matches the Converter's first generic type. + * </p> */ - public static <T> void register(final Class<T> clazz, final Converter<T, ? extends Throwable> converter) { - if (converter == null) { - unregister(clazz); - } else { - converterMap.put(clazz, converter); - } + private final Map<Class<?>, Converter<?, ? extends Throwable>> converterMap; + + /** + * Constructs a default initialized instance. + */ + public TypeHandler() { + this(createDefaultMap()); } /** - * Resets the registered Converters to the default state. + * Constructs a default initialized instance. * + * @param converterMap The converter map. * @since 1.7.0 */ - public static void resetConverters() { - converterMap.clear(); - putDefaultMap(converterMap); + public TypeHandler(final Map<Class<?>, Converter<?, ? extends Throwable>> converterMap) { + this.converterMap = converterMap; } /** - * Unregisters a Converter for a Class. If {@code converter} is null registration is cleared for {@code clazz}, and no converter will be used in processing. + * Gets the registered converter for the the Class, or {@link Converter#DEFAULT} if absent. * - * @param clazz the Class to unregister. + * @param <T> The Class parameter type. + * @param clazz The Class to get the Converter for. + * @return the registered converter if any, {@link Converter#DEFAULT} otherwise. * @since 1.7.0 */ - public static void unregister(final Class<?> clazz) { - converterMap.remove(clazz); + @SuppressWarnings("unchecked") // returned value will have type T because it is fixed by clazz + public <T> Converter<T, ?> getConverter(final Class<T> clazz) { + return (Converter<T, ?>) converterMap.getOrDefault(clazz, Converter.DEFAULT); } + } diff --git a/src/test/java/org/apache/commons/cli/OptionTest.java b/src/test/java/org/apache/commons/cli/OptionTest.java index eaaf3c6..d56fd7e 100644 --- a/src/test/java/org/apache/commons/cli/OptionTest.java +++ b/src/test/java/org/apache/commons/cli/OptionTest.java @@ -68,6 +68,9 @@ public class OptionTest { } } + /** Always returns the same Path. */ + private static final Converter<Path, InvalidPathException> PATH_CONVERTER = s -> Paths.get("foo"); + private static void checkOption(final Option option, final String opt, final String description, final String longOpt, final int numArgs, final String argName, final boolean required, final boolean optionalArg, final char valueSeparator, final Class<?> cls, final String deprecatedDesc, final Boolean deprecatedForRemoval, final String deprecatedSince) { @@ -266,13 +269,8 @@ public class OptionTest { assertNotEquals(Option.builder("test").build().hashCode(), Option.builder("test").longOpt("long test").build().hashCode()); } - /** Always returns the same Path. */ - private static final Converter<Path, InvalidPathException> PATH_CONVERTER = s -> Paths.get("foo"); - @Test public void testSerialization() throws IOException, ClassNotFoundException { - // TODO No global map! - TypeHandler.resetConverters(); final Option option = Option.builder("o").type(TypeHandlerTest.Instantiable.class).build(); assertEquals(Converter.DEFAULT, option.getConverter()); Option roundtrip = roundTrip(option); @@ -284,16 +282,10 @@ public class OptionTest { assertEquals(Converter.DEFAULT, roundtrip.getConverter()); // verify registered class converters and verifiers do not get reset to default. // converters are NOT Serializable, use a serialization proxy if you want that. - try { - TypeHandler.register(Path.class, PATH_CONVERTER); - // verify earlier values still set. - assertEquals(Converter.DATE, option.getConverter()); - roundtrip = roundTrip(option); - assertEquals(Converter.DEFAULT, roundtrip.getConverter()); - } finally { - // TODO No global map! - TypeHandler.resetConverters(); - } + // verify earlier values still set. + assertEquals(Converter.DATE, option.getConverter()); + roundtrip = roundTrip(option); + assertEquals(Converter.DEFAULT, roundtrip.getConverter()); } @Test diff --git a/src/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java b/src/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java index c080237..aaba40a 100644 --- a/src/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java +++ b/src/test/java/org/apache/commons/cli/PatternOptionBuilderTest.java @@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -33,7 +34,6 @@ import java.util.Calendar; import java.util.Date; import java.util.Vector; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; /** @@ -41,10 +41,6 @@ import org.junit.jupiter.api.Test; */ @SuppressWarnings("deprecation") // tests some deprecated classes public class PatternOptionBuilderTest { - @BeforeAll - public static void setup() { - PatternOptionBuilder.registerTypes(); - } @Test public void testClassPattern() throws Exception { @@ -164,12 +160,7 @@ public class PatternOptionBuilderTest { assertEquals(new URL("https://commons.apache.org"), line.getOptionObject('t'), "url flag t"); // FILES NOT SUPPORTED YET - try { - assertEquals(new File[0], line.getOptionObject('m'), "files flag m"); - fail("Multiple files are not supported yet, should have failed"); - } catch (final UnsupportedOperationException uoe) { - // expected - } + assertThrows(UnsupportedOperationException.class, () -> line.getOptionObject('m')); assertEquals(expectedDate, line.getOptionObject('z'), "date flag z"); diff --git a/src/test/java/org/apache/commons/cli/TypeHandlerTest.java b/src/test/java/org/apache/commons/cli/TypeHandlerTest.java index ae7ff6e..6267069 100644 --- a/src/test/java/org/apache/commons/cli/TypeHandlerTest.java +++ b/src/test/java/org/apache/commons/cli/TypeHandlerTest.java @@ -37,6 +37,7 @@ import java.time.Instant; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -70,18 +71,18 @@ public class TypeHandlerTest { /** Always returns the same Path. */ private static final Converter<Path, InvalidPathException> PATH_CONVERTER = s -> Paths.get("foo"); - static Stream<Date> createDateFixtures() { + private static Stream<Date> createDateFixtures() { return Stream.of(Date.from(Instant.EPOCH), Date.from(Instant.ofEpochSecond(0)), Date.from(Instant.ofEpochSecond(40_000))); } - private static Stream<Arguments> createValueTestParameters() { + private static Stream<Arguments> createValueTestParameters() throws MalformedURLException { // force the PatternOptionBuilder to load / modify the TypeHandler table. @SuppressWarnings("unused") - final Class<?> ignore = PatternOptionBuilder.FILES_VALUE; + final Class<?> loadStatic = PatternOptionBuilder.FILES_VALUE; // reset the type handler table. - TypeHandler.resetConverters(); - final List<Arguments> lst = new ArrayList<>(); + // TypeHandler.resetConverters(); + final List<Arguments> list = new ArrayList<>(); /* * Dates calculated from strings are dependent upon configuration and environment settings for the machine on which the test is running. To avoid this @@ -90,115 +91,81 @@ public class TypeHandlerTest { final Date date = new Date(1023400137000L); final DateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); - try { - lst.add(Arguments.of(Instantiable.class.getName(), PatternOptionBuilder.CLASS_VALUE, Instantiable.class)); - lst.add(Arguments.of("what ever", PatternOptionBuilder.CLASS_VALUE, ParseException.class)); - - lst.add(Arguments.of("what ever", PatternOptionBuilder.DATE_VALUE, ParseException.class)); - lst.add(Arguments.of(dateFormat.format(date), PatternOptionBuilder.DATE_VALUE, date)); - lst.add(Arguments.of("Jun 06 17:48:57 EDT 2002", PatternOptionBuilder.DATE_VALUE, ParseException.class)); + list.add(Arguments.of(Instantiable.class.getName(), PatternOptionBuilder.CLASS_VALUE, Instantiable.class)); + list.add(Arguments.of("what ever", PatternOptionBuilder.CLASS_VALUE, ParseException.class)); - lst.add(Arguments.of("non-existing.file", PatternOptionBuilder.EXISTING_FILE_VALUE, ParseException.class)); + list.add(Arguments.of("what ever", PatternOptionBuilder.DATE_VALUE, ParseException.class)); + list.add(Arguments.of(dateFormat.format(date), PatternOptionBuilder.DATE_VALUE, date)); + list.add(Arguments.of("Jun 06 17:48:57 EDT 2002", PatternOptionBuilder.DATE_VALUE, ParseException.class)); - lst.add(Arguments.of("some-file.txt", PatternOptionBuilder.FILE_VALUE, new File("some-file.txt"))); + list.add(Arguments.of("non-existing.file", PatternOptionBuilder.EXISTING_FILE_VALUE, ParseException.class)); - lst.add(Arguments.of("some-path.txt", Path.class, new File("some-path.txt").toPath())); + list.add(Arguments.of("some-file.txt", PatternOptionBuilder.FILE_VALUE, new File("some-file.txt"))); - // the PatternOptionBUilder.FILES_VALUE is not registered so it should just return the string - lst.add(Arguments.of("some.files", PatternOptionBuilder.FILES_VALUE, "some.files")); + list.add(Arguments.of("some-path.txt", Path.class, new File("some-path.txt").toPath())); - lst.add(Arguments.of("just-a-string", Integer.class, ParseException.class)); - lst.add(Arguments.of("5", Integer.class, 5)); - lst.add(Arguments.of("5.5", Integer.class, ParseException.class)); - lst.add(Arguments.of(Long.toString(Long.MAX_VALUE), Integer.class, ParseException.class)); + // the PatternOptionBuilder.FILES_VALUE is not registered so it should just return the string + list.add(Arguments.of("some.files", PatternOptionBuilder.FILES_VALUE, "some.files")); - lst.add(Arguments.of("just-a-string", Long.class, ParseException.class)); - lst.add(Arguments.of("5", Long.class, 5L)); - lst.add(Arguments.of("5.5", Long.class, ParseException.class)); + list.add(Arguments.of("just-a-string", Integer.class, ParseException.class)); + list.add(Arguments.of("5", Integer.class, 5)); + list.add(Arguments.of("5.5", Integer.class, ParseException.class)); + list.add(Arguments.of(Long.toString(Long.MAX_VALUE), Integer.class, ParseException.class)); - lst.add(Arguments.of("just-a-string", Short.class, ParseException.class)); - lst.add(Arguments.of("5", Short.class, (short) 5)); - lst.add(Arguments.of("5.5", Short.class, ParseException.class)); - lst.add(Arguments.of(Integer.toString(Integer.MAX_VALUE), Short.class, ParseException.class)); + list.add(Arguments.of("just-a-string", Long.class, ParseException.class)); + list.add(Arguments.of("5", Long.class, 5L)); + list.add(Arguments.of("5.5", Long.class, ParseException.class)); - lst.add(Arguments.of("just-a-string", Byte.class, ParseException.class)); - lst.add(Arguments.of("5", Byte.class, (byte) 5)); - lst.add(Arguments.of("5.5", Byte.class, ParseException.class)); - lst.add(Arguments.of(Short.toString(Short.MAX_VALUE), Byte.class, ParseException.class)); + list.add(Arguments.of("just-a-string", Short.class, ParseException.class)); + list.add(Arguments.of("5", Short.class, (short) 5)); + list.add(Arguments.of("5.5", Short.class, ParseException.class)); + list.add(Arguments.of(Integer.toString(Integer.MAX_VALUE), Short.class, ParseException.class)); - lst.add(Arguments.of("just-a-string", Character.class, 'j')); - lst.add(Arguments.of("5", Character.class, '5')); - lst.add(Arguments.of("5.5", Character.class, '5')); - lst.add(Arguments.of("\\u0124", Character.class, Character.toChars(0x0124)[0])); + list.add(Arguments.of("just-a-string", Byte.class, ParseException.class)); + list.add(Arguments.of("5", Byte.class, (byte) 5)); + list.add(Arguments.of("5.5", Byte.class, ParseException.class)); + list.add(Arguments.of(Short.toString(Short.MAX_VALUE), Byte.class, ParseException.class)); - lst.add(Arguments.of("just-a-string", Double.class, ParseException.class)); - lst.add(Arguments.of("5", Double.class, 5d)); - lst.add(Arguments.of("5.5", Double.class, 5.5)); + list.add(Arguments.of("just-a-string", Character.class, 'j')); + list.add(Arguments.of("5", Character.class, '5')); + list.add(Arguments.of("5.5", Character.class, '5')); + list.add(Arguments.of("\\u0124", Character.class, Character.toChars(0x0124)[0])); - lst.add(Arguments.of("just-a-string", Float.class, ParseException.class)); - lst.add(Arguments.of("5", Float.class, 5f)); - lst.add(Arguments.of("5.5", Float.class, 5.5f)); - lst.add(Arguments.of(Double.toString(Double.MAX_VALUE), Float.class, Float.POSITIVE_INFINITY)); + list.add(Arguments.of("just-a-string", Double.class, ParseException.class)); + list.add(Arguments.of("5", Double.class, 5d)); + list.add(Arguments.of("5.5", Double.class, 5.5)); - lst.add(Arguments.of("just-a-string", BigInteger.class, ParseException.class)); - lst.add(Arguments.of("5", BigInteger.class, new BigInteger("5"))); - lst.add(Arguments.of("5.5", BigInteger.class, ParseException.class)); + list.add(Arguments.of("just-a-string", Float.class, ParseException.class)); + list.add(Arguments.of("5", Float.class, 5f)); + list.add(Arguments.of("5.5", Float.class, 5.5f)); + list.add(Arguments.of(Double.toString(Double.MAX_VALUE), Float.class, Float.POSITIVE_INFINITY)); - lst.add(Arguments.of("just-a-string", BigDecimal.class, ParseException.class)); - lst.add(Arguments.of("5", BigDecimal.class, new BigDecimal("5"))); - lst.add(Arguments.of("5.5", BigDecimal.class, new BigDecimal(5.5))); + list.add(Arguments.of("just-a-string", BigInteger.class, ParseException.class)); + list.add(Arguments.of("5", BigInteger.class, new BigInteger("5"))); + list.add(Arguments.of("5.5", BigInteger.class, ParseException.class)); - lst.add(Arguments.of("1.5", PatternOptionBuilder.NUMBER_VALUE, Double.valueOf(1.5))); - lst.add(Arguments.of("15", PatternOptionBuilder.NUMBER_VALUE, Long.valueOf(15))); - lst.add(Arguments.of("not a number", PatternOptionBuilder.NUMBER_VALUE, ParseException.class)); + list.add(Arguments.of("just-a-string", BigDecimal.class, ParseException.class)); + list.add(Arguments.of("5", BigDecimal.class, new BigDecimal("5"))); + list.add(Arguments.of("5.5", BigDecimal.class, new BigDecimal(5.5))); - lst.add(Arguments.of(Instantiable.class.getName(), PatternOptionBuilder.OBJECT_VALUE, new Instantiable())); - lst.add(Arguments.of(NotInstantiable.class.getName(), PatternOptionBuilder.OBJECT_VALUE, ParseException.class)); - lst.add(Arguments.of("unknown", PatternOptionBuilder.OBJECT_VALUE, ParseException.class)); + list.add(Arguments.of("1.5", PatternOptionBuilder.NUMBER_VALUE, Double.valueOf(1.5))); + list.add(Arguments.of("15", PatternOptionBuilder.NUMBER_VALUE, Long.valueOf(15))); + list.add(Arguments.of("not a number", PatternOptionBuilder.NUMBER_VALUE, ParseException.class)); - lst.add(Arguments.of("String", PatternOptionBuilder.STRING_VALUE, "String")); + list.add(Arguments.of(Instantiable.class.getName(), PatternOptionBuilder.OBJECT_VALUE, new Instantiable())); + list.add(Arguments.of(NotInstantiable.class.getName(), PatternOptionBuilder.OBJECT_VALUE, ParseException.class)); + list.add(Arguments.of("unknown", PatternOptionBuilder.OBJECT_VALUE, ParseException.class)); - final String urlString = "https://commons.apache.org"; - lst.add(Arguments.of(urlString, PatternOptionBuilder.URL_VALUE, new URL(urlString))); - lst.add(Arguments.of("Malformed-url", PatternOptionBuilder.URL_VALUE, ParseException.class)); + list.add(Arguments.of("String", PatternOptionBuilder.STRING_VALUE, "String")); - return lst.stream(); + final String urlString = "https://commons.apache.org"; + list.add(Arguments.of(urlString, PatternOptionBuilder.URL_VALUE, new URL(urlString))); + list.add(Arguments.of("Malformed-url", PatternOptionBuilder.URL_VALUE, ParseException.class)); - } catch (final MalformedURLException e) { - throw new RuntimeException(e); - } + return list.stream(); } - @SuppressWarnings("unchecked") - @ParameterizedTest(name = "{0} as {1}") - @MethodSource("createValueTestParameters") - public void createValueTests(final String str, final Class<?> type, final Object expected) throws Exception { - @SuppressWarnings("cast") - final Object objectApiTest = (Object) type; // KEEP this cast - if (expected instanceof Class<?> && Throwable.class.isAssignableFrom((Class<?>) expected)) { - assertThrows((Class<Throwable>) expected, () -> TypeHandler.createValue(str, type)); - assertThrows((Class<Throwable>) expected, () -> { - TypeHandler.createValue(str, objectApiTest); - }); - } else { - assertEquals(expected, TypeHandler.createValue(str, type)); - assertEquals(expected, TypeHandler.createValue(str, objectApiTest)); - } - } - - @Test - public void testClear() { - assertEquals(Converter.NUMBER, TypeHandler.getConverter(Number.class)); - try { - TypeHandler.clear(); - assertEquals(Converter.DEFAULT, TypeHandler.getConverter(Number.class)); - } finally { - TypeHandler.resetConverters(); - assertEquals(Converter.NUMBER, TypeHandler.getConverter(Number.class)); - } - } - @Test public void testCreateClass() throws ParseException { final Class<?> cls = getClass(); @@ -217,6 +184,12 @@ public class TypeHandlerTest { assertEquals(file, TypeHandler.createFile(file.toString())); } + @Test + public void testOpenFile() { + final File file = new File("").getAbsoluteFile(); + assertEquals(file, TypeHandler.createFile(file.toString())); + } + @Test public void testCreateFiles() { assertThrows(UnsupportedOperationException.class, () -> TypeHandler.createFiles(null)); @@ -239,6 +212,21 @@ public class TypeHandlerTest { assertEquals(file, TypeHandler.createURL(file.toString())); } + @SuppressWarnings("unchecked") + @ParameterizedTest(name = "{0} as {1}") + @MethodSource("createValueTestParameters") + public void testCreateValue(final String str, final Class<?> type, final Object expected) throws Exception { + @SuppressWarnings("cast") + final Object objectApiTest = (Object) type; // KEEP this cast + if (expected instanceof Class<?> && Throwable.class.isAssignableFrom((Class<?>) expected)) { + assertThrows((Class<Throwable>) expected, () -> TypeHandler.createValue(str, type)); + assertThrows((Class<Throwable>) expected, () -> TypeHandler.createValue(str, objectApiTest)); + } else { + assertEquals(expected, TypeHandler.createValue(str, type)); + assertEquals(expected, TypeHandler.createValue(str, objectApiTest)); + } + } + @Test public void testCreateValueExistingFile() throws Exception { try (FileInputStream result = TypeHandler.createValue("src/test/resources/org/apache/commons/cli/existing-readable.file", @@ -255,27 +243,16 @@ public class TypeHandlerTest { @Test public void testRegister() { - assertEquals(Converter.PATH, TypeHandler.getConverter(Path.class)); + final Map<Class<?>, Converter<?, ? extends Throwable>> map = TypeHandler.createDefaultMap(); + final TypeHandler typeHandler = new TypeHandler(map); + assertEquals(Converter.PATH, typeHandler.getConverter(Path.class)); try { - TypeHandler.register(Path.class, PATH_CONVERTER); - assertEquals(PATH_CONVERTER, TypeHandler.getConverter(Path.class)); + map.put(Path.class, PATH_CONVERTER); + assertEquals(PATH_CONVERTER, typeHandler.getConverter(Path.class)); } finally { - TypeHandler.unregister(Path.class); - assertEquals(Converter.DEFAULT, TypeHandler.getConverter(Path.class)); + map.remove(Path.class); + assertEquals(Converter.DEFAULT, typeHandler.getConverter(Path.class)); } } - @Test - public void testResetConverters() { - assertEquals(Converter.PATH, TypeHandler.getConverter(Path.class)); - try { - TypeHandler.register(Path.class, PATH_CONVERTER); - assertEquals(PATH_CONVERTER, TypeHandler.getConverter(Path.class)); - TypeHandler.resetConverters(); - assertEquals(Converter.PATH, TypeHandler.getConverter(Path.class)); - assertEquals(Converter.DEFAULT, TypeHandler.getConverter(NotInstantiable.class)); - } finally { - TypeHandler.resetConverters(); - } - } }
