Skip to content

Commit

Permalink
#83 additional built-in type converters
Browse files Browse the repository at this point in the history
  • Loading branch information
remkop committed Dec 18, 2017
1 parent 0ab935a commit 598fb81
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 25 deletions.
23 changes: 23 additions & 0 deletions src/main/java/picocli/CommandLine.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -2888,6 +2895,22 @@ static class PatternConverter implements ITypeConverter<Pattern> {
static class UUIDConverter implements ITypeConverter<UUID> {
public UUID convert(String s) throws Exception { return UUID.fromString(s); }
}
static class CurrencyConverter implements ITypeConverter<Currency> {
public Currency convert(String s) throws Exception { return Currency.getInstance(s); }
}
static class TimeZoneConverter implements ITypeConverter<TimeZone> {
public TimeZone convert(String s) throws Exception { return TimeZone.getTimeZone(s); }
}
static class ByteOrderConverter implements ITypeConverter<ByteOrder> {
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<Class> {
public Class<?> convert(String s) throws Exception { return Class.forName(s); }
}
private BuiltIn() {} // private constructor: never instantiate
}

Expand Down
76 changes: 51 additions & 25 deletions src/test/java/picocli/CommandLineTypeConversionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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()
Expand All @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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));
}
}

Expand Down

0 comments on commit 598fb81

Please sign in to comment.