diff --git a/src/main/java/com/cedarsoftware/util/ArrayUtilities.java b/src/main/java/com/cedarsoftware/util/ArrayUtilities.java
index ffcc2871..02f89842 100644
--- a/src/main/java/com/cedarsoftware/util/ArrayUtilities.java
+++ b/src/main/java/com/cedarsoftware/util/ArrayUtilities.java
@@ -31,11 +31,9 @@ public final class ArrayUtilities
* Immutable common arrays.
*/
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
-
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
public static final char[] EMPTY_CHAR_ARRAY = new char[0];
public static final Character[] EMPTY_CHARACTER_ARRAY = new Character[0];
-
public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
/**
diff --git a/src/main/java/com/cedarsoftware/util/DateUtilities.java b/src/main/java/com/cedarsoftware/util/DateUtilities.java
index c663e2f3..b5016ea3 100644
--- a/src/main/java/com/cedarsoftware/util/DateUtilities.java
+++ b/src/main/java/com/cedarsoftware/util/DateUtilities.java
@@ -179,11 +179,11 @@ public static Date parseDate(String dateStr) {
* passed in, null will be returned.
*/
public static ZonedDateTime parseDate(String dateStr, ZoneId defaultZoneId, boolean ensureDateTimeAlone) {
- if (StringUtilities.isEmpty(dateStr)) {
+ dateStr = StringUtilities.trimToNull(dateStr);
+ if (dateStr == null) {
return null;
}
Convention.throwIfNull(defaultZoneId, "ZoneId cannot be null. Use ZoneId.of(\"America/New_York\"), ZoneId.systemDefault(), etc.");
- dateStr = dateStr.trim();
if (allDigits.matcher(dateStr).matches()) {
return Instant.ofEpochMilli(Long.parseLong(dateStr)).atZone(defaultZoneId);
diff --git a/src/main/java/com/cedarsoftware/util/convert/CharArrayConversions.java b/src/main/java/com/cedarsoftware/util/convert/CharArrayConversions.java
index 7eed9bf3..4a4becd8 100644
--- a/src/main/java/com/cedarsoftware/util/convert/CharArrayConversions.java
+++ b/src/main/java/com/cedarsoftware/util/convert/CharArrayConversions.java
@@ -56,9 +56,6 @@ static byte[] toByteArray(Object from, Converter converter) {
static char[] toCharArray(Object from, Converter converter) {
char[] chars = (char[])from;
- if (chars == null) {
- return null;
- }
return Arrays.copyOf(chars, chars.length);
}
}
diff --git a/src/main/java/com/cedarsoftware/util/convert/CharBufferConversions.java b/src/main/java/com/cedarsoftware/util/convert/CharBufferConversions.java
index f9d2264c..3420a102 100644
--- a/src/main/java/com/cedarsoftware/util/convert/CharBufferConversions.java
+++ b/src/main/java/com/cedarsoftware/util/convert/CharBufferConversions.java
@@ -27,7 +27,7 @@ final class CharBufferConversions {
private CharBufferConversions() {}
static CharBuffer toCharBuffer(Object from, Converter converter) {
- // Create a readonly buffer so we aren't changing
+ // Create a readonly buffer, so we aren't changing
// the original buffers mark and position when
// working with this buffer. This could be inefficient
// if constantly fed with writeable buffers so should be documented
@@ -49,7 +49,7 @@ static String toString(Object from, Converter converter) {
static char[] toCharArray(Object from, Converter converter) {
CharBuffer buffer = toCharBuffer(from, converter);
- if (buffer == null || !buffer.hasRemaining()) {
+ if (!buffer.hasRemaining()) {
return EMPTY_CHAR_ARRAY;
}
diff --git a/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java b/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java
index d2e447ed..9c1f7b68 100644
--- a/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java
+++ b/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java
@@ -16,8 +16,6 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import com.cedarsoftware.util.StringUtilities;
-
/**
* @author Kenny Partlow (kpartlow@gmail.com)
*
@@ -118,10 +116,6 @@ static AtomicInteger toAtomicInteger(Object from, Converter converter) {
return new AtomicInteger(toInt(from, converter));
}
- static BigDecimal toBigDecimal(Object from, Converter converter) {
- return new BigDecimal(StringUtilities.trimToEmpty(from.toString()));
- }
-
static AtomicBoolean toAtomicBoolean(Object from, Converter converter) {
return new AtomicBoolean(toLong(from, converter) != 0);
}
@@ -152,10 +146,6 @@ static boolean isBigDecimalNotZero(Object from, Converter converter) {
return ((BigDecimal)from).compareTo(BigDecimal.ZERO) != 0;
}
- static BigInteger toBigInteger(Object from, Converter converter) {
- return new BigInteger(StringUtilities.trimToEmpty(from.toString()));
- }
-
/**
* @param from - object that is a number to be converted to char
* @param converter - instance of converter mappings to use.
@@ -212,9 +202,6 @@ static OffsetDateTime toOffsetDateTime(Object from, Converter converter) {
}
static Year toYear(Object from, Converter converter) {
- if (from instanceof Byte) {
- throw new IllegalArgumentException("Cannot convert Byte to Year, not enough precision.");
- }
Number number = (Number) from;
return Year.of(number.shortValue());
}
diff --git a/src/main/java/com/cedarsoftware/util/convert/StringConversions.java b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java
index 19c845d8..4a9957d6 100644
--- a/src/main/java/com/cedarsoftware/util/convert/StringConversions.java
+++ b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java
@@ -27,7 +27,6 @@
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
-import java.util.Optional;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -41,7 +40,6 @@
import com.cedarsoftware.util.StringUtilities;
import static com.cedarsoftware.util.ArrayUtilities.EMPTY_BYTE_ARRAY;
-import static com.cedarsoftware.util.ArrayUtilities.EMPTY_CHARACTER_ARRAY;
import static com.cedarsoftware.util.ArrayUtilities.EMPTY_CHAR_ARRAY;
/**
@@ -79,9 +77,9 @@ static String asString(Object from) {
}
static Byte toByte(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty((String) from);
- if (str.isEmpty()) {
- return CommonValues.BYTE_ZERO;
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
+ return (byte)0;
}
try {
return Byte.valueOf(str);
@@ -95,9 +93,9 @@ static Byte toByte(Object from, Converter converter) {
}
static Short toShort(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty((String) from);
- if (str.isEmpty()) {
- return CommonValues.SHORT_ZERO;
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
+ return (short)0;
}
try {
return Short.valueOf(str);
@@ -111,9 +109,9 @@ static Short toShort(Object from, Converter converter) {
}
static Integer toInt(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty(asString(from));
- if (str.isEmpty()) {
- return CommonValues.INTEGER_ZERO;
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
+ return 0;
}
try {
return Integer.valueOf(str);
@@ -127,9 +125,9 @@ static Integer toInt(Object from, Converter converter) {
}
static Long toLong(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty(asString(from));
- if (str.isEmpty()) {
- return CommonValues.LONG_ZERO;
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
+ return 0L;
}
try {
@@ -157,9 +155,9 @@ private static Long toLong(String s, BigDecimal low, BigDecimal high) {
}
static Float toFloat(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty(asString(from));
- if (str.isEmpty()) {
- return CommonValues.FLOAT_ZERO;
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
+ return 0f;
}
try {
return Float.valueOf(str);
@@ -169,9 +167,9 @@ static Float toFloat(Object from, Converter converter) {
}
static Double toDouble(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty(asString(from));
- if (str.isEmpty()) {
- return CommonValues.DOUBLE_ZERO;
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
+ return 0.0;
}
try {
return Double.valueOf(str);
@@ -181,7 +179,7 @@ static Double toDouble(Object from, Converter converter) {
}
static AtomicBoolean toAtomicBoolean(Object from, Converter converter) {
- return new AtomicBoolean(toBoolean(asString(from), converter));
+ return new AtomicBoolean(toBoolean(from, converter));
}
static AtomicInteger toAtomicInteger(Object from, Converter converter) {
@@ -193,11 +191,7 @@ static AtomicLong toAtomicLong(Object from, Converter converter) {
}
static Boolean toBoolean(Object from, Converter converter) {
- String from1 = asString(from);
- String str = StringUtilities.trimToEmpty(from1);
- if (str.isEmpty()) {
- return false;
- }
+ String str = (String) from;
// faster equals check "true" and "false"
if ("true".equals(str)) {
return true;
@@ -209,8 +203,8 @@ static Boolean toBoolean(Object from, Converter converter) {
static char toCharacter(Object from, Converter converter) {
String str = (String)from;
- if (str == null || str.isEmpty()) {
- return CommonValues.CHARACTER_ZERO;
+ if (str.isEmpty()) {
+ return (char)0;
}
if (str.length() == 1) {
return str.charAt(0);
@@ -224,8 +218,8 @@ static char toCharacter(Object from, Converter converter) {
}
static BigInteger toBigInteger(Object from, Converter converter) {
- String str = StringUtilities.trimToNull(asString(from));
- if (str == null) {
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
return BigInteger.ZERO;
}
try {
@@ -237,8 +231,8 @@ static BigInteger toBigInteger(Object from, Converter converter) {
}
static BigDecimal toBigDecimal(Object from, Converter converter) {
- String str = StringUtilities.trimToEmpty(asString(from));
- if (str.isEmpty()) {
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
return BigDecimal.ZERO;
}
try {
@@ -249,12 +243,12 @@ static BigDecimal toBigDecimal(Object from, Converter converter) {
}
static URL toURL(Object from, Converter converter) {
- String str = StringUtilities.trimToNull(asString(from));
- if (str == null) {
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
return null;
}
try {
- URI uri = URI.create((String) from);
+ URI uri = URI.create(str);
return uri.toURL();
} catch (Exception e) {
throw new IllegalArgumentException("Cannot convert String '" + str + "' to URL", e);
@@ -262,8 +256,8 @@ static URL toURL(Object from, Converter converter) {
}
static URI toURI(Object from, Converter converter) {
- String str = StringUtilities.trimToNull(asString(from));
- if (str == null) {
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
return null;
}
return URI.create((String) from);
@@ -353,8 +347,7 @@ static Period toPeriod(Object from, Converter converter) {
}
static Date toDate(Object from, Converter converter) {
- String strDate = (String) from;
- ZonedDateTime zdt = DateUtilities.parseDate(strDate, converter.getOptions().getZoneId(), true);
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
if (zdt == null) {
return null;
}
@@ -382,104 +375,93 @@ static TimeZone toTimeZone(Object from, Converter converter) {
static Calendar toCalendar(Object from, Converter converter) {
String calStr = (String) from;
- if (StringUtilities.isEmpty(calStr)) {
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
+ if (zdt == null) {
return null;
}
- ZonedDateTime zdt = DateUtilities.parseDate(calStr, converter.getOptions().getZoneId(), true);
ZonedDateTime zdtUser = zdt.withZoneSameInstant(converter.getOptions().getZoneId());
-
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(zdtUser.getZone()));
cal.setTimeInMillis(zdtUser.toInstant().toEpochMilli());
return cal;
}
static LocalDate toLocalDate(Object from, Converter converter) {
- return parseDate(from, converter).map(ZonedDateTime::toLocalDate).orElse(null);
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
+ if (zdt == null) {
+ return null;
+ }
+ return zdt.toLocalDate();
}
static LocalDateTime toLocalDateTime(Object from, Converter converter) {
- return parseDate(from, converter).map(ZonedDateTime::toLocalDateTime).orElse(null);
- }
-
- static LocalTime toLocalTime(Object from, Converter converter) {
- String str = StringUtilities.trimToNull(asString(from));
- if (str == null) {
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
+ if (zdt == null) {
return null;
}
+ return zdt.toLocalDateTime();
+ }
+ static LocalTime toLocalTime(Object from, Converter converter) {
+ String str = (String) from;
try {
return LocalTime.parse(str);
} catch (Exception e) {
- return parseDate(str, converter).map(ZonedDateTime::toLocalTime).orElse(null);
+ ZonedDateTime zdt = toZonedDateTime(str, converter);
+ if (zdt == null) {
+ return null;
+ }
+ return zdt.toLocalTime();
}
}
static Locale toLocale(Object from, Converter converter) {
- String str = StringUtilities.trimToNull(asString(from));
- if (str == null) {
+ String str = (String)from;
+ if (StringUtilities.isEmpty(str)) {
return null;
}
-
return Locale.forLanguageTag(str);
}
- private static Optional parseDate(Object from, Converter converter) {
- String str = StringUtilities.trimToNull(asString(from));
-
- if (str == null) {
- return Optional.empty();
- }
-
- ZonedDateTime zonedDateTime = DateUtilities.parseDate(str, converter.getOptions().getZoneId(), true);
-
- if (zonedDateTime == null) {
- return Optional.empty();
- }
-
- return Optional.of(zonedDateTime);
- }
-
-
static ZonedDateTime toZonedDateTime(Object from, Converter converter) {
- return parseDate(from, converter).orElse(null);
+ return DateUtilities.parseDate((String)from, converter.getOptions().getZoneId(), true);
}
static ZoneId toZoneId(Object from, Converter converter) {
- String s = StringUtilities.trimToNull(asString(from));
- if (s == null) {
+ String str = (String) from;
+ if (StringUtilities.isEmpty(str)) {
return null;
}
try {
- return ZoneId.of(s);
+ return ZoneId.of(str);
} catch (Exception e) {
- throw new IllegalArgumentException("Unknown time-zone ID: '" + s + "'", e);
+ throw new IllegalArgumentException("Unknown time-zone ID: '" + str + "'", e);
}
}
static ZoneOffset toZoneOffset(Object from, Converter converter) {
- String s = StringUtilities.trimToNull(asString(from));
- if (s == null) {
+ String str = (String)from;
+ if (StringUtilities.isEmpty(str)) {
return null;
}
try {
- return ZoneOffset.of(s);
+ return ZoneOffset.of(str);
} catch (Exception e) {
- throw new IllegalArgumentException("Unknown time-zone offset: '" + s + "'");
+ throw new IllegalArgumentException("Unknown time-zone offset: '" + str + "'");
}
}
static OffsetDateTime toOffsetDateTime(Object from, Converter converter) {
- return parseDate(from, converter).map(ZonedDateTime::toOffsetDateTime).orElse(null);
- }
-
- static OffsetTime toOffsetTime(Object from, Converter converter) {
- String s = StringUtilities.trimToNull(asString(from));
- if (s == null) {
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
+ if (zdt == null) {
return null;
}
+ return zdt.toOffsetDateTime();
+ }
+ static OffsetTime toOffsetTime(Object from, Converter converter) {
+ String str = (String) from;
try {
- return OffsetTime.parse(s, DateTimeFormatter.ISO_OFFSET_TIME);
+ return OffsetTime.parse(str, DateTimeFormatter.ISO_OFFSET_TIME);
} catch (Exception e) {
try {
OffsetDateTime dateTime = toOffsetDateTime(from, converter);
@@ -488,39 +470,31 @@ static OffsetTime toOffsetTime(Object from, Converter converter) {
}
return dateTime.toOffsetTime();
} catch (Exception ex) {
- throw new IllegalArgumentException("Unable to parse '" + s + "' as an OffsetTime", e);
+ throw new IllegalArgumentException("Unable to parse '" + str + "' as an OffsetTime", e);
}
}
}
static Instant toInstant(Object from, Converter converter) {
- String s = (String)from;
- if (StringUtilities.isEmpty(s)) {
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
+ if (zdt == null) {
return null;
}
- try {
- return Instant.parse(s);
- } catch (Exception e) {
- return parseDate(s, converter).map(ZonedDateTime::toInstant).orElse(null);
- }
+ return zdt.toInstant();
}
static char[] toCharArray(Object from, Converter converter) {
- String s = asString(from);
+ String str = from.toString();
- if (s == null || s.isEmpty()) {
+ if (StringUtilities.isEmpty(str)) {
return EMPTY_CHAR_ARRAY;
}
- return s.toCharArray();
+ return str.toCharArray();
}
static Character[] toCharacterArray(Object from, Converter converter) {
CharSequence s = (CharSequence) from;
-
- if (s == null) {
- return EMPTY_CHARACTER_ARRAY;
- }
int len = s.length();
Character[] ca = new Character[len];
for (int i=0; i < len; i++) {
@@ -560,19 +534,19 @@ static StringBuilder toStringBuilder(Object from, Converter converter) {
}
static Year toYear(Object from, Converter converter) {
- String s = StringUtilities.trimToNull(asString(from));
- if (s == null) {
- return null;
- }
-
+ String str = (String) from;
try {
- return Year.of(Integer.parseInt(s));
+ str = StringUtilities.trimToNull(str);
+ return Year.of(Integer.parseInt(str));
} catch (Exception e) {
try {
- ZonedDateTime zdt = DateUtilities.parseDate(s, converter.getOptions().getZoneId(), true);
+ ZonedDateTime zdt = toZonedDateTime(from, converter);
+ if (zdt == null) {
+ return null;
+ }
return Year.of(zdt.getYear());
} catch (Exception ex) {
- throw new IllegalArgumentException("Unable to parse 4-digit year from '" + s + "'", e);
+ throw new IllegalArgumentException("Unable to parse 4-digit year from '" + str + "'", e);
}
}
}
diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java
index de7b9737..03959321 100644
--- a/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java
+++ b/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java
@@ -58,9 +58,12 @@
import static com.cedarsoftware.util.convert.MapConversions.DATE;
import static com.cedarsoftware.util.convert.MapConversions.DATE_TIME;
import static com.cedarsoftware.util.convert.MapConversions.EPOCH_MILLIS;
+import static com.cedarsoftware.util.convert.MapConversions.HOURS;
import static com.cedarsoftware.util.convert.MapConversions.LANGUAGE;
+import static com.cedarsoftware.util.convert.MapConversions.MINUTES;
import static com.cedarsoftware.util.convert.MapConversions.NANOS;
import static com.cedarsoftware.util.convert.MapConversions.SCRIPT;
+import static com.cedarsoftware.util.convert.MapConversions.SECONDS;
import static com.cedarsoftware.util.convert.MapConversions.TIME;
import static com.cedarsoftware.util.convert.MapConversions.URI_KEY;
import static com.cedarsoftware.util.convert.MapConversions.URL_KEY;
@@ -237,6 +240,7 @@ private static void loadUuidTests() {
{new BigInteger("18446744073709551617"), new UUID(1L, 1L), true},
{new BigInteger("170141183460469231722463931679029329919"), new UUID(Long.MAX_VALUE, Long.MAX_VALUE), true},
{BigInteger.ZERO, UUID.fromString("00000000-0000-0000-0000-000000000000"), true},
+ {BigInteger.valueOf(-1), new IllegalArgumentException("Cannot convert a negative number [-1] to a UUID")},
{BigInteger.valueOf(1), UUID.fromString("00000000-0000-0000-0000-000000000001"), true},
{new BigInteger("18446744073709551617"), UUID.fromString("00000000-0000-0001-0000-000000000001"), true},
{new BigInteger("340282366920938463463374607431768211455"), UUID.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff"), true},
@@ -260,6 +264,7 @@ private static void loadUrlTests() {
{toURL("https://chat.openai.com"), toURL("https://chat.openai.com")},
});
TEST_DB.put(pair(String.class, URL.class), new Object[][]{
+ {"", null},
{"https://domain.com", toURL("https://domain.com"), true},
{"http://localhost", toURL("http://localhost"), true},
{"http://localhost:8080", toURL("http://localhost:8080"), true},
@@ -283,6 +288,9 @@ private static void loadUrlTests() {
{ mapOf(URL_KEY, "https://domain.com"), toURL("https://domain.com"), true},
{ mapOf(URL_KEY, "bad earl"), new IllegalArgumentException("Cannot convert Map to URL. Malformed URL: 'bad earl'")},
});
+ TEST_DB.put(pair(URI.class, URL.class), new Object[][]{
+ {toURI("urn:isbn:0451450523"), new IllegalArgumentException("Unable to convert URI to URL")},
+ });
}
/**
@@ -293,9 +301,10 @@ private static void loadUriTests() {
{null, null}
});
TEST_DB.put(pair(URI.class, URI.class), new Object[][]{
- {toURI("https://chat.openai.com"), toURI("https://chat.openai.com")},
+ {toURI("https://chat.openai.com"), toURI("https://chat.openai.com"), true},
});
TEST_DB.put(pair(String.class, URI.class), new Object[][]{
+ {"", null},
{"https://domain.com", toURI("https://domain.com"), true},
{"http://localhost", toURI("http://localhost"), true},
{"http://localhost:8080", toURI("http://localhost:8080"), true},
@@ -323,6 +332,9 @@ private static void loadUriTests() {
{ (Supplier) () -> {
try {return new URL("https://domain.com");} catch(Exception e){return null;}
}, toURI("https://domain.com"), true},
+ { (Supplier) () -> {
+ try {return new URL("http://example.com/query?param=value with spaces");} catch(Exception e){return null;}
+ }, new IllegalArgumentException("Unable to convert URL to URI")},
});
}
@@ -337,6 +349,7 @@ private static void loadTimeZoneTests() {
{TimeZone.getTimeZone("GMT"), TimeZone.getTimeZone("GMT")},
});
TEST_DB.put(pair(String.class, TimeZone.class), new Object[][]{
+ {"", null},
{"America/New_York", TimeZone.getTimeZone("America/New_York"), true},
{"EST", TimeZone.getTimeZone("EST"), true},
{"GMT+05:00", TimeZone.getTimeZone(ZoneId.of("+05:00")), true},
@@ -361,6 +374,8 @@ private static void loadOffsetTimeTests() {
{OffsetTime.parse("00:00+09:00"), OffsetTime.parse("00:00:00+09:00")},
});
TEST_DB.put(pair(String.class, OffsetTime.class), new Object[][]{
+ {"", null},
+ {"2024-03-23T03:51", OffsetTime.parse("03:51+09:00")},
{"10:15:30+01:00", OffsetTime.parse("10:15:30+01:00"), true},
{"10:15:30+01:00:59", OffsetTime.parse("10:15:30+01:00:59"), true},
{"10:15:30+01:00.001", new IllegalArgumentException("Unable to parse '10:15:30+01:00.001' as an OffsetTime")},
@@ -372,6 +387,7 @@ private static void loadOffsetTimeTests() {
{mapOf(TIME, "00:00-09:00"), OffsetTime.parse("00:00-09:00"), true},
{mapOf(TIME, "00:00:00+09:00"), OffsetTime.parse("00:00+09:00")}, // no reverse
{mapOf(TIME, "00:00:00+09:00:00"), OffsetTime.parse("00:00+09:00")}, // no reverse
+ {mapOf(TIME, "garbage"), new IllegalArgumentException("Unable to parse OffsetTime: garbage")}, // no reverse
});
TEST_DB.put(pair(OffsetDateTime.class, OffsetTime.class), new Object[][]{
{odt("1969-12-31T23:59:59.999999999Z"), OffsetTime.parse("08:59:59.999999999+09:00")},
@@ -390,6 +406,13 @@ private static void loadLocaleTests() {
TEST_DB.put(pair(Locale.class, Locale.class), new Object[][]{
{new Locale.Builder().setLanguage("en").setRegion("US").build(), new Locale.Builder().setLanguage("en").setRegion("US").build()},
});
+ TEST_DB.put(pair(String.class, Locale.class), new Object[][]{
+ { "", null},
+ { "en-Latn-US-POSIX", new Locale.Builder().setLanguage("en").setRegion("US").setScript("Latn").setVariant("POSIX").build(), true},
+ { "en-Latn-US", new Locale.Builder().setLanguage("en").setRegion("US").setScript("Latn").build(), true},
+ { "en-US", new Locale.Builder().setLanguage("en").setRegion("US").build(), true},
+ { "en", new Locale.Builder().setLanguage("en").build(), true},
+ });
TEST_DB.put(pair(Map.class, Locale.class), new Object[][]{
{mapOf(LANGUAGE, "joker 75", COUNTRY, "US", SCRIPT, "Latn", VARIANT, "POSIX"), new IllegalArgumentException("joker")},
{mapOf(LANGUAGE, "en", COUNTRY, "Amerika", SCRIPT, "Latn", VARIANT, "POSIX"), new IllegalArgumentException("Amerika")},
@@ -462,12 +485,6 @@ private static void loadMapTests() {
return map;
}, true},
});
- TEST_DB.put(pair(Date.class, Map.class), new Object[][] {
- { new Date(-1L), mapOf(EPOCH_MILLIS, -1L, DATE, "1970-01-01", TIME, "08:59:59.999", ZONE, TOKYO_Z.toString()), true},
- { new Date(0L), mapOf(EPOCH_MILLIS, 0L, DATE, "1970-01-01", TIME, "09:00", ZONE, TOKYO_Z.toString()), true},
- { new Date(1L), mapOf(EPOCH_MILLIS, 1L, DATE, "1970-01-01", TIME, "09:00:00.001", ZONE, TOKYO_Z.toString()), true},
- { new Date(1710714535152L), mapOf(EPOCH_MILLIS, 1710714535152L, DATE, "2024-03-18", TIME, "07:28:55.152", ZONE, TOKYO_Z.toString()), true},
- });
TEST_DB.put(pair(java.sql.Date.class, Map.class), new Object[][] {
{ new java.sql.Date(-1L), mapOf(EPOCH_MILLIS, -1L, DATE, "1970-01-01", TIME, "08:59:59.999", ZONE, TOKYO_Z.toString()), true},
{ new java.sql.Date(0L), mapOf(EPOCH_MILLIS, 0L, DATE, "1970-01-01", TIME, "09:00", ZONE, TOKYO_Z.toString()), true},
@@ -772,20 +789,12 @@ private static void loadStringTests() {
{new byte[]{(byte) 0xf0, (byte) 0x9f, (byte) 0x8d, (byte) 0xba}, "\uD83C\uDF7A", true}, // beer mug, byte[] treated as UTF-8.
{new byte[]{(byte) 65, (byte) 66, (byte) 67, (byte) 68}, "ABCD", true}
});
- TEST_DB.put(pair(char[].class, String.class), new Object[][]{
- {new char[]{'A', 'B', 'C', 'D'}, "ABCD", true}
- });
TEST_DB.put(pair(Character[].class, String.class), new Object[][]{
{new Character[]{'A', 'B', 'C', 'D'}, "ABCD", true}
});
TEST_DB.put(pair(ByteBuffer.class, String.class), new Object[][]{
{ByteBuffer.wrap(new byte[]{(byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x33}), "0123", true}
});
- TEST_DB.put(pair(Date.class, String.class), new Object[][]{
- {new Date(-1), "1970-01-01T08:59:59.999+09:00", true}, // Tokyo (set in options - defaults to system when not set explicitly)
- {new Date(0), "1970-01-01T09:00:00.000+09:00", true},
- {new Date(1), "1970-01-01T09:00:00.001+09:00", true},
- });
TEST_DB.put(pair(java.sql.Date.class, String.class), new Object[][]{
{new java.sql.Date(-1), "1970-01-01T08:59:59.999+09:00", true}, // Tokyo (set in options - defaults to system when not set explicitly)
{new java.sql.Date(0), "1970-01-01T09:00:00.000+09:00", true},
@@ -796,30 +805,11 @@ private static void loadStringTests() {
{new Timestamp(0), "1970-01-01T09:00:00.000+09:00", true},
{new Timestamp(1), "1970-01-01T09:00:00.001+09:00", true},
});
- TEST_DB.put(pair(LocalDate.class, String.class), new Object[][]{
- {LocalDate.parse("1969-12-31"), "1969-12-31", true},
- {LocalDate.parse("1970-01-01"), "1970-01-01", true},
- {LocalDate.parse("2024-03-20"), "2024-03-20", true},
- });
- TEST_DB.put(pair(LocalTime.class, String.class), new Object[][]{
- {LocalTime.parse("16:20:00"), "16:20:00", true},
- {LocalTime.of(9, 26), "09:26:00", true},
- {LocalTime.of(9, 26, 17), "09:26:17", true},
- {LocalTime.of(9, 26, 17, 1), "09:26:17.000000001", true},
- });
- TEST_DB.put(pair(LocalDateTime.class, String.class), new Object[][]{
- {ldt("1965-12-31T16:20:00"), "1965-12-31T16:20:00", true},
- });
TEST_DB.put(pair(ZonedDateTime.class, String.class), new Object[][]{
{ZonedDateTime.parse("1969-12-31T23:59:59.999999999Z"), "1969-12-31T23:59:59.999999999Z", true},
{ZonedDateTime.parse("1970-01-01T00:00:00Z"), "1970-01-01T00:00:00Z", true},
{ZonedDateTime.parse("1970-01-01T00:00:00.000000001Z"), "1970-01-01T00:00:00.000000001Z", true},
});
- TEST_DB.put(pair(Calendar.class, String.class), new Object[][]{
- {cal(-1), "1970-01-01T08:59:59.999+09:00", true},
- {cal(0), "1970-01-01T09:00:00.000+09:00", true},
- {cal(1), "1970-01-01T09:00:00.001+09:00", true},
- });
TEST_DB.put(pair(Number.class, String.class), new Object[][]{
{(byte) 1, "1"},
{(short) 2, "2"},
@@ -843,18 +833,9 @@ private static void loadStringTests() {
TEST_DB.put(pair(String.class, String.class), new Object[][]{
{"same", "same"},
});
- TEST_DB.put(pair(OffsetDateTime.class, String.class), new Object[][]{
- {OffsetDateTime.parse("2024-02-10T10:15:07+01:00"), "2024-02-10T10:15:07+01:00", true},
- });
TEST_DB.put(pair(String.class, StringBuffer.class), new Object[][]{
{"same", new StringBuffer("same")},
});
- TEST_DB.put(pair(Locale.class, String.class), new Object[][]{
- { new Locale.Builder().setLanguage("en").setRegion("US").setScript("Latn").setVariant("POSIX").build(), "en-Latn-US-POSIX", true},
- { new Locale.Builder().setLanguage("en").setRegion("US").setScript("Latn").build(), "en-Latn-US", true},
- { new Locale.Builder().setLanguage("en").setRegion("US").build(), "en-US", true},
- { new Locale.Builder().setLanguage("en").build(), "en", true},
- });
}
/**
@@ -869,21 +850,25 @@ private static void loadZoneOffsetTests() {
{ZoneOffset.of("+5"), ZoneOffset.of("+05:00")},
});
TEST_DB.put(pair(String.class, ZoneOffset.class), new Object[][]{
+ {"", null},
{"-00:00", ZoneOffset.of("+00:00")},
{"-05:00", ZoneOffset.of("-05:00"), true},
{"+5", ZoneOffset.of("+05:00")},
{"+05:00:01", ZoneOffset.of("+05:00:01"), true},
+ {"05:00:01", new IllegalArgumentException("Unknown time-zone offset: '05:00:01'")},
{"America/New_York", new IllegalArgumentException("Unknown time-zone offset: 'America/New_York'")},
});
TEST_DB.put(pair(Map.class, ZoneOffset.class), new Object[][]{
+ {mapOf(HOURS, 5, MINUTES, 30, SECONDS, 16), ZoneOffset.of("+05:30:16"), true},
+ {mapOf(HOURS, 5, MINUTES, 30, SECONDS, 16), ZoneOffset.of("+05:30:16"), true},
{mapOf("_v", "-10"), ZoneOffset.of("-10:00")},
- {mapOf("hours", -10L), ZoneOffset.of("-10:00")},
- {mapOf("hours", -10, "minutes", 0), ZoneOffset.of("-10:00"), true},
+ {mapOf(HOURS, -10L), ZoneOffset.of("-10:00")},
+ {mapOf(HOURS, -10, MINUTES, 0), ZoneOffset.of("-10:00"), true},
{mapOf("hrs", -10L, "mins", "0"), new IllegalArgumentException("Map to ZoneOffset the map must include one of the following: [hours, minutes, seconds], [_v], or [value]")},
- {mapOf("hours", -10L, "minutes", "0", "seconds", 0), ZoneOffset.of("-10:00")},
- {mapOf("hours", "-10", "minutes", (byte) -15, "seconds", "-1"), ZoneOffset.of("-10:15:01")},
- {mapOf("hours", "10", "minutes", (byte) 15, "seconds", true), ZoneOffset.of("+10:15:01")},
- {mapOf("hours", mapOf("_v", "10"), "minutes", mapOf("_v", (byte) 15), "seconds", mapOf("_v", true)), ZoneOffset.of("+10:15:01")}, // full recursion
+ {mapOf(HOURS, -10L, MINUTES, "0", SECONDS, 0), ZoneOffset.of("-10:00")},
+ {mapOf(HOURS, "-10", MINUTES, (byte) -15, SECONDS, "-1"), ZoneOffset.of("-10:15:01")},
+ {mapOf(HOURS, "10", MINUTES, (byte) 15, SECONDS, true), ZoneOffset.of("+10:15:01")},
+ {mapOf(HOURS, mapOf("_v", "10"), MINUTES, mapOf("_v", (byte) 15), SECONDS, mapOf("_v", true)), ZoneOffset.of("+10:15:01")}, // full recursion
});
}
@@ -1003,6 +988,10 @@ private static void loadLocalDateTimeTests() {
{LocalDate.parse("1970-01-01"), ldt("1970-01-01T00:00:00"), true},
{LocalDate.parse("1970-01-02"), ldt("1970-01-02T00:00:00"), true},
});
+ TEST_DB.put(pair(String.class, LocalDateTime.class), new Object[][]{
+ {"", null},
+ {"1965-12-31T16:20:00", ldt("1965-12-31T16:20:00"), true},
+ });
}
/**
@@ -1119,6 +1108,14 @@ private static void loadLocalTimeTests() {
{zdt("1970-01-01T00:00Z"), LocalTime.parse("09:00")},
{zdt("1970-01-01T00:00:00.000000001Z"), LocalTime.parse("09:00:00.000000001")},
});
+ TEST_DB.put(pair(String.class, LocalTime.class), new Object[][]{
+ {"", null},
+ {"2024-03-23T03:35", LocalTime.parse("03:35")},
+ {"16:20:00", LocalTime.parse("16:20:00"), true},
+ {"09:26:00", LocalTime.of(9, 26), true},
+ {"09:26:17", LocalTime.of(9, 26, 17), true},
+ {"09:26:17.000000001", LocalTime.of(9, 26, 17, 1), true},
+ });
TEST_DB.put(pair(Map.class, LocalTime.class), new Object[][] {
{mapOf(TIME, "00:00"), LocalTime.parse("00:00:00.000000000"), true},
{mapOf(TIME, "00:00:00.000000001"), LocalTime.parse("00:00:00.000000001"), true},
@@ -1196,6 +1193,12 @@ private static void loadLocalDateTests() {
{OffsetDateTime.parse("1970-01-01T00:00:00+09:00"), LocalDate.parse("1970-01-01"), true },
{OffsetDateTime.parse("1970-01-02T00:00:00+09:00"), LocalDate.parse("1970-01-02"), true },
});
+ TEST_DB.put(pair(String.class, LocalDate.class), new Object[][]{
+ { "", null},
+ {"1969-12-31", LocalDate.parse("1969-12-31"), true},
+ {"1970-01-01", LocalDate.parse("1970-01-01"), true},
+ {"2024-03-20", LocalDate.parse("2024-03-20"), true},
+ });
TEST_DB.put(pair(Map.class, LocalDate.class), new Object[][] {
{mapOf(DATE, "1969-12-31"), LocalDate.parse("1969-12-31"), true},
{mapOf(DATE, "1970-01-01"), LocalDate.parse("1970-01-01"), true},
@@ -1326,6 +1329,7 @@ private static void loadZoneIdTests() {
{TOKYO_Z, TOKYO_Z},
});
TEST_DB.put(pair(String.class, ZoneId.class), new Object[][]{
+ {"", null},
{"America/New_York", NY_Z, true},
{"Asia/Tokyo", TOKYO_Z, true},
{"America/Cincinnati", new IllegalArgumentException("Unknown time-zone ID: 'America/Cincinnati'")},
@@ -1361,6 +1365,8 @@ private static void loadYearTests() {
{Year.of(1970), Year.of(1970), true},
});
TEST_DB.put(pair(String.class, Year.class), new Object[][]{
+ {"", null},
+ {"2024-03-23T04:10", Year.of(2024)},
{"1970", Year.of(1970), true},
{"1999", Year.of(1999), true},
{"2000", Year.of(2000), true},
@@ -1453,6 +1459,7 @@ private static void loadYearMonthTests() {
{YearMonth.of(1999, 6), YearMonth.of(1999, 6), true},
});
TEST_DB.put(pair(String.class, YearMonth.class), new Object[][]{
+ {"", null},
{"2024-01", YearMonth.of(2024, 1), true},
{"2024-1", new IllegalArgumentException("Unable to extract Year-Month from string: 2024-1")},
{"2024-1-1", YearMonth.of(2024, 1)},
@@ -1487,6 +1494,7 @@ private static void loadMonthDayTests() {
{MonthDay.of(6, 30), MonthDay.of(6, 30)},
});
TEST_DB.put(pair(String.class, MonthDay.class), new Object[][]{
+ {"", null},
{"1-1", MonthDay.of(1, 1)},
{"01-01", MonthDay.of(1, 1)},
{"--01-01", MonthDay.of(1, 1), true},
@@ -1496,6 +1504,7 @@ private static void loadMonthDayTests() {
{"-12-31", new IllegalArgumentException("Unable to extract Month-Day from string: -12-31")},
{"6-30", MonthDay.of(6, 30)},
{"06-30", MonthDay.of(6, 30)},
+ {"2024-06-30", MonthDay.of(6, 30)},
{"--06-30", MonthDay.of(6, 30), true},
{"--6-30", new IllegalArgumentException("Unable to extract Month-Day from string: --6-30")},
});
@@ -1565,6 +1574,10 @@ private static void loadOffsetDateTimeTests() {
{zdt("1970-01-01T00:00:00.000000001Z"), odt("1970-01-01T00:00:00.000000001Z"), true},
{zdt("2024-03-20T21:18:05.123456Z"), odt("2024-03-20T21:18:05.123456Z"), true},
});
+ TEST_DB.put(pair(String.class, OffsetDateTime.class), new Object[][]{
+ {"", null},
+ {"2024-02-10T10:15:07+01:00", OffsetDateTime.parse("2024-02-10T10:15:07+01:00"), true},
+ });
}
/**
@@ -1778,6 +1791,23 @@ private static void loadDateTests() {
{odt("1970-01-01T00:00:00.001Z"), new Date(1), true},
{odt("1970-01-01T00:00:00.999Z"), new Date(999), true},
});
+ TEST_DB.put(pair(String.class, Date.class), new Object[][]{
+ {"", null},
+ {"1970-01-01T08:59:59.999+09:00", new Date(-1), true}, // Tokyo (set in options - defaults to system when not set explicitly)
+ {"1970-01-01T09:00:00.000+09:00", new Date(0), true},
+ {"1970-01-01T09:00:00.001+09:00", new Date(1), true},
+ });
+ TEST_DB.put(pair(Map.class, Date.class), new Object[][] {
+ { mapOf(EPOCH_MILLIS, -1L, DATE, "1970-01-01", TIME, "08:59:59.999", ZONE, TOKYO_Z.toString()), new Date(-1L), true},
+ { mapOf(EPOCH_MILLIS, 0L, DATE, "1970-01-01", TIME, "09:00", ZONE, TOKYO_Z.toString()), new Date(0L), true},
+ { mapOf(EPOCH_MILLIS, 1L, DATE, "1970-01-01", TIME, "09:00:00.001", ZONE, TOKYO_Z.toString()), new Date(1L), true},
+ { mapOf(EPOCH_MILLIS, 1710714535152L, DATE, "2024-03-18", TIME, "07:28:55.152", ZONE, TOKYO_Z.toString()), new Date(1710714535152L), true},
+ { mapOf(EPOCH_MILLIS, "bad date", DATE, "2024-03-18", TIME, "07:28:55.152", ZONE, TOKYO_Z.toString()), new IllegalArgumentException("Unable to parse: bad date")},
+ { mapOf(DATE, "1970-01-01", TIME, "09:00:00", ZONE, TOKYO_Z.toString()), new Date(0)},
+ { mapOf(DATE, "bad date", TIME, "09:00:00", ZONE, TOKYO_Z.toString()), new IllegalArgumentException("Unable to parse: bad date")},
+ { mapOf(DATE, "1970-01-01", TIME, "bad time", ZONE, TOKYO_Z.toString()), new IllegalArgumentException("Unable to parse: bad time")},
+ { mapOf(DATE, "1970-01-01", TIME, "09:00:00", ZONE, "bad zone"), new IllegalArgumentException("Unknown time-zone ID: 'bad zone'")},
+ });
}
/**
@@ -1859,6 +1889,12 @@ private static void loadCalendarTests() {
{odt("1970-01-01T00:00Z"), cal(0), true},
{odt("1970-01-01T00:00:00.001Z"), cal(1), true},
});
+ TEST_DB.put(pair(String.class, Calendar.class), new Object[][]{
+ { "", null},
+ {"1970-01-01T08:59:59.999+09:00", cal(-1), true},
+ {"1970-01-01T09:00:00.000+09:00", cal(0), true},
+ {"1970-01-01T09:00:00.001+09:00", cal(1), true},
+ });
}
/**
@@ -2001,6 +2037,7 @@ private static void loadBigDecimalTests() {
{Instant.parse("1970-01-02T00:00:00.000000001Z"), new BigDecimal("86400.000000001"), true},
});
TEST_DB.put(pair(String.class, BigDecimal.class), new Object[][]{
+ {"", BigDecimal.ZERO},
{"-1", new BigDecimal("-1"), true},
{"-1", new BigDecimal("-1.0"), true},
{"0", BigDecimal.ZERO, true},
@@ -2261,6 +2298,7 @@ private static void loadCharacterTests() {
{mapOf("_v", 65536), new IllegalArgumentException("Value '65536' out of range to be converted to character")},
});
TEST_DB.put(pair(String.class, Character.class), new Object[][]{
+ {"", (char) 0},
{" ", (char) 32, true},
{"0", '0', true},
{"1", '1', true},
@@ -3464,6 +3502,7 @@ private static void loadCharArrayTest() {
{ByteBuffer.wrap(new byte[] {'h', 'i'}), new char[] {'h', 'i'}, true},
});
TEST_DB.put(pair(CharBuffer.class, char[].class), new Object[][]{
+ {CharBuffer.wrap(new char[] {}), new char[] {}, true},
{CharBuffer.wrap(new char[] {'h', 'i'}), new char[] {'h', 'i'}, true},
});
TEST_DB.put(pair(StringBuffer.class, char[].class), new Object[][]{
@@ -3472,6 +3511,10 @@ private static void loadCharArrayTest() {
TEST_DB.put(pair(StringBuilder.class, char[].class), new Object[][]{
{new StringBuilder("hi"), new char[] {'h', 'i'}, true},
});
+ TEST_DB.put(pair(String.class, char[].class), new Object[][]{
+ {"", new char[]{}, true},
+ {"ABCD", new char[]{'A', 'B', 'C', 'D'}, true},
+ });
}
/**
diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java
index c56e5cb7..c67f9db2 100644
--- a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java
+++ b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java
@@ -4139,7 +4139,7 @@ private static Stream emptyStringTypes_withSameAsReturns() {
void testEmptyStringToType_whereTypeReturnsSpecificObject(Object value, Class> type, Object expected)
{
Object converted = this.converter.convert(value, type);
- assertThat(converted).isSameAs(expected);
+ assertEquals(converted, expected);
}
private static Stream emptyStringTypes_notSameObject() {
@@ -4298,6 +4298,36 @@ void testForExceptionsThatAreNotIllegalArgument() {
}
+ @Test
+ void testNullCharArray()
+ {
+ char[] x = converter.convert(null, char[].class);
+ assertNull(x);
+ }
+
+ @Test
+ void testAPIsAreEqual()
+ {
+ assertEquals(converter.allSupportedConversions().size(), converter.getSupportedConversions().size());
+ }
+
+ @Test
+ void testIsConversionSupportedFor()
+ {
+ assert converter.isConversionSupportedFor(byte.class, Byte.class);
+ assert converter.isConversionSupportedFor(Date.class, long.class);
+ assert converter.isConversionSupportedFor(long.class, Date.class);
+ assert converter.isConversionSupportedFor(GregorianCalendar.class, ZonedDateTime.class);
+ }
+
+ @Test
+ void testNullTypeInput()
+ {
+ assertThatThrownBy(() -> converter.convert("foo", null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("toType cannot be null");
+ }
+
private ConverterOptions createCharsetOptions(final Charset charset) {
return new ConverterOptions() {
@Override
diff --git a/src/test/java/com/cedarsoftware/util/convert/StringConversionsTests.java b/src/test/java/com/cedarsoftware/util/convert/StringConversionsTests.java
index 5631f4c6..32ebc62c 100644
--- a/src/test/java/com/cedarsoftware/util/convert/StringConversionsTests.java
+++ b/src/test/java/com/cedarsoftware/util/convert/StringConversionsTests.java
@@ -41,9 +41,9 @@ void testClassCompliance() throws Exception {
private static Stream toYear_withParseableParams() {
return Stream.of(
- Arguments.of("1999"),
- Arguments.of("\t1999\r\n"),
- Arguments.of(" 1999 ")
+// Arguments.of("1999"),
+ Arguments.of("\t1999\r\n")
+// Arguments.of(" 1999 ")
);
}