From 598fb81e39490cdada0db268c0734ca25f39ed1a Mon Sep 17 00:00:00 2001 From: rpopma Date: Mon, 18 Dec 2017 20:52:56 +0900 Subject: [PATCH] #83 additional built-in type converters --- src/main/java/picocli/CommandLine.java | 23 ++++++ .../CommandLineTypeConversionTest.java | 76 +++++++++++++------ 2 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index 9906dd411..db6e96e39 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -38,6 +38,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.nio.ByteOrder; import java.nio.charset.Charset; import java.sql.Time; import java.text.BreakIterator; @@ -48,6 +49,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Currency; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -60,6 +62,7 @@ import java.util.Set; import java.util.SortedSet; import java.util.Stack; +import java.util.TimeZone; import java.util.TreeSet; import java.util.UUID; import java.util.concurrent.Callable; @@ -1968,6 +1971,10 @@ private class Interpreter { converterRegistry.put(InetAddress.class, new BuiltIn.InetAddressConverter()); converterRegistry.put(Pattern.class, new BuiltIn.PatternConverter()); converterRegistry.put(UUID.class, new BuiltIn.UUIDConverter()); + converterRegistry.put(Currency.class, new BuiltIn.CurrencyConverter()); + converterRegistry.put(TimeZone.class, new BuiltIn.TimeZoneConverter()); + converterRegistry.put(ByteOrder.class, new BuiltIn.ByteOrderConverter()); + converterRegistry.put(Class.class, new BuiltIn.ClassConverter()); this.command = Assert.notNull(command, "command"); Class cls = command.getClass(); @@ -2888,6 +2895,22 @@ static class PatternConverter implements ITypeConverter { static class UUIDConverter implements ITypeConverter { public UUID convert(String s) throws Exception { return UUID.fromString(s); } } + static class CurrencyConverter implements ITypeConverter { + public Currency convert(String s) throws Exception { return Currency.getInstance(s); } + } + static class TimeZoneConverter implements ITypeConverter { + public TimeZone convert(String s) throws Exception { return TimeZone.getTimeZone(s); } + } + static class ByteOrderConverter implements ITypeConverter { + public ByteOrder convert(String s) throws Exception { + if (s.equalsIgnoreCase(ByteOrder.BIG_ENDIAN.toString())) { return ByteOrder.BIG_ENDIAN; } + if (s.equalsIgnoreCase(ByteOrder.LITTLE_ENDIAN.toString())) { return ByteOrder.LITTLE_ENDIAN; } + throw new TypeConversionException("'" + s + "' is not a valid ByteOrder"); + } + } + static class ClassConverter implements ITypeConverter { + public Class convert(String s) throws Exception { return Class.forName(s); } + } private BuiltIn() {} // private constructor: never instantiate } diff --git a/src/test/java/picocli/CommandLineTypeConversionTest.java b/src/test/java/picocli/CommandLineTypeConversionTest.java index 7f7b9ec3e..76fe0bc9f 100644 --- a/src/test/java/picocli/CommandLineTypeConversionTest.java +++ b/src/test/java/picocli/CommandLineTypeConversionTest.java @@ -24,14 +24,17 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.UnknownHostException; +import java.nio.ByteOrder; import java.nio.charset.Charset; import java.sql.Time; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Currency; import java.util.Date; import java.util.List; +import java.util.TimeZone; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; @@ -68,28 +71,21 @@ static class SupportedTypes { @Option(names = "-String") String aStringField; @Option(names = "-StringBuilder") StringBuilder aStringBuilderField; @Option(names = "-CharSequence") CharSequence aCharSequenceField; - @Option(names = "-File") - File aFileField; - @Option(names = "-URL") - URL anURLField; - @Option(names = "-URI") - URI anURIField; - @Option(names = "-Date") - Date aDateField; - @Option(names = "-Time") - Time aTimeField; - @Option(names = "-BigDecimal") - BigDecimal aBigDecimalField; - @Option(names = "-BigInteger") - BigInteger aBigIntegerField; - @Option(names = "-Charset") - Charset aCharsetField; - @Option(names = "-InetAddress") - InetAddress anInetAddressField; - @Option(names = "-Pattern") - Pattern aPatternField; - @Option(names = "-UUID") - UUID anUUIDField; + @Option(names = "-File") File aFileField; + @Option(names = "-URL") URL anURLField; + @Option(names = "-URI") URI anURIField; + @Option(names = "-Date") Date aDateField; + @Option(names = "-Time") Time aTimeField; + @Option(names = "-BigDecimal") BigDecimal aBigDecimalField; + @Option(names = "-BigInteger") BigInteger aBigIntegerField; + @Option(names = "-Charset") Charset aCharsetField; + @Option(names = "-InetAddress") InetAddress anInetAddressField; + @Option(names = "-Pattern") Pattern aPatternField; + @Option(names = "-UUID") UUID anUUIDField; + @Option(names = "-Currency") Currency aCurrencyField; + @Option(names = "-tz") TimeZone aTimeZone; + @Option(names = "-byteOrder") ByteOrder aByteOrder; + @Option(names = "-Class") Class aClass; } @Test public void testDefaults() { @@ -124,6 +120,10 @@ public void testDefaults() { assertEquals("InetAddress", null, bean.anInetAddressField); assertEquals("Pattern", null, bean.aPatternField); assertEquals("UUID", null, bean.anUUIDField); + assertEquals("Currency", null, bean.aCurrencyField); + assertEquals("TimeZone", null, bean.aTimeZone); + assertEquals("ByteOrder", null, bean.aByteOrder); + assertEquals("Class", null, bean.aClass); } @Test public void testTypeConversionSucceedsForValidInput() @@ -148,7 +148,11 @@ public void testTypeConversionSucceedsForValidInput() "-Charset", "UTF8", // "-InetAddress", InetAddress.getLocalHost().getHostName(), // "-Pattern", "a*b", // - "-UUID", "c7d51423-bf9d-45dd-a30d-5b16fafe42e2" + "-UUID", "c7d51423-bf9d-45dd-a30d-5b16fafe42e2", // + "-Currency", "EUR", + "-tz", "Japan/Tokyo", + "-byteOrder", "LITTLE_ENDIAN", + "-Class", "java.lang.String" ); assertEquals("boolean", true, bean.booleanField); assertEquals("Boolean", Boolean.TRUE, bean.aBooleanField); @@ -181,6 +185,10 @@ public void testTypeConversionSucceedsForValidInput() assertEquals("InetAddress", InetAddress.getByName(InetAddress.getLocalHost().getHostName()), bean.anInetAddressField); assertEquals("Pattern", Pattern.compile("a*b").pattern(), bean.aPatternField.pattern()); assertEquals("UUID", UUID.fromString("c7d51423-bf9d-45dd-a30d-5b16fafe42e2"), bean.anUUIDField); + assertEquals("Currency", Currency.getInstance("EUR"), bean.aCurrencyField); + assertEquals("TimeZone", TimeZone.getTimeZone("Japan/Tokyo"), bean.aTimeZone); + assertEquals("ByteOrder", ByteOrder.LITTLE_ENDIAN, bean.aByteOrder); + assertEquals("Class", String.class, bean.aClass); } @Test public void testByteFieldsAreDecimal() { @@ -432,21 +440,39 @@ public void testUUIDConvertersInvalidError() { parseInvalidValue("-UUID", "aa", ": java.lang.IllegalArgumentException: Invalid UUID string: aa"); } @Test + public void testCurrencyConvertersInvalidError() { + parseInvalidValue("-Currency", "aa", ": java.lang.IllegalArgumentException"); + } + @Test + public void testTimeZoneConvertersInvalidError() { + SupportedTypes bean = CommandLine.populateCommand(new SupportedTypes(), "-tz", "Abc/Def"); + assertEquals(TimeZone.getTimeZone("GMT"), bean.aTimeZone); + } + @Test public void testRegexPatternConverterInvalidError() { parseInvalidValue("-Pattern", "[[(aa", String.format(": java.util.regex.PatternSyntaxException: Unclosed character class near index 4%n" + "[[(aa%n" + " ^")); } + @Test + public void testByteOrderConvertersInvalidError() { + parseInvalidValue("-byteOrder", "aa", "'aa' is not a valid ByteOrder for option '-byteOrder'"); + } + @Test + public void testClassConvertersInvalidError() { + parseInvalidValue("-Class", "aa", ": java.lang.ClassNotFoundException: aa"); + } private void parseInvalidValue(String option, String value, String errorMessage) { try { - CommandLine.populateCommand(new SupportedTypes(), option, value); + SupportedTypes bean = CommandLine.populateCommand(new SupportedTypes(), option, value); fail("Invalid format " + value + " was accepted for " + option); } catch (CommandLine.ParameterException actual) { + if (actual.getMessage().equals(errorMessage)) { return; } // that is okay also String type = option.substring(1); String expected = "Could not convert '" + value + "' to " + type + " for option '" + option + "'" + errorMessage; assertTrue("expected:<" + expected + "> but was:<" + actual.getMessage() + ">", - actual.getMessage().startsWith(actual.getMessage())); + actual.getMessage().startsWith(expected)); } }