diff --git a/src/main/java/com/cedarsoftware/util/convert/Converter.java b/src/main/java/com/cedarsoftware/util/convert/Converter.java index a691c174..b4cea50f 100644 --- a/src/main/java/com/cedarsoftware/util/convert/Converter.java +++ b/src/main/java/com/cedarsoftware/util/convert/Converter.java @@ -3,6 +3,8 @@ import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.URI; +import java.net.URL; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.sql.Timestamp; @@ -23,6 +25,7 @@ import java.util.AbstractMap; import java.util.Calendar; import java.util.Date; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -628,6 +631,12 @@ private static void buildFactoryConversions() { CONVERSION_DB.put(pair(Map.class, Class.class), MapConversions::toClass); CONVERSION_DB.put(pair(String.class, Class.class), StringConversions::toClass); + // Class conversions supported + CONVERSION_DB.put(pair(Void.class, Locale.class), VoidConversions::toNull); + CONVERSION_DB.put(pair(Locale.class, Locale.class), Converter::identity); + CONVERSION_DB.put(pair(String.class, Locale.class), StringConversions::toLocale); + CONVERSION_DB.put(pair(Map.class, Locale.class), MapConversions::toLocale); + // String conversions supported CONVERSION_DB.put(pair(Void.class, String.class), VoidConversions::toNull); CONVERSION_DB.put(pair(Byte.class, String.class), StringConversions::toString); @@ -673,6 +682,9 @@ private static void buildFactoryConversions() { CONVERSION_DB.put(pair(OffsetTime.class, String.class), OffsetTimeConversions::toString); CONVERSION_DB.put(pair(OffsetDateTime.class, String.class), OffsetDateTimeConversions::toString); CONVERSION_DB.put(pair(Year.class, String.class), YearConversions::toString); + CONVERSION_DB.put(pair(Locale.class, String.class), LocaleConversions::toString); + CONVERSION_DB.put(pair(URL.class, String.class), StringConversions::toString); + CONVERSION_DB.put(pair(URI.class, String.class), StringConversions::toString); // Duration conversions supported CONVERSION_DB.put(pair(Void.class, Duration.class), VoidConversions::toNull); diff --git a/src/main/java/com/cedarsoftware/util/convert/LocaleConversions.java b/src/main/java/com/cedarsoftware/util/convert/LocaleConversions.java new file mode 100644 index 00000000..c860f2af --- /dev/null +++ b/src/main/java/com/cedarsoftware/util/convert/LocaleConversions.java @@ -0,0 +1,11 @@ +package com.cedarsoftware.util.convert; + +import java.util.Locale; + +public final class LocaleConversions { + private LocaleConversions() {} + + static String toString(Object from, Converter converter) { + return ((Locale)from).toLanguageTag(); + } +} diff --git a/src/main/java/com/cedarsoftware/util/convert/MapConversions.java b/src/main/java/com/cedarsoftware/util/convert/MapConversions.java index 192aca4b..33bc577e 100644 --- a/src/main/java/com/cedarsoftware/util/convert/MapConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/MapConversions.java @@ -20,6 +20,7 @@ import java.util.Calendar; import java.util.Date; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.UUID; @@ -81,6 +82,9 @@ final class MapConversions { static final String DATE_TIME = "dateTime"; private static final String ID = "id"; + public static final String LANGUAGE = "language"; + public static final String VARIANT = "variant"; + private static String COUNTRY = "country"; private MapConversions() {} @@ -204,6 +208,32 @@ static Calendar toCalendar(Object from, Converter converter) { } } + private static final String[] LOCALE_PARAMS = new String[] { LANGUAGE }; + static Locale toLocale(Object from, Converter converter) { + Map map = (Map) from; + + if (map.containsKey(VALUE) || map.containsKey(V)) { + return fromValueForMultiKey(map, converter, Locale.class, LOCALE_PARAMS); + } + + String language = converter.convert(map.get(LANGUAGE), String.class); + if (language == null) { + throw new IllegalArgumentException("java.util.Locale must specify 'language' field"); + } + String country = converter.convert(map.get(COUNTRY), String.class); + String variant = converter.convert(map.get(VARIANT), String.class); + + if (country == null) { + return new Locale(language); + } + if (variant == null) { + return new Locale(language, country); + } + + return new Locale(language, country, variant); + } + + private static final String[] LOCAL_DATE_PARAMS = new String[] { YEAR, MONTH, DAY }; static LocalDate toLocalDate(Object from, Converter converter) { Map map = (Map) from; @@ -360,16 +390,18 @@ static YearMonth toYearMonth(Object from, Converter converter) { private static final String[] PERIOD_PARAMS = new String[] { YEARS, MONTHS, DAYS }; static Period toPeriod(Object from, Converter converter) { + Map map = (Map) from; - if (map.containsKey(YEARS) && map.containsKey(MONTHS) && map.containsKey(DAYS)) { - ConverterOptions options = converter.getOptions(); - int years = converter.convert(map.get(YEARS), int.class); - int months = converter.convert(map.get(MONTHS), int.class); - int days = converter.convert(map.get(DAYS), int.class); - return Period.of(years, months, days); - } else { + + if (map.containsKey(VALUE) || map.containsKey(V)) { return fromValueForMultiKey(from, converter, Period.class, PERIOD_PARAMS); } + + Number years = converter.convert(map.getOrDefault(YEARS, 0), int.class); + Number months = converter.convert(map.getOrDefault(MONTHS, 0), int.class); + Number days = converter.convert(map.getOrDefault(DAYS, 0), int.class); + + return Period.of(years.intValue(), months.intValue(), days.intValue()); } static ZoneId toZoneId(Object from, Converter converter) { @@ -391,10 +423,9 @@ static ZoneId toZoneId(Object from, Converter converter) { static ZoneOffset toZoneOffset(Object from, Converter converter) { Map map = (Map) from; if (map.containsKey(HOURS)) { - ConverterOptions options = converter.getOptions(); int hours = converter.convert(map.get(HOURS), int.class); - int minutes = converter.convert(map.get(MINUTES), int.class); // optional - int seconds = converter.convert(map.get(SECONDS), int.class); // optional + int minutes = converter.convert(map.getOrDefault(MINUTES, 0), int.class); // optional + int seconds = converter.convert(map.getOrDefault(SECONDS, 0), int.class); // optional return ZoneOffset.ofHoursMinutesSeconds(hours, minutes, seconds); } else { return fromValueForMultiKey(from, converter, ZoneOffset.class, ZONE_OFFSET_PARAMS); diff --git a/src/main/java/com/cedarsoftware/util/convert/StringConversions.java b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java index 54faf827..d12545ca 100644 --- a/src/main/java/com/cedarsoftware/util/convert/StringConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java @@ -25,6 +25,7 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Locale; import java.util.Optional; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; @@ -351,6 +352,15 @@ static LocalTime toLocalTime(Object from, Converter converter) { } } + static Locale toLocale(Object from, Converter converter) { + String str = StringUtilities.trimToNull(asString(from)); + if (str == null) { + return null; + } + + return Locale.forLanguageTag(str); + } + private static Optional parseDate(Object from, Converter converter) { String str = StringUtilities.trimToNull(asString(from));