From 52dd3c2bc747d8984b94deb9489a7d4271118d74 Mon Sep 17 00:00:00 2001 From: Ken Partlow Date: Wed, 24 Jan 2024 18:01:23 -0500 Subject: [PATCH 1/6] Added Instant Conversions Updated StringUtilities to support less Specific CharSequence over String Moved in more MapConversions Updated conversion classes to have the (s) to match JDK Patterns (Arrays, Collections) for static utility classes. --- .../com/cedarsoftware/util/DateUtilities.java | 4 +- .../cedarsoftware/util/StringUtilities.java | 282 +++++- ...ion.java => AtomicBooleanConversions.java} | 8 +- ...onversion.java => BooleanConversions.java} | 8 +- ...nversion.java => CalendarConversions.java} | 8 +- ...version.java => CharacterConversions.java} | 11 +- .../cedarsoftware/util/convert/Converter.java | 833 +++++++++--------- .../util/convert/ConverterOptions.java | 12 + ...teConversion.java => DateConversions.java} | 33 +- .../util/convert/InstantConversion.java | 67 -- .../util/convert/InstantConversions.java | 76 ++ ...version.java => LocalDateConversions.java} | 4 +- ...ion.java => LocalDateTimeConversions.java} | 3 +- ...MapConversion.java => MapConversions.java} | 104 ++- ...Conversion.java => NumberConversions.java} | 18 +- ...Conversion.java => StringConversions.java} | 50 +- .../util/convert/UUIDConversions.java | 28 + ...idConversion.java => VoidConversions.java} | 5 +- ...ion.java => ZonedDateTimeConversions.java} | 4 +- .../util/TestStringUtilities.java | 499 +++++++++-- .../AtomicBooleanConversionsTests.java | 210 +++++ .../util/convert/BooleanConversionsTests.java | 229 +++++ .../util/convert/ConverterTest.java | 183 ++-- 23 files changed, 1901 insertions(+), 778 deletions(-) rename src/main/java/com/cedarsoftware/util/convert/{AtomicBooleanConversion.java => AtomicBooleanConversions.java} (92%) rename src/main/java/com/cedarsoftware/util/convert/{BooleanConversion.java => BooleanConversions.java} (95%) rename src/main/java/com/cedarsoftware/util/convert/{CalendarConversion.java => CalendarConversions.java} (94%) rename src/main/java/com/cedarsoftware/util/convert/{CharacterConversion.java => CharacterConversions.java} (90%) rename src/main/java/com/cedarsoftware/util/convert/{DateConversion.java => DateConversions.java} (62%) delete mode 100644 src/main/java/com/cedarsoftware/util/convert/InstantConversion.java create mode 100644 src/main/java/com/cedarsoftware/util/convert/InstantConversions.java rename src/main/java/com/cedarsoftware/util/convert/{LocalDateConversion.java => LocalDateConversions.java} (96%) rename src/main/java/com/cedarsoftware/util/convert/{LocalDateTimeConversion.java => LocalDateTimeConversions.java} (97%) rename src/main/java/com/cedarsoftware/util/convert/{MapConversion.java => MapConversions.java} (57%) rename src/main/java/com/cedarsoftware/util/convert/{NumberConversion.java => NumberConversions.java} (92%) rename src/main/java/com/cedarsoftware/util/convert/{StringConversion.java => StringConversions.java} (85%) create mode 100644 src/main/java/com/cedarsoftware/util/convert/UUIDConversions.java rename src/main/java/com/cedarsoftware/util/convert/{VoidConversion.java => VoidConversions.java} (94%) rename src/main/java/com/cedarsoftware/util/convert/{ZonedDateTimeConversion.java => ZonedDateTimeConversions.java} (95%) create mode 100644 src/test/java/com/cedarsoftware/util/convert/AtomicBooleanConversionsTests.java create mode 100644 src/test/java/com/cedarsoftware/util/convert/BooleanConversionsTests.java diff --git a/src/main/java/com/cedarsoftware/util/DateUtilities.java b/src/main/java/com/cedarsoftware/util/DateUtilities.java index dfccd86d..13c20339 100644 --- a/src/main/java/com/cedarsoftware/util/DateUtilities.java +++ b/src/main/java/com/cedarsoftware/util/DateUtilities.java @@ -157,7 +157,7 @@ private DateUtilities() { * passed in, null will be returned. */ public static Date parseDate(String dateStr) { - if (StringUtilities.isEmpty(dateStr)) { + if (StringUtilities.isWhitespace(dateStr)) { return null; } ZonedDateTime zonedDateTime = parseDate(dateStr, ZoneId.systemDefault(), true); @@ -357,4 +357,4 @@ private static String stripBrackets(String input) { } return input.replaceAll("^\\[|\\]$", ""); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cedarsoftware/util/StringUtilities.java b/src/main/java/com/cedarsoftware/util/StringUtilities.java index 8e8954b4..992c1dd0 100644 --- a/src/main/java/com/cedarsoftware/util/StringUtilities.java +++ b/src/main/java/com/cedarsoftware/util/StringUtilities.java @@ -1,6 +1,7 @@ package com.cedarsoftware.util; import java.io.UnsupportedEncodingException; +import java.util.Optional; import java.util.Random; /** @@ -31,6 +32,8 @@ public final class StringUtilities }; public static final String FOLDER_SEPARATOR = "/"; + public static final String EMPTY = ""; + /** *

Constructor is declared private since all methods are static.

*/ @@ -39,22 +42,124 @@ private StringUtilities() super(); } - public static boolean equals(final String str1, final String str2) - { - if (str1 == null || str2 == null) - { - return str1 == str2; + /** + * Compares two CharSequences, returning {@code true} if they represent + * equal sequences of characters. + * + *

{@code null}s are handled without exceptions. Two {@code null} + * references are considered to be equal. The comparison is case-sensitive.

+ * + * @param cs1 the first CharSequence, may be {@code null} + * @param cs2 the second CharSequence, may be {@code null} + * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} + * @see #equalsIgnoreCase(CharSequence, CharSequence) + */ + public static boolean equals(final CharSequence cs1, final CharSequence cs2) { + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null) { + return false; + } + if (cs1.length() != cs2.length()) { + return false; + } + if (cs1 instanceof String && cs2 instanceof String) { + return cs1.equals(cs2); + } + // Step-wise comparison + final int length = cs1.length(); + for (int i = 0; i < length; i++) { + if (cs1.charAt(i) != cs2.charAt(i)) { + return false; + } } - return str1.equals(str2); + return true; } - public static boolean equalsIgnoreCase(final String s1, final String s2) - { - if (s1 == null || s2 == null) - { - return s1 == s2; + /** + * Compares two CharSequences, returning {@code true} if they represent + * equal sequences of characters, ignoring case. + * + *

{@code null}s are handled without exceptions. Two {@code null} + * references are considered equal. The comparison is case insensitive.

+ * + * @param cs1 the first CharSequence, may be {@code null} + * @param cs2 the second CharSequence, may be {@code null} + * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null} + * @see #equals(CharSequence, CharSequence) + */ + public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null) { + return false; } - return s1.equalsIgnoreCase(s2); + if (cs1.length() != cs2.length()) { + return false; + } + return regionMatches(cs1, true, 0, cs2, 0, cs1.length()); + } + + /** + * Green implementation of regionMatches. + * + * @param cs the {@link CharSequence} to be processed + * @param ignoreCase whether or not to be case-insensitive + * @param thisStart the index to start on the {@code cs} CharSequence + * @param substring the {@link CharSequence} to be looked for + * @param start the index to start on the {@code substring} CharSequence + * @param length character length of the region + * @return whether the region matched + */ + static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart, + final CharSequence substring, final int start, final int length) { + Convention.throwIfNull(cs, "cs to be processed cannot be null"); + Convention.throwIfNull(substring, "substring cannot be null"); + + if (cs instanceof String && substring instanceof String) { + return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length); + } + int index1 = thisStart; + int index2 = start; + int tmpLen = length; + + // Extract these first so we detect NPEs the same as the java.lang.String version + final int srcLen = cs.length() - thisStart; + final int otherLen = substring.length() - start; + + // Check for invalid parameters + if (thisStart < 0 || start < 0 || length < 0) { + return false; + } + + // Check that the regions are long enough + if (srcLen < length || otherLen < length) { + return false; + } + + while (tmpLen-- > 0) { + final char c1 = cs.charAt(index1++); + final char c2 = substring.charAt(index2++); + + if (c1 == c2) { + continue; + } + + if (!ignoreCase) { + return false; + } + + // The real same check as in String.regionMatches(): + final char u1 = Character.toUpperCase(c1); + final char u2 = Character.toUpperCase(c2); + if (u1 != u2 && Character.toLowerCase(u1) != Character.toLowerCase(u2)) { + return false; + } + } + + return true; } public static boolean equalsWithTrim(final String s1, final String s2) @@ -75,41 +180,89 @@ public static boolean equalsIgnoreCaseWithTrim(final String s1, final String s2) return s1.trim().equalsIgnoreCase(s2.trim()); } - public static boolean isEmpty(final String s) - { - return trimLength(s) == 0; + /** + * Checks if a CharSequence is empty ("") or null. + * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is empty or null + * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) + */ + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; } - public static boolean hasContent(final String s) - { - return !(trimLength(s) == 0); // faster than returning !isEmpty() + /** + * Checks if a CharSequence is not empty ("") and not null. + * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is not empty and not null + */ + public static boolean isNotEmpty(final CharSequence cs) { + return !isEmpty(cs); } /** - * Use this method when you don't want a length check to - * throw a NullPointerException when + * Checks if a CharSequence is empty (""), null or whitespace only. * - * @param s string to return length of - * @return 0 if string is null, otherwise the length of string. + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is null, empty or whitespace only */ - public static int length(final String s) - { - return s == null ? 0 : s.length(); + public static boolean isWhitespace(final CharSequence cs) { + final int strLen = length(cs); + if (strLen == 0) { + return true; + } + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + return true; } /** - * Returns the length of the trimmed string. If the length is - * null then it returns 0. + * Checks if a CharSequence is not empty (""), not null and not whitespace only. + * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is + * not empty and not null and not whitespace only */ - public static int trimLength(final String s) - { - return (s == null) ? 0 : s.trim().length(); + public static boolean hasContent(final CharSequence cs) { + return !isWhitespace(cs); } - public static int lastIndexOf(String path, char ch) - { - if (path == null) - { + /** + * Checks if a CharSequence is not empty (""), not null and not whitespace only. + * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is + * not empty and not null and not whitespace only + */ + public static boolean isNotWhitespace(final CharSequence cs) { + return !isWhitespace(cs); + } + + /** + * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}. + * + * @param cs a CharSequence or {@code null} + * @return CharSequence length or {@code 0} if the CharSequence is {@code null}. + */ + public static int length(final CharSequence cs) { + return cs == null ? 0 : cs.length(); + } + + /** + * @param s a String or {@code null} + * @return the trimmed length of the String or 0 if the string is null. + */ + public static int trimLength(final String s) { + return trimToEmpty(s).length(); + } + + + public static int lastIndexOf(String path, char ch) { + if (path == null) { return -1; } return path.lastIndexOf(ch); @@ -169,7 +322,7 @@ private static char convertDigit(int value) public static int count(String s, char c) { - return count (s, "" + c); + return count (s, EMPTY + c); } /** @@ -268,11 +421,11 @@ public static String wildcardToRegexString(String wildcard) public static int levenshteinDistance(CharSequence s, CharSequence t) { // degenerate cases s - if (s == null || "".equals(s)) + if (s == null || EMPTY.equals(s)) { - return t == null || "".equals(t) ? 0 : t.length(); + return t == null || EMPTY.equals(t) ? 0 : t.length(); } - else if (t == null || "".equals(t)) + else if (t == null || EMPTY.equals(t)) { return s.length(); } @@ -329,11 +482,11 @@ else if (t == null || "".equals(t)) */ public static int damerauLevenshteinDistance(CharSequence source, CharSequence target) { - if (source == null || "".equals(source)) + if (source == null || EMPTY.equals(source)) { - return target == null || "".equals(target) ? 0 : target.length(); + return target == null || EMPTY.equals(target) ? 0 : target.length(); } - else if (target == null || "".equals(target)) + else if (target == null || EMPTY.equals(target)) { return source.length(); } @@ -415,6 +568,7 @@ public static String getRandomString(Random random, int minLen, int maxLen) { StringBuilder s = new StringBuilder(); final int len = minLen + random.nextInt(maxLen - minLen + 1); + for (int i=0; i < len; i++) { s.append(getRandomChar(random, i == 0)); @@ -425,7 +579,7 @@ public static String getRandomString(Random random, int minLen, int maxLen) public static String getRandomChar(Random random, boolean upper) { int r = random.nextInt(26); - return upper ? "" + (char)((int)'A' + r) : "" + (char)((int)'a' + r); + return upper ? EMPTY + (char)((int)'A' + r) : EMPTY + (char)((int)'a' + r); } /** @@ -523,4 +677,48 @@ public static int hashCodeIgnoreCase(String s) } return hash; } + + /** + * Removes control characters (char <= 32) from both + * ends of this String, handling {@code null} by returning + * {@code null}. + * + *

The String is trimmed using {@link String#trim()}. + * Trim removes start and end characters <= 32. + * + * @param str the String to be trimmed, may be null + * @return the trimmed string, {@code null} if null String input + */ + public static String trim(final String str) { + return str == null ? null : str.trim(); + } + + /** + * Trims a string, its null safe and null will return empty string here.. + * @param value string input + * @return String trimmed string, if value was null this will be empty + */ + public static String trimToEmpty(String value) { + return value == null ? EMPTY : value.trim(); + } + + /** + * Trims a string, If the string trims to empty then we return null. + * @param value string input + * @return String, trimmed from value. If the value was empty we return null. + */ + public static String trimToNull(String value) { + final String ts = trim(value); + return isEmpty(ts) ? null : ts; + } + + /** + * Trims a string, If the string trims to empty then we return the default. + * @param value string input + * @param defaultValue value to return on empty or null + * @return trimmed string, or defaultValue when null or empty + */ + public static String trimEmptyToDefault(String value, String defaultValue) { + return Optional.ofNullable(value).map(StringUtilities::trimToNull).orElse(defaultValue); + } } diff --git a/src/main/java/com/cedarsoftware/util/convert/AtomicBooleanConversion.java b/src/main/java/com/cedarsoftware/util/convert/AtomicBooleanConversions.java similarity index 92% rename from src/main/java/com/cedarsoftware/util/convert/AtomicBooleanConversion.java rename to src/main/java/com/cedarsoftware/util/convert/AtomicBooleanConversions.java index b5730345..03034ae4 100644 --- a/src/main/java/com/cedarsoftware/util/convert/AtomicBooleanConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/AtomicBooleanConversions.java @@ -6,7 +6,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -public class AtomicBooleanConversion { +public class AtomicBooleanConversions { static Byte toByte(Object from, Converter converter, ConverterOptions options) { AtomicBoolean b = (AtomicBoolean) from; @@ -43,11 +43,17 @@ static boolean toBoolean(Object from, Converter converter, ConverterOptions opti return b.get(); } + static AtomicBoolean toAtomicBoolean(Object from, Converter converter, ConverterOptions options) { + AtomicBoolean b = (AtomicBoolean) from; + return new AtomicBoolean(b.get()); + } + static AtomicInteger toAtomicInteger(Object from, Converter converter, ConverterOptions options) { AtomicBoolean b = (AtomicBoolean) from; return b.get() ? new AtomicInteger(1) : new AtomicInteger (0); } + static AtomicLong toAtomicLong(Object from, Converter converter, ConverterOptions options) { AtomicBoolean b = (AtomicBoolean) from; return b.get() ? new AtomicLong(1) : new AtomicLong(0); diff --git a/src/main/java/com/cedarsoftware/util/convert/BooleanConversion.java b/src/main/java/com/cedarsoftware/util/convert/BooleanConversions.java similarity index 95% rename from src/main/java/com/cedarsoftware/util/convert/BooleanConversion.java rename to src/main/java/com/cedarsoftware/util/convert/BooleanConversions.java index 44b6b6fa..62a348af 100644 --- a/src/main/java/com/cedarsoftware/util/convert/BooleanConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/BooleanConversions.java @@ -24,7 +24,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -public class BooleanConversion { +public final class BooleanConversions { + + private BooleanConversions() { + } + static Byte toByte(Object from, Converter converter, ConverterOptions options) { Boolean b = (Boolean) from; return b ? CommonValues.BYTE_ONE : CommonValues.BYTE_ZERO; @@ -81,6 +85,6 @@ static Double toDouble(Object from, Converter converter, ConverterOptions option static char toCharacter(Object from, Converter converter, ConverterOptions options) { Boolean b = (Boolean) from; - return b ? CommonValues.CHARACTER_ONE : CommonValues.CHARACTER_ZERO; + return b ? options.trueChar() : options.falseChar(); } } diff --git a/src/main/java/com/cedarsoftware/util/convert/CalendarConversion.java b/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java similarity index 94% rename from src/main/java/com/cedarsoftware/util/convert/CalendarConversion.java rename to src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java index 7f72de01..bef02a73 100644 --- a/src/main/java/com/cedarsoftware/util/convert/CalendarConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java @@ -12,7 +12,7 @@ import java.util.GregorianCalendar; import java.util.concurrent.atomic.AtomicLong; -public class CalendarConversion { +public class CalendarConversions { static Date toDate(Object fromInstance) { return ((Calendar)fromInstance).getTime(); @@ -34,11 +34,15 @@ static ZonedDateTime toZonedDateTime(Object fromInstance, Converter converter, C return toZonedDateTime(fromInstance, options); } - static Long toLong(Object fromInstance, Converter converter, ConverterOptions options) { return toLong(fromInstance); } + static double toDouble(Object fromInstance, Converter converter, ConverterOptions options) { + return (double)toLong(fromInstance); + } + + static Date toDate(Object fromInstance, Converter converter, ConverterOptions options) { return toDate(fromInstance); } diff --git a/src/main/java/com/cedarsoftware/util/convert/CharacterConversion.java b/src/main/java/com/cedarsoftware/util/convert/CharacterConversions.java similarity index 90% rename from src/main/java/com/cedarsoftware/util/convert/CharacterConversion.java rename to src/main/java/com/cedarsoftware/util/convert/CharacterConversions.java index 25b5aecd..ec2d2a73 100644 --- a/src/main/java/com/cedarsoftware/util/convert/CharacterConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/CharacterConversions.java @@ -1,24 +1,19 @@ package com.cedarsoftware.util.convert; -import com.cedarsoftware.util.CaseInsensitiveMap; -import com.cedarsoftware.util.CollectionUtilities; - import java.math.BigDecimal; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -public class CharacterConversion { +public class CharacterConversions { - private CharacterConversion() { + private CharacterConversions() { } static boolean toBoolean(Object from) { char c = (char) from; - return (c == 1) || (c == 't') || (c == 'T') || (c == '1'); + return (c == 1) || (c == 't') || (c == 'T') || (c == '1') || (c == 'y') || (c == 'Y'); } diff --git a/src/main/java/com/cedarsoftware/util/convert/Converter.java b/src/main/java/com/cedarsoftware/util/convert/Converter.java index 5c4ea206..cd6aef13 100644 --- a/src/main/java/com/cedarsoftware/util/convert/Converter.java +++ b/src/main/java/com/cedarsoftware/util/convert/Converter.java @@ -108,393 +108,361 @@ private static void buildPrimitiveWrappers() { private static void buildFactoryConversions() { // Byte/byte Conversions supported - DEFAULT_FACTORY.put(pair(Void.class, byte.class), NumberConversion::toByteZero); - DEFAULT_FACTORY.put(pair(Void.class, Byte.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, byte.class), NumberConversions::toByteZero); + DEFAULT_FACTORY.put(pair(Void.class, Byte.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Byte.class, Byte.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Short.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Integer.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Long.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Float.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Double.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Boolean.class, Byte.class), BooleanConversion::toByte); - DEFAULT_FACTORY.put(pair(Character.class, Byte.class), CharacterConversion::toByte); - DEFAULT_FACTORY.put(pair(Calendar.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Byte.class), AtomicBooleanConversion::toByte); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(BigInteger.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Number.class, Byte.class), NumberConversion::toByte); - DEFAULT_FACTORY.put(pair(Map.class, Byte.class), MapConversion::toByte); - DEFAULT_FACTORY.put(pair(String.class, Byte.class), StringConversion::toByte); + DEFAULT_FACTORY.put(pair(Short.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Integer.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Long.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Float.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Double.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Boolean.class, Byte.class), BooleanConversions::toByte); + DEFAULT_FACTORY.put(pair(Character.class, Byte.class), CharacterConversions::toByte); + DEFAULT_FACTORY.put(pair(Calendar.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Byte.class), AtomicBooleanConversions::toByte); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(BigInteger.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Number.class, Byte.class), NumberConversions::toByte); + DEFAULT_FACTORY.put(pair(Map.class, Byte.class), MapConversions::toByte); + DEFAULT_FACTORY.put(pair(String.class, Byte.class), StringConversions::toByte); // Short/short conversions supported - DEFAULT_FACTORY.put(pair(Void.class, short.class), NumberConversion::toShortZero); - DEFAULT_FACTORY.put(pair(Void.class, Short.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Short.class), NumberConversion::toShort); + DEFAULT_FACTORY.put(pair(Void.class, short.class), NumberConversions::toShortZero); + DEFAULT_FACTORY.put(pair(Void.class, Short.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Short.class), NumberConversions::toShort); DEFAULT_FACTORY.put(pair(Short.class, Short.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Integer.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(Long.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(Float.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(Double.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(Boolean.class, Short.class), BooleanConversion::toShort); - DEFAULT_FACTORY.put(pair(Character.class, Short.class), CharacterConversion::toShort); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Short.class), AtomicBooleanConversion::toShort); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(BigInteger.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(LocalDate.class, Short.class), (fromInstance, converter, options) -> ((LocalDate) fromInstance).toEpochDay()); - DEFAULT_FACTORY.put(pair(Number.class, Short.class), NumberConversion::toShort); - DEFAULT_FACTORY.put(pair(Map.class, Short.class), (fromInstance, converter, options) -> converter.fromValueMap((Map) fromInstance, short.class, null, options)); - DEFAULT_FACTORY.put(pair(String.class, Short.class), StringConversion::toShort); + DEFAULT_FACTORY.put(pair(Integer.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(Long.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(Float.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(Double.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(Boolean.class, Short.class), BooleanConversions::toShort); + DEFAULT_FACTORY.put(pair(Character.class, Short.class), CharacterConversions::toShort); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Short.class), AtomicBooleanConversions::toShort); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(BigInteger.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(Number.class, Short.class), NumberConversions::toShort); + DEFAULT_FACTORY.put(pair(Map.class, Short.class), MapConversions::toShort); + DEFAULT_FACTORY.put(pair(String.class, Short.class), StringConversions::toShort); // Integer/int conversions supported - DEFAULT_FACTORY.put(pair(Void.class, int.class), NumberConversion::toIntZero); - DEFAULT_FACTORY.put(pair(Void.class, Integer.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(Short.class, Integer.class), NumberConversion::toInt); + DEFAULT_FACTORY.put(pair(Void.class, int.class), NumberConversions::toIntZero); + DEFAULT_FACTORY.put(pair(Void.class, Integer.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(Short.class, Integer.class), NumberConversions::toInt); DEFAULT_FACTORY.put(pair(Integer.class, Integer.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Long.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(Float.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(Double.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(Boolean.class, Integer.class), BooleanConversion::toInteger); - DEFAULT_FACTORY.put(pair(Character.class, Integer.class), CharacterConversion::toInt); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Integer.class), AtomicBooleanConversion::toInteger); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(BigInteger.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(LocalDate.class, Integer.class), (fromInstance, converter, options) -> (int) ((LocalDate) fromInstance).toEpochDay()); - DEFAULT_FACTORY.put(pair(Number.class, Integer.class), NumberConversion::toInt); - DEFAULT_FACTORY.put(pair(Map.class, Integer.class), MapConversion::toInt); - DEFAULT_FACTORY.put(pair(String.class, Integer.class), StringConversion::toInt); + DEFAULT_FACTORY.put(pair(Long.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(Float.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(Double.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(Boolean.class, Integer.class), BooleanConversions::toInteger); + DEFAULT_FACTORY.put(pair(Character.class, Integer.class), CharacterConversions::toInt); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Integer.class), AtomicBooleanConversions::toInteger); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(BigInteger.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(Number.class, Integer.class), NumberConversions::toInt); + DEFAULT_FACTORY.put(pair(Map.class, Integer.class), MapConversions::toInt); + DEFAULT_FACTORY.put(pair(String.class, Integer.class), StringConversions::toInt); // Long/long conversions supported - DEFAULT_FACTORY.put(pair(Void.class, long.class), NumberConversion::toLongZero); - DEFAULT_FACTORY.put(pair(Void.class, Long.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(Short.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(Integer.class, Long.class), NumberConversion::toLong); + DEFAULT_FACTORY.put(pair(Void.class, long.class), NumberConversions::toLongZero); + DEFAULT_FACTORY.put(pair(Void.class, Long.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(Short.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(Integer.class, Long.class), NumberConversions::toLong); DEFAULT_FACTORY.put(pair(Long.class, Long.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Float.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(Double.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(Boolean.class, Long.class), BooleanConversion::toLong); - DEFAULT_FACTORY.put(pair(Character.class, Long.class), CharacterConversion::toLong); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Long.class), AtomicBooleanConversion::toLong); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(BigInteger.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(Date.class, Long.class), DateConversion::toLong); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, Long.class), DateConversion::toLong); - DEFAULT_FACTORY.put(pair(Timestamp.class, Long.class), DateConversion::toLong); - DEFAULT_FACTORY.put(pair(Instant.class, Long.class), InstantConversion::toLong); - DEFAULT_FACTORY.put(pair(LocalDate.class, Long.class), LocalDateConversion::toLong); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, Long.class), LocalDateTimeConversion::toLong); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Long.class), ZonedDateTimeConversion::toLong); - DEFAULT_FACTORY.put(pair(Calendar.class, Long.class), CalendarConversion::toLong); - DEFAULT_FACTORY.put(pair(Number.class, Long.class), NumberConversion::toLong); - DEFAULT_FACTORY.put(pair(Map.class, Long.class), MapConversion::toLong); - DEFAULT_FACTORY.put(pair(String.class, Long.class), StringConversion::toLong); + DEFAULT_FACTORY.put(pair(Float.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(Double.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(Boolean.class, Long.class), BooleanConversions::toLong); + DEFAULT_FACTORY.put(pair(Character.class, Long.class), CharacterConversions::toLong); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Long.class), AtomicBooleanConversions::toLong); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(BigInteger.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(Date.class, Long.class), DateConversions::toLong); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, Long.class), DateConversions::toLong); + DEFAULT_FACTORY.put(pair(Timestamp.class, Long.class), DateConversions::toLong); + DEFAULT_FACTORY.put(pair(Instant.class, Long.class), InstantConversions::toLong); + DEFAULT_FACTORY.put(pair(LocalDate.class, Long.class), LocalDateConversions::toLong); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, Long.class), LocalDateTimeConversions::toLong); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Long.class), ZonedDateTimeConversions::toLong); + DEFAULT_FACTORY.put(pair(Calendar.class, Long.class), CalendarConversions::toLong); + DEFAULT_FACTORY.put(pair(Number.class, Long.class), NumberConversions::toLong); + DEFAULT_FACTORY.put(pair(Map.class, Long.class), MapConversions::toLong); + DEFAULT_FACTORY.put(pair(String.class, Long.class), StringConversions::toLong); // Float/float conversions supported - DEFAULT_FACTORY.put(pair(Void.class, float.class), NumberConversion::toFloatZero); - DEFAULT_FACTORY.put(pair(Void.class, Float.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(Short.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(Integer.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(Long.class, Float.class), NumberConversion::toFloat); + DEFAULT_FACTORY.put(pair(Void.class, float.class), NumberConversions::toFloatZero); + DEFAULT_FACTORY.put(pair(Void.class, Float.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(Short.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(Integer.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(Long.class, Float.class), NumberConversions::toFloat); DEFAULT_FACTORY.put(pair(Float.class, Float.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Double.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(Boolean.class, Float.class), BooleanConversion::toFloat); - DEFAULT_FACTORY.put(pair(Character.class, Float.class), CharacterConversion::toFloat); - DEFAULT_FACTORY.put(pair(Instant.class, Float.class), InstantConversion::toFloat); - DEFAULT_FACTORY.put(pair(LocalDate.class, Float.class), LocalDateConversion::toLong); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Float.class), AtomicBooleanConversion::toFloat); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(BigInteger.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(Number.class, Float.class), NumberConversion::toFloat); - DEFAULT_FACTORY.put(pair(Map.class, Float.class), MapConversion::toFloat); - DEFAULT_FACTORY.put(pair(String.class, Float.class), StringConversion::toFloat); + DEFAULT_FACTORY.put(pair(Double.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(Boolean.class, Float.class), BooleanConversions::toFloat); + DEFAULT_FACTORY.put(pair(Character.class, Float.class), CharacterConversions::toFloat); + DEFAULT_FACTORY.put(pair(Instant.class, Float.class), InstantConversions::toFloat); + DEFAULT_FACTORY.put(pair(LocalDate.class, Float.class), LocalDateConversions::toLong); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Float.class), AtomicBooleanConversions::toFloat); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(BigInteger.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(Number.class, Float.class), NumberConversions::toFloat); + DEFAULT_FACTORY.put(pair(Map.class, Float.class), MapConversions::toFloat); + DEFAULT_FACTORY.put(pair(String.class, Float.class), StringConversions::toFloat); // Double/double conversions supported - DEFAULT_FACTORY.put(pair(Void.class, double.class), NumberConversion::toDoubleZero); - DEFAULT_FACTORY.put(pair(Void.class, Double.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(Short.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(Integer.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(Long.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(Float.class, Double.class), NumberConversion::toDouble); + DEFAULT_FACTORY.put(pair(Void.class, double.class), NumberConversions::toDoubleZero); + DEFAULT_FACTORY.put(pair(Void.class, Double.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(Short.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(Integer.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(Long.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(Float.class, Double.class), NumberConversions::toDouble); DEFAULT_FACTORY.put(pair(Double.class, Double.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Boolean.class, Double.class), BooleanConversion::toDouble); - DEFAULT_FACTORY.put(pair(Character.class, Double.class), CharacterConversion::toDouble); - DEFAULT_FACTORY.put(pair(Instant.class, Double.class), InstantConversion::toLong); - DEFAULT_FACTORY.put(pair(LocalDate.class, Double.class), LocalDateConversion::toLong); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, Double.class), LocalDateTimeConversion::toLong); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Double.class), ZonedDateTimeConversion::toLong); - DEFAULT_FACTORY.put(pair(Date.class, Double.class), DateConversion::toLong); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, Double.class), DateConversion::toLong); - DEFAULT_FACTORY.put(pair(Timestamp.class, Double.class), DateConversion::toLong); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Double.class), AtomicBooleanConversion::toDouble); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(BigInteger.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(Calendar.class, Double.class), (fromInstance, converter, options) -> (double) ((Calendar) fromInstance).getTime().getTime()); - DEFAULT_FACTORY.put(pair(Number.class, Double.class), NumberConversion::toDouble); - DEFAULT_FACTORY.put(pair(Map.class, Double.class), MapConversion::toDouble); - DEFAULT_FACTORY.put(pair(String.class, Double.class), StringConversion::toDouble); + DEFAULT_FACTORY.put(pair(Boolean.class, Double.class), BooleanConversions::toDouble); + DEFAULT_FACTORY.put(pair(Character.class, Double.class), CharacterConversions::toDouble); + DEFAULT_FACTORY.put(pair(Instant.class, Double.class), InstantConversions::toLong); + DEFAULT_FACTORY.put(pair(LocalDate.class, Double.class), LocalDateConversions::toLong); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, Double.class), LocalDateTimeConversions::toLong); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Double.class), ZonedDateTimeConversions::toLong); + DEFAULT_FACTORY.put(pair(Date.class, Double.class), DateConversions::toLong); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, Double.class), DateConversions::toLong); + DEFAULT_FACTORY.put(pair(Timestamp.class, Double.class), DateConversions::toLong); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Double.class), AtomicBooleanConversions::toDouble); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(BigInteger.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(Calendar.class, Double.class), CalendarConversions::toDouble); + DEFAULT_FACTORY.put(pair(Number.class, Double.class), NumberConversions::toDouble); + DEFAULT_FACTORY.put(pair(Map.class, Double.class), MapConversions::toDouble); + DEFAULT_FACTORY.put(pair(String.class, Double.class), StringConversions::toDouble); // Boolean/boolean conversions supported - DEFAULT_FACTORY.put(pair(Void.class, boolean.class), VoidConversion::toBoolean); - DEFAULT_FACTORY.put(pair(Void.class, Boolean.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(Short.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(Integer.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(Long.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(Float.class, Boolean.class), NumberConversion::isFloatTypeNotZero); - DEFAULT_FACTORY.put(pair(Double.class, Boolean.class), NumberConversion::isFloatTypeNotZero); + DEFAULT_FACTORY.put(pair(Void.class, boolean.class), VoidConversions::toBoolean); + DEFAULT_FACTORY.put(pair(Void.class, Boolean.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(Short.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(Integer.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(Long.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(Float.class, Boolean.class), NumberConversions::isFloatTypeNotZero); + DEFAULT_FACTORY.put(pair(Double.class, Boolean.class), NumberConversions::isFloatTypeNotZero); DEFAULT_FACTORY.put(pair(Boolean.class, Boolean.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Character.class, Boolean.class), CharacterConversion::toBoolean); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Boolean.class), AtomicBooleanConversion::toBoolean); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(BigInteger.class, Boolean.class), NumberConversion::isBigIntegerNotZero); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Boolean.class), NumberConversion::isBigDecimalNotZero); - DEFAULT_FACTORY.put(pair(Number.class, Boolean.class), NumberConversion::isIntTypeNotZero); - DEFAULT_FACTORY.put(pair(Map.class, Boolean.class), MapConversion::toBoolean); - DEFAULT_FACTORY.put(pair(String.class, Boolean.class), StringConversion::toBoolean); + DEFAULT_FACTORY.put(pair(Character.class, Boolean.class), CharacterConversions::toBoolean); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Boolean.class), AtomicBooleanConversions::toBoolean); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(BigInteger.class, Boolean.class), NumberConversions::isBigIntegerNotZero); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Boolean.class), NumberConversions::isBigDecimalNotZero); + DEFAULT_FACTORY.put(pair(Number.class, Boolean.class), NumberConversions::isIntTypeNotZero); + DEFAULT_FACTORY.put(pair(Map.class, Boolean.class), MapConversions::toBoolean); + DEFAULT_FACTORY.put(pair(String.class, Boolean.class), StringConversions::toBoolean); // Character/chat conversions supported - DEFAULT_FACTORY.put(pair(Void.class, char.class), VoidConversion::toChar); - DEFAULT_FACTORY.put(pair(Void.class, Character.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Short.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Integer.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Long.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Float.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Double.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Boolean.class, Character.class), BooleanConversion::toCharacter); + DEFAULT_FACTORY.put(pair(Void.class, char.class), VoidConversions::toChar); + DEFAULT_FACTORY.put(pair(Void.class, Character.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Short.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Integer.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Long.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Float.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Double.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Boolean.class, Character.class), BooleanConversions::toCharacter); DEFAULT_FACTORY.put(pair(Character.class, Character.class), Converter::identity); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Character.class), AtomicBooleanConversion::toCharacter); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(BigInteger.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Character.class), NumberConversion::toCharacter); - DEFAULT_FACTORY.put(pair(Number.class, Character.class), NumberConversion::toCharacter); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Character.class), AtomicBooleanConversions::toCharacter); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(BigInteger.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Character.class), NumberConversions::toCharacter); + DEFAULT_FACTORY.put(pair(Number.class, Character.class), NumberConversions::toCharacter); DEFAULT_FACTORY.put(pair(Map.class, Character.class), (fromInstance, converter, options) -> converter.fromValueMap((Map) fromInstance, char.class, null, options)); - DEFAULT_FACTORY.put(pair(String.class, Character.class), StringConversion::toCharacter); + DEFAULT_FACTORY.put(pair(String.class, Character.class), StringConversions::toCharacter); // BigInteger versions supported - DEFAULT_FACTORY.put(pair(Void.class, BigInteger.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, BigInteger.class), NumberConversion::integerTypeToBigInteger); - DEFAULT_FACTORY.put(pair(Short.class, BigInteger.class), NumberConversion::integerTypeToBigInteger); - DEFAULT_FACTORY.put(pair(Integer.class, BigInteger.class), NumberConversion::integerTypeToBigInteger); - DEFAULT_FACTORY.put(pair(Long.class, BigInteger.class), NumberConversion::integerTypeToBigInteger); - DEFAULT_FACTORY.put(pair(Float.class, BigInteger.class), (fromInstance, converter, options) -> new BigInteger(String.format("%.0f", (float) fromInstance))); - DEFAULT_FACTORY.put(pair(Double.class, BigInteger.class), (fromInstance, converter, options) -> new BigInteger(String.format("%.0f", (double) fromInstance))); - DEFAULT_FACTORY.put(pair(Boolean.class, BigInteger.class), BooleanConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(Character.class, BigInteger.class), CharacterConversion::toBigInteger); + DEFAULT_FACTORY.put(pair(Void.class, BigInteger.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, BigInteger.class), NumberConversions::integerTypeToBigInteger); + DEFAULT_FACTORY.put(pair(Short.class, BigInteger.class), NumberConversions::integerTypeToBigInteger); + DEFAULT_FACTORY.put(pair(Integer.class, BigInteger.class), NumberConversions::integerTypeToBigInteger); + DEFAULT_FACTORY.put(pair(Long.class, BigInteger.class), NumberConversions::integerTypeToBigInteger); + DEFAULT_FACTORY.put(pair(Float.class, BigInteger.class), NumberConversions::floatingPointToBigInteger); + DEFAULT_FACTORY.put(pair(Double.class, BigInteger.class), NumberConversions::floatingPointToBigInteger); + DEFAULT_FACTORY.put(pair(Boolean.class, BigInteger.class), BooleanConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(Character.class, BigInteger.class), CharacterConversions::toBigInteger); DEFAULT_FACTORY.put(pair(BigInteger.class, BigInteger.class), Converter::identity); - DEFAULT_FACTORY.put(pair(BigDecimal.class, BigInteger.class), NumberConversion::bigDecimalToBigInteger); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, BigInteger.class), AtomicBooleanConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, BigInteger.class), NumberConversion::integerTypeToBigInteger); - DEFAULT_FACTORY.put(pair(AtomicLong.class, BigInteger.class), NumberConversion::integerTypeToBigInteger); - DEFAULT_FACTORY.put(pair(Date.class, BigInteger.class), DateConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, BigInteger.class), DateConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(Timestamp.class, BigInteger.class), DateConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(Instant.class, BigInteger.class), InstantConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(LocalDate.class, BigInteger.class), LocalDateConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, BigInteger.class), LocalDateTimeConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, BigInteger.class), ZonedDateTimeConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(UUID.class, BigInteger.class), (fromInstance, converter, options) -> { - UUID uuid = (UUID) fromInstance; - BigInteger mostSignificant = BigInteger.valueOf(uuid.getMostSignificantBits()); - BigInteger leastSignificant = BigInteger.valueOf(uuid.getLeastSignificantBits()); - // Shift the most significant bits to the left and add the least significant bits - return mostSignificant.shiftLeft(64).add(leastSignificant); - }); - DEFAULT_FACTORY.put(pair(Calendar.class, BigInteger.class), CalendarConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(Number.class, BigInteger.class), (fromInstance, converter, options) -> new BigInteger(fromInstance.toString())); - DEFAULT_FACTORY.put(pair(Map.class, BigInteger.class), MapConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(String.class, BigInteger.class), StringConversion::toBigInteger); - - + DEFAULT_FACTORY.put(pair(BigDecimal.class, BigInteger.class), NumberConversions::bigDecimalToBigInteger); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, BigInteger.class), AtomicBooleanConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, BigInteger.class), NumberConversions::integerTypeToBigInteger); + DEFAULT_FACTORY.put(pair(AtomicLong.class, BigInteger.class), NumberConversions::integerTypeToBigInteger); + DEFAULT_FACTORY.put(pair(Date.class, BigInteger.class), DateConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, BigInteger.class), DateConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(Timestamp.class, BigInteger.class), DateConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(Instant.class, BigInteger.class), InstantConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(LocalDate.class, BigInteger.class), LocalDateConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, BigInteger.class), LocalDateTimeConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, BigInteger.class), ZonedDateTimeConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(UUID.class, BigInteger.class), UUIDConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(Calendar.class, BigInteger.class), CalendarConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(Number.class, BigInteger.class), NumberConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(Map.class, BigInteger.class), MapConversions::toBigInteger); + DEFAULT_FACTORY.put(pair(String.class, BigInteger.class), StringConversions::toBigInteger); // BigDecimal conversions supported - DEFAULT_FACTORY.put(pair(Void.class, BigDecimal.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, BigDecimal.class), NumberConversion::integerTypeToBigDecimal); - DEFAULT_FACTORY.put(pair(Short.class, BigDecimal.class), NumberConversion::integerTypeToBigDecimal); - DEFAULT_FACTORY.put(pair(Integer.class, BigDecimal.class), NumberConversion::integerTypeToBigDecimal); - DEFAULT_FACTORY.put(pair(Long.class, BigDecimal.class), NumberConversion::integerTypeToBigDecimal); - DEFAULT_FACTORY.put(pair(Float.class, BigDecimal.class), NumberConversion::floatingPointToBigDecimal); - DEFAULT_FACTORY.put(pair(Double.class, BigDecimal.class), NumberConversion::floatingPointToBigDecimal); - DEFAULT_FACTORY.put(pair(Boolean.class, BigDecimal.class), BooleanConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(Character.class, BigDecimal.class), CharacterConversion::toBigDecimal); + DEFAULT_FACTORY.put(pair(Void.class, BigDecimal.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, BigDecimal.class), NumberConversions::integerTypeToBigDecimal); + DEFAULT_FACTORY.put(pair(Short.class, BigDecimal.class), NumberConversions::integerTypeToBigDecimal); + DEFAULT_FACTORY.put(pair(Integer.class, BigDecimal.class), NumberConversions::integerTypeToBigDecimal); + DEFAULT_FACTORY.put(pair(Long.class, BigDecimal.class), NumberConversions::integerTypeToBigDecimal); + DEFAULT_FACTORY.put(pair(Float.class, BigDecimal.class), NumberConversions::floatingPointToBigDecimal); + DEFAULT_FACTORY.put(pair(Double.class, BigDecimal.class), NumberConversions::floatingPointToBigDecimal); + DEFAULT_FACTORY.put(pair(Boolean.class, BigDecimal.class), BooleanConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(Character.class, BigDecimal.class), CharacterConversions::toBigDecimal); DEFAULT_FACTORY.put(pair(BigDecimal.class, BigDecimal.class), Converter::identity); - DEFAULT_FACTORY.put(pair(BigInteger.class, BigDecimal.class), NumberConversion::bigIntegerToBigDecimal); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, BigDecimal.class), AtomicBooleanConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, BigDecimal.class), NumberConversion::integerTypeToBigDecimal); - DEFAULT_FACTORY.put(pair(AtomicLong.class, BigDecimal.class), NumberConversion::integerTypeToBigDecimal); - DEFAULT_FACTORY.put(pair(Date.class, BigDecimal.class), DateConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, BigDecimal.class), DateConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(Timestamp.class, BigDecimal.class), DateConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(Instant.class, BigDecimal.class), InstantConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(LocalDate.class, BigDecimal.class), LocalDateConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, BigDecimal.class), LocalDateTimeConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, BigDecimal.class), ZonedDateTimeConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(UUID.class, BigDecimal.class), (fromInstance, converter, options) -> { - UUID uuid = (UUID) fromInstance; - BigInteger mostSignificant = BigInteger.valueOf(uuid.getMostSignificantBits()); - BigInteger leastSignificant = BigInteger.valueOf(uuid.getLeastSignificantBits()); - // Shift the most significant bits to the left and add the least significant bits - return new BigDecimal(mostSignificant.shiftLeft(64).add(leastSignificant)); - }); - DEFAULT_FACTORY.put(pair(Calendar.class, BigDecimal.class), CalendarConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(Number.class, BigDecimal.class), (fromInstance, converter, options) -> new BigDecimal(fromInstance.toString())); - DEFAULT_FACTORY.put(pair(Map.class, BigDecimal.class), MapConversion::toBigDecimal); - DEFAULT_FACTORY.put(pair(String.class, BigDecimal.class), StringConversion::toBigDecimal); + DEFAULT_FACTORY.put(pair(BigInteger.class, BigDecimal.class), NumberConversions::bigIntegerToBigDecimal); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, BigDecimal.class), AtomicBooleanConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, BigDecimal.class), NumberConversions::integerTypeToBigDecimal); + DEFAULT_FACTORY.put(pair(AtomicLong.class, BigDecimal.class), NumberConversions::integerTypeToBigDecimal); + DEFAULT_FACTORY.put(pair(Date.class, BigDecimal.class), DateConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, BigDecimal.class), DateConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(Timestamp.class, BigDecimal.class), DateConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(Instant.class, BigDecimal.class), InstantConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(LocalDate.class, BigDecimal.class), LocalDateConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, BigDecimal.class), LocalDateTimeConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, BigDecimal.class), ZonedDateTimeConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(UUID.class, BigDecimal.class), UUIDConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(Calendar.class, BigDecimal.class), CalendarConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(Number.class, BigDecimal.class), NumberConversions::bigDecimalToBigDecimal); + DEFAULT_FACTORY.put(pair(Map.class, BigDecimal.class), MapConversions::toBigDecimal); + DEFAULT_FACTORY.put(pair(String.class, BigDecimal.class), StringConversions::toBigDecimal); // AtomicBoolean conversions supported - DEFAULT_FACTORY.put(pair(Void.class, AtomicBoolean.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Short.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Integer.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Long.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Float.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Double.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Boolean.class, AtomicBoolean.class), BooleanConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Character.class, AtomicBoolean.class), CharacterConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(BigInteger.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(BigDecimal.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, AtomicBoolean.class), (fromInstance, converter, options) -> new AtomicBoolean(((AtomicBoolean) fromInstance).get())); // mutable, so dupe - DEFAULT_FACTORY.put(pair(AtomicInteger.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(AtomicLong.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Number.class, AtomicBoolean.class), NumberConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(Map.class, AtomicBoolean.class), MapConversion::toAtomicBoolean); - DEFAULT_FACTORY.put(pair(String.class, AtomicBoolean.class), StringConversion::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Void.class, AtomicBoolean.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Short.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Integer.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Long.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Float.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Double.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Boolean.class, AtomicBoolean.class), BooleanConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Character.class, AtomicBoolean.class), CharacterConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(BigInteger.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(BigDecimal.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, AtomicBoolean.class), AtomicBooleanConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(AtomicLong.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Number.class, AtomicBoolean.class), NumberConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(Map.class, AtomicBoolean.class), MapConversions::toAtomicBoolean); + DEFAULT_FACTORY.put(pair(String.class, AtomicBoolean.class), StringConversions::toAtomicBoolean); // AtomicInteger conversions supported - DEFAULT_FACTORY.put(pair(Void.class, AtomicInteger.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Short.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Integer.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Long.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Float.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Double.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Boolean.class, AtomicInteger.class), BooleanConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Character.class, AtomicInteger.class), CharacterConversion::toBigInteger); - DEFAULT_FACTORY.put(pair(BigInteger.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(BigDecimal.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(AtomicInteger.class, AtomicInteger.class), NumberConversion::toAtomicInteger); // mutable, so dupe - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, AtomicInteger.class), AtomicBooleanConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(AtomicLong.class, AtomicInteger.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(LocalDate.class, AtomicInteger.class), LocalDateConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Number.class, AtomicBoolean.class), NumberConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(Map.class, AtomicInteger.class), MapConversion::toAtomicInteger); - DEFAULT_FACTORY.put(pair(String.class, AtomicInteger.class), StringConversion::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Void.class, AtomicInteger.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Short.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Integer.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Long.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Float.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Double.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Boolean.class, AtomicInteger.class), BooleanConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Character.class, AtomicInteger.class), CharacterConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(BigInteger.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(BigDecimal.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, AtomicInteger.class), AtomicBooleanConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(AtomicLong.class, AtomicInteger.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(LocalDate.class, AtomicInteger.class), LocalDateConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Number.class, AtomicBoolean.class), NumberConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(Map.class, AtomicInteger.class), MapConversions::toAtomicInteger); + DEFAULT_FACTORY.put(pair(String.class, AtomicInteger.class), StringConversions::toAtomicInteger); // AtomicLong conversions supported - DEFAULT_FACTORY.put(pair(Void.class, AtomicLong.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Byte.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Short.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Integer.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Long.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Float.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Double.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Boolean.class, AtomicLong.class), BooleanConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Character.class, AtomicLong.class), (fromInstance, converter, options) -> new AtomicLong(((char) fromInstance))); - DEFAULT_FACTORY.put(pair(BigInteger.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(BigDecimal.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(AtomicBoolean.class, AtomicLong.class), AtomicBooleanConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(AtomicLong.class, AtomicLong.class), Converter::identity); // mutable, so dupe - DEFAULT_FACTORY.put(pair(AtomicInteger.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Date.class, AtomicLong.class), DateConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, AtomicLong.class), DateConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Timestamp.class, AtomicLong.class), DateConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Instant.class, AtomicLong.class), InstantConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(LocalDate.class, AtomicLong.class), LocalDateConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, AtomicLong.class), LocalDateTimeConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, AtomicLong.class), ZonedDateTimeConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Calendar.class, AtomicLong.class), CalendarConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Number.class, AtomicLong.class), NumberConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(Map.class, AtomicLong.class), MapConversion::toAtomicLong); - DEFAULT_FACTORY.put(pair(String.class, AtomicLong.class), StringConversion::toAtomicLong); + DEFAULT_FACTORY.put(pair(Void.class, AtomicLong.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Byte.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Short.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Integer.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Long.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Float.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Double.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Boolean.class, AtomicLong.class), BooleanConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Character.class, AtomicLong.class), CharacterConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(BigInteger.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(BigDecimal.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(AtomicBoolean.class, AtomicLong.class), AtomicBooleanConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(AtomicLong.class, AtomicLong.class), Converter::identity); + DEFAULT_FACTORY.put(pair(AtomicInteger.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Date.class, AtomicLong.class), DateConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, AtomicLong.class), DateConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Timestamp.class, AtomicLong.class), DateConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Instant.class, AtomicLong.class), InstantConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(LocalDate.class, AtomicLong.class), LocalDateConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, AtomicLong.class), LocalDateTimeConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, AtomicLong.class), ZonedDateTimeConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Calendar.class, AtomicLong.class), CalendarConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Number.class, AtomicLong.class), NumberConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(Map.class, AtomicLong.class), MapConversions::toAtomicLong); + DEFAULT_FACTORY.put(pair(String.class, AtomicLong.class), StringConversions::toAtomicLong); // Date conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Date.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, Date.class), NumberConversion::toDate); - DEFAULT_FACTORY.put(pair(Double.class, Date.class), NumberConversion::toDate); - DEFAULT_FACTORY.put(pair(BigInteger.class, Date.class), NumberConversion::toDate); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Date.class), NumberConversion::toDate); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Date.class), NumberConversion::toDate); - DEFAULT_FACTORY.put(pair(Date.class, Date.class), (fromInstance, converter, options) -> new Date(((Date) fromInstance).getTime())); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, Date.class), (fromInstance, converter, options) -> new Date(((Date) fromInstance).getTime())); - DEFAULT_FACTORY.put(pair(Timestamp.class, Date.class), (fromInstance, converter, options) -> new Date(((Date) fromInstance).getTime())); - DEFAULT_FACTORY.put(pair(Instant.class, Date.class), InstantConversion::toDate); - DEFAULT_FACTORY.put(pair(LocalDate.class, Date.class), LocalDateConversion::toDate); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, Date.class), LocalDateTimeConversion::toDate); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Date.class), ZonedDateTimeConversion::toDate); - DEFAULT_FACTORY.put(pair(Calendar.class, Date.class), CalendarConversion::toDate); - DEFAULT_FACTORY.put(pair(Number.class, Date.class), NumberConversion::toDate); - DEFAULT_FACTORY.put(pair(Map.class, Date.class), (fromInstance, converter, options) -> { - Map map = (Map) fromInstance; - if (map.containsKey("time")) { - return converter.convert(map.get("time"), Date.class, options); - } else { - return converter.fromValueMap(map, Date.class, CollectionUtilities.setOf("time"), options); - } - }); - DEFAULT_FACTORY.put(pair(String.class, Date.class), (fromInstance, converter, options) -> DateUtilities.parseDate(((String) fromInstance).trim())); + DEFAULT_FACTORY.put(pair(Void.class, Date.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, Date.class), NumberConversions::toDate); + DEFAULT_FACTORY.put(pair(Double.class, Date.class), NumberConversions::toDate); + DEFAULT_FACTORY.put(pair(BigInteger.class, Date.class), NumberConversions::toDate); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Date.class), NumberConversions::toDate); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Date.class), NumberConversions::toDate); + DEFAULT_FACTORY.put(pair(Date.class, Date.class), DateConversions::toDate); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, Date.class), DateConversions::toDate); + DEFAULT_FACTORY.put(pair(Timestamp.class, Date.class), DateConversions::toDate); + DEFAULT_FACTORY.put(pair(Instant.class, Date.class), InstantConversions::toDate); + DEFAULT_FACTORY.put(pair(LocalDate.class, Date.class), LocalDateConversions::toDate); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, Date.class), LocalDateTimeConversions::toDate); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Date.class), ZonedDateTimeConversions::toDate); + DEFAULT_FACTORY.put(pair(Calendar.class, Date.class), CalendarConversions::toDate); + DEFAULT_FACTORY.put(pair(Number.class, Date.class), NumberConversions::toDate); + DEFAULT_FACTORY.put(pair(Map.class, Date.class), MapConversions::toDate); + DEFAULT_FACTORY.put(pair(String.class, Date.class), StringConversions::toDate); // java.sql.Date conversion supported - DEFAULT_FACTORY.put(pair(Void.class, java.sql.Date.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, java.sql.Date.class), NumberConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(Double.class, java.sql.Date.class), NumberConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(BigInteger.class, java.sql.Date.class), NumberConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(BigDecimal.class, java.sql.Date.class), NumberConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(AtomicLong.class, java.sql.Date.class), NumberConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, java.sql.Date.class), DateConversion::toSqlDate); // mutable type (creates new) - DEFAULT_FACTORY.put(pair(Date.class, java.sql.Date.class), DateConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(Timestamp.class, java.sql.Date.class), DateConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(LocalDate.class, java.sql.Date.class), LocalDateConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, java.sql.Date.class), LocalDateTimeConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, java.sql.Date.class), ZonedDateTimeConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(Calendar.class, java.sql.Date.class), CalendarConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(Number.class, java.sql.Date.class), NumberConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(Map.class, java.sql.Date.class), MapConversion::toSqlDate); - DEFAULT_FACTORY.put(pair(String.class, java.sql.Date.class), StringConversion::toSqlDate); + DEFAULT_FACTORY.put(pair(Void.class, java.sql.Date.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, java.sql.Date.class), NumberConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Double.class, java.sql.Date.class), NumberConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(BigInteger.class, java.sql.Date.class), NumberConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(BigDecimal.class, java.sql.Date.class), NumberConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(AtomicLong.class, java.sql.Date.class), NumberConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, java.sql.Date.class), DateConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Date.class, java.sql.Date.class), DateConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Timestamp.class, java.sql.Date.class), DateConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Instant.class, java.sql.Date.class), InstantConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(LocalDate.class, java.sql.Date.class), LocalDateConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, java.sql.Date.class), LocalDateTimeConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, java.sql.Date.class), ZonedDateTimeConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Calendar.class, java.sql.Date.class), CalendarConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Number.class, java.sql.Date.class), NumberConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(Map.class, java.sql.Date.class), MapConversions::toSqlDate); + DEFAULT_FACTORY.put(pair(String.class, java.sql.Date.class), StringConversions::toSqlDate); // Timestamp conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Timestamp.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, Timestamp.class), NumberConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(Double.class, Timestamp.class), NumberConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(BigInteger.class, Timestamp.class), NumberConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Timestamp.class), NumberConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Timestamp.class), NumberConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(Timestamp.class, Timestamp.class), DateConversion::toTimestamp); //mutable type (creates new) - DEFAULT_FACTORY.put(pair(java.sql.Date.class, Timestamp.class), DateConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(Date.class, Timestamp.class), DateConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(LocalDate.class, Timestamp.class), LocalDateConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, Timestamp.class), LocalDateTimeConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Timestamp.class), ZonedDateTimeConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(Calendar.class, Timestamp.class), CalendarConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(Number.class, Timestamp.class), NumberConversion::toTimestamp); - DEFAULT_FACTORY.put(pair(Map.class, Timestamp.class), (fromInstance, converter, options) -> { - Map map = (Map) fromInstance; - if (map.containsKey("time")) { - long time = converter.convert(map.get("time"), long.class, options); - int ns = converter.convert(map.get("nanos"), int.class, options); - Timestamp timeStamp = new Timestamp(time); - timeStamp.setNanos(ns); - return timeStamp; - } else { - return converter.fromValueMap(map, Timestamp.class, CollectionUtilities.setOf("time", "nanos"), options); - } - }); + DEFAULT_FACTORY.put(pair(Void.class, Timestamp.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, Timestamp.class), NumberConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Double.class, Timestamp.class), NumberConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(BigInteger.class, Timestamp.class), NumberConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Timestamp.class), NumberConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Timestamp.class), NumberConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Timestamp.class, Timestamp.class), DateConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, Timestamp.class), DateConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Date.class, Timestamp.class), DateConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Instant.class,Timestamp.class), InstantConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(LocalDate.class, Timestamp.class), LocalDateConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, Timestamp.class), LocalDateTimeConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Timestamp.class), ZonedDateTimeConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Calendar.class, Timestamp.class), CalendarConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Number.class, Timestamp.class), NumberConversions::toTimestamp); + DEFAULT_FACTORY.put(pair(Map.class, Timestamp.class), MapConversions::toTimestamp); DEFAULT_FACTORY.put(pair(String.class, Timestamp.class), (fromInstance, converter, options) -> { String str = ((String) fromInstance).trim(); Date date = DateUtilities.parseDate(str); @@ -505,20 +473,21 @@ private static void buildFactoryConversions() { }); // Calendar conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Calendar.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, Calendar.class), NumberConversion::toCalendar); - DEFAULT_FACTORY.put(pair(Double.class, Calendar.class), NumberConversion::toCalendar); - DEFAULT_FACTORY.put(pair(BigInteger.class, Calendar.class), NumberConversion::toCalendar); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Calendar.class), NumberConversion::toCalendar); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Calendar.class), NumberConversion::toCalendar); - DEFAULT_FACTORY.put(pair(Date.class, Calendar.class), DateConversion::toCalendar); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, Calendar.class), DateConversion::toCalendar); - DEFAULT_FACTORY.put(pair(Timestamp.class, Calendar.class), DateConversion::toCalendar); - DEFAULT_FACTORY.put(pair(LocalDate.class, Calendar.class), LocalDateConversion::toCalendar); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, Calendar.class), LocalDateTimeConversion::toCalendar); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Calendar.class), ZonedDateTimeConversion::toCalendar); - DEFAULT_FACTORY.put(pair(Calendar.class, Calendar.class), CalendarConversion::clone); - DEFAULT_FACTORY.put(pair(Number.class, Calendar.class), NumberConversion::toCalendar); + DEFAULT_FACTORY.put(pair(Void.class, Calendar.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, Calendar.class), NumberConversions::toCalendar); + DEFAULT_FACTORY.put(pair(Double.class, Calendar.class), NumberConversions::toCalendar); + DEFAULT_FACTORY.put(pair(BigInteger.class, Calendar.class), NumberConversions::toCalendar); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Calendar.class), NumberConversions::toCalendar); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Calendar.class), NumberConversions::toCalendar); + DEFAULT_FACTORY.put(pair(Date.class, Calendar.class), DateConversions::toCalendar); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, Calendar.class), DateConversions::toCalendar); + DEFAULT_FACTORY.put(pair(Timestamp.class, Calendar.class), DateConversions::toCalendar); + DEFAULT_FACTORY.put(pair(Instant.class, Calendar.class), InstantConversions::toCalendar); + DEFAULT_FACTORY.put(pair(LocalDate.class, Calendar.class), LocalDateConversions::toCalendar); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, Calendar.class), LocalDateTimeConversions::toCalendar); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Calendar.class), ZonedDateTimeConversions::toCalendar); + DEFAULT_FACTORY.put(pair(Calendar.class, Calendar.class), CalendarConversions::clone); + DEFAULT_FACTORY.put(pair(Number.class, Calendar.class), NumberConversions::toCalendar); DEFAULT_FACTORY.put(pair(Map.class, Calendar.class), (fromInstance, converter, options) -> { Map map = (Map) fromInstance; if (map.containsKey("time")) { @@ -545,11 +514,12 @@ private static void buildFactoryConversions() { if (date == null) { return null; } - return CalendarConversion.create(date.getTime(), options); + return CalendarConversions.create(date.getTime(), options); }); + // LocalTime conversions supported - DEFAULT_FACTORY.put(pair(Void.class, LocalTime.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, LocalTime.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(LocalTime.class, LocalTime.class), Converter::identity); DEFAULT_FACTORY.put(pair(String.class, LocalTime.class), (fromInstance, converter, options) -> { String strTime = (String) fromInstance; @@ -573,21 +543,21 @@ private static void buildFactoryConversions() { }); // LocalDate conversions supported - DEFAULT_FACTORY.put(pair(Void.class, LocalDate.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, LocalDate.class), NumberConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(Double.class, LocalDate.class), NumberConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(BigInteger.class, LocalDate.class), NumberConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(BigDecimal.class, LocalDate.class), NumberConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(AtomicLong.class, LocalDate.class), NumberConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, LocalDate.class), DateConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(Timestamp.class, LocalDate.class), DateConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(Date.class, LocalDate.class), DateConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(Instant.class, LocalDate.class), InstantConversion::toLocalDate); + DEFAULT_FACTORY.put(pair(Void.class, LocalDate.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, LocalDate.class), NumberConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(Double.class, LocalDate.class), NumberConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(BigInteger.class, LocalDate.class), NumberConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(BigDecimal.class, LocalDate.class), NumberConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(AtomicLong.class, LocalDate.class), NumberConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, LocalDate.class), DateConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(Timestamp.class, LocalDate.class), DateConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(Date.class, LocalDate.class), DateConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(Instant.class, LocalDate.class), InstantConversions::toLocalDate); DEFAULT_FACTORY.put(pair(LocalDate.class, LocalDate.class), Converter::identity); DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalDate.class), (fromInstance, converter, options) -> ((LocalDateTime) fromInstance).toLocalDate()); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalDate.class), ZonedDateTimeConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(Calendar.class, LocalDate.class), CalendarConversion::toLocalDate); - DEFAULT_FACTORY.put(pair(Number.class, LocalDate.class), NumberConversion::toLocalDate); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalDate.class), ZonedDateTimeConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(Calendar.class, LocalDate.class), CalendarConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(Number.class, LocalDate.class), NumberConversions::toLocalDate); DEFAULT_FACTORY.put(pair(Map.class, LocalDate.class), (fromInstance, converter, options) -> { Map map = (Map) fromInstance; if (map.containsKey("month") && map.containsKey("day") && map.containsKey("year")) { @@ -609,21 +579,21 @@ private static void buildFactoryConversions() { }); // LocalDateTime conversions supported - DEFAULT_FACTORY.put(pair(Void.class, LocalDateTime.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, LocalDateTime.class), NumberConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(Double.class, LocalDateTime.class), NumberConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(BigInteger.class, LocalDateTime.class), NumberConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(BigDecimal.class, LocalDateTime.class), NumberConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(AtomicLong.class, LocalDateTime.class), NumberConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, LocalDateTime.class), DateConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(Timestamp.class, LocalDateTime.class), DateConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(Date.class, LocalDateTime.class), DateConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(Instant.class, LocalDateTime.class), InstantConversion::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Void.class, LocalDateTime.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, LocalDateTime.class), NumberConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Double.class, LocalDateTime.class), NumberConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(BigInteger.class, LocalDateTime.class), NumberConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(BigDecimal.class, LocalDateTime.class), NumberConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(AtomicLong.class, LocalDateTime.class), NumberConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, LocalDateTime.class), DateConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Timestamp.class, LocalDateTime.class), DateConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Date.class, LocalDateTime.class), DateConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Instant.class, LocalDateTime.class), InstantConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalDateTime.class), Converter::identity); - DEFAULT_FACTORY.put(pair(LocalDate.class, LocalDateTime.class), LocalDateConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalDateTime.class), ZonedDateTimeConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(Calendar.class, LocalDateTime.class), CalendarConversion::toLocalDateTime); - DEFAULT_FACTORY.put(pair(Number.class, LocalDateTime.class), NumberConversion::toLocalDateTime); + DEFAULT_FACTORY.put(pair(LocalDate.class, LocalDateTime.class), LocalDateConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalDateTime.class), ZonedDateTimeConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Calendar.class, LocalDateTime.class), CalendarConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(Number.class, LocalDateTime.class), NumberConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(Map.class, LocalDateTime.class), (fromInstance, converter, options) -> { Map map = (Map) fromInstance; return converter.fromValueMap(map, LocalDateTime.class, null, options); @@ -638,20 +608,20 @@ private static void buildFactoryConversions() { }); // ZonedDateTime conversions supported - DEFAULT_FACTORY.put(pair(Void.class, ZonedDateTime.class), VoidConversion::toNull); - DEFAULT_FACTORY.put(pair(Long.class, ZonedDateTime.class), NumberConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(Double.class, ZonedDateTime.class), NumberConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(BigInteger.class, ZonedDateTime.class), NumberConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(BigDecimal.class, ZonedDateTime.class), NumberConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(AtomicLong.class, ZonedDateTime.class), NumberConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, ZonedDateTime.class), DateConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(Timestamp.class, ZonedDateTime.class), DateConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(Date.class, ZonedDateTime.class), DateConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(LocalDate.class, ZonedDateTime.class), LocalDateConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, ZonedDateTime.class), LocalDateTimeConversion::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Void.class, ZonedDateTime.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Double.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(BigInteger.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(BigDecimal.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(AtomicLong.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, ZonedDateTime.class), DateConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Timestamp.class, ZonedDateTime.class), DateConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Date.class, ZonedDateTime.class), DateConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(LocalDate.class, ZonedDateTime.class), LocalDateConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, ZonedDateTime.class), LocalDateTimeConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(ZonedDateTime.class, ZonedDateTime.class), Converter::identity); - DEFAULT_FACTORY.put(pair(Calendar.class, ZonedDateTime.class), CalendarConversion::toZonedDateTime); - DEFAULT_FACTORY.put(pair(Number.class, ZonedDateTime.class), NumberConversion::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Calendar.class, ZonedDateTime.class), CalendarConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Number.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(Map.class, ZonedDateTime.class), (fromInstance, converter, options) -> { Map map = (Map) fromInstance; return converter.fromValueMap(map, ZonedDateTime.class, null, options); @@ -666,7 +636,7 @@ private static void buildFactoryConversions() { }); // UUID conversions supported - DEFAULT_FACTORY.put(pair(Void.class, UUID.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, UUID.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(UUID.class, UUID.class), Converter::identity); DEFAULT_FACTORY.put(pair(String.class, UUID.class), (fromInstance, converter, options) -> UUID.fromString(((String) fromInstance).trim())); DEFAULT_FACTORY.put(pair(BigInteger.class, UUID.class), (fromInstance, converter, options) -> { @@ -682,10 +652,10 @@ private static void buildFactoryConversions() { long leastSigBits = bigInt.and(new BigInteger("FFFFFFFFFFFFFFFF", 16)).longValue(); return new UUID(mostSigBits, leastSigBits); }); - DEFAULT_FACTORY.put(pair(Map.class, UUID.class), MapConversion::toUUID); + DEFAULT_FACTORY.put(pair(Map.class, UUID.class), MapConversions::toUUID); // Class conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Class.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, Class.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Class.class, Class.class), Converter::identity); DEFAULT_FACTORY.put(pair(Map.class, Class.class), (fromInstance, converter, options) -> converter.fromValueMap((Map) fromInstance, AtomicLong.class, null, options)); DEFAULT_FACTORY.put(pair(String.class, Class.class), (fromInstance, converter, options) -> { @@ -698,7 +668,7 @@ private static void buildFactoryConversions() { }); // String conversions supported - DEFAULT_FACTORY.put(pair(Void.class, String.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, String.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Byte.class, String.class), Converter::toString); DEFAULT_FACTORY.put(pair(Short.class, String.class), Converter::toString); DEFAULT_FACTORY.put(pair(Integer.class, String.class), Converter::toString); @@ -744,7 +714,7 @@ private static void buildFactoryConversions() { return simpleDateFormat.format(((Calendar) fromInstance).getTime()); }); DEFAULT_FACTORY.put(pair(Number.class, String.class), Converter::toString); - DEFAULT_FACTORY.put(pair(Map.class, String.class), MapConversion::toString); + DEFAULT_FACTORY.put(pair(Map.class, String.class), MapConversions::toString); DEFAULT_FACTORY.put(pair(Enum.class, String.class), (fromInstance, converter, options) -> ((Enum) fromInstance).name()); DEFAULT_FACTORY.put(pair(String.class, String.class), Converter::identity); DEFAULT_FACTORY.put(pair(Duration.class, String.class), Converter::toString); @@ -753,7 +723,7 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(MonthDay.class, String.class), Converter::toString); // Duration conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Duration.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, Duration.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Duration.class, Duration.class), Converter::identity); DEFAULT_FACTORY.put(pair(String.class, Duration.class), (fromInstance, converter, options) -> Duration.parse((String) fromInstance)); DEFAULT_FACTORY.put(pair(Map.class, Duration.class), (fromInstance, converter, options) -> { @@ -768,34 +738,23 @@ private static void buildFactoryConversions() { }); // Instant conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Instant.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, Instant.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Instant.class, Instant.class), Converter::identity); - - DEFAULT_FACTORY.put(pair(Long.class, Instant.class), NumberConversion::toInstant); - DEFAULT_FACTORY.put(pair(Double.class, Instant.class), NumberConversion::toInstant); - DEFAULT_FACTORY.put(pair(BigInteger.class, Instant.class), NumberConversion::toInstant); - DEFAULT_FACTORY.put(pair(BigDecimal.class, Instant.class), NumberConversion::toInstant); - DEFAULT_FACTORY.put(pair(AtomicLong.class, Instant.class), NumberConversion::toInstant); - DEFAULT_FACTORY.put(pair(java.sql.Date.class, Instant.class), DateConversion::toInstant); - DEFAULT_FACTORY.put(pair(Timestamp.class, Instant.class), DateConversion::toInstant); - DEFAULT_FACTORY.put(pair(Date.class, Instant.class), DateConversion::toInstant); - DEFAULT_FACTORY.put(pair(LocalDate.class, Instant.class), LocalDateConversion::toInstant); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, Instant.class), LocalDateTimeConversion::toInstant); - DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Instant.class), ZonedDateTimeConversion::toInstant); - DEFAULT_FACTORY.put(pair(Calendar.class, Instant.class), CalendarConversion::toInstant); - DEFAULT_FACTORY.put(pair(Number.class, Instant.class), NumberConversion::toInstant); - - - - - - DEFAULT_FACTORY.put(pair(String.class, Instant.class), (fromInstance, converter, options) -> { - try { - return Instant.parse((String) fromInstance); - } catch (Exception e) { - return DateUtilities.parseDate((String) fromInstance).toInstant(); - } - }); + DEFAULT_FACTORY.put(pair(Long.class, Instant.class), NumberConversions::toInstant); + DEFAULT_FACTORY.put(pair(Double.class, Instant.class), NumberConversions::toInstant); + DEFAULT_FACTORY.put(pair(BigInteger.class, Instant.class), NumberConversions::toInstant); + DEFAULT_FACTORY.put(pair(BigDecimal.class, Instant.class), NumberConversions::toInstant); + DEFAULT_FACTORY.put(pair(AtomicLong.class, Instant.class), NumberConversions::toInstant); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, Instant.class), DateConversions::toInstant); + DEFAULT_FACTORY.put(pair(Timestamp.class, Instant.class), DateConversions::toInstant); + DEFAULT_FACTORY.put(pair(Date.class, Instant.class), DateConversions::toInstant); + DEFAULT_FACTORY.put(pair(LocalDate.class, Instant.class), LocalDateConversions::toInstant); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, Instant.class), LocalDateTimeConversions::toInstant); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Instant.class), ZonedDateTimeConversions::toInstant); + DEFAULT_FACTORY.put(pair(Calendar.class, Instant.class), CalendarConversions::toInstant); + DEFAULT_FACTORY.put(pair(Number.class, Instant.class), NumberConversions::toInstant); + + DEFAULT_FACTORY.put(pair(String.class, Instant.class), StringConversions::toInstant); DEFAULT_FACTORY.put(pair(Map.class, Instant.class), (fromInstance, converter, options) -> { Map map = (Map) fromInstance; if (map.containsKey("seconds")) { @@ -817,7 +776,7 @@ private static void buildFactoryConversions() { // java.time.ZoneRegion = com.cedarsoftware.util.io.DEFAULT_FACTORY.ZoneIdFactory // MonthDay conversions supported - DEFAULT_FACTORY.put(pair(Void.class, MonthDay.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, MonthDay.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(MonthDay.class, MonthDay.class), Converter::identity); DEFAULT_FACTORY.put(pair(String.class, MonthDay.class), (fromInstance, converter, options) -> { String monthDay = (String) fromInstance; @@ -835,7 +794,7 @@ private static void buildFactoryConversions() { }); // Map conversions supported - DEFAULT_FACTORY.put(pair(Void.class, Map.class), VoidConversion::toNull); + DEFAULT_FACTORY.put(pair(Void.class, Map.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Byte.class, Map.class), Converter::initMap); DEFAULT_FACTORY.put(pair(Short.class, Map.class), Converter::initMap); DEFAULT_FACTORY.put(pair(Integer.class, Map.class), Converter::initMap); diff --git a/src/main/java/com/cedarsoftware/util/convert/ConverterOptions.java b/src/main/java/com/cedarsoftware/util/convert/ConverterOptions.java index 30008478..60f74f84 100644 --- a/src/main/java/com/cedarsoftware/util/convert/ConverterOptions.java +++ b/src/main/java/com/cedarsoftware/util/convert/ConverterOptions.java @@ -65,4 +65,16 @@ public interface ConverterOptions { * @return TimeZone expected on the target when finished (only for types that support ZoneId or TimeZone) */ default TimeZone getTimeZone() { return TimeZone.getTimeZone(this.getZoneId()); } + + /** + * Character to return for boolean to Character conversion when the boolean is true. + * @return the Character representing true + */ + default Character trueChar() { return CommonValues.CHARACTER_ONE; } + + /** + * Character to return for boolean to Character conversion when the boolean is false. + * @return the Character representing false + */ + default Character falseChar() { return CommonValues.CHARACTER_ZERO; } } diff --git a/src/main/java/com/cedarsoftware/util/convert/DateConversion.java b/src/main/java/com/cedarsoftware/util/convert/DateConversions.java similarity index 62% rename from src/main/java/com/cedarsoftware/util/convert/DateConversion.java rename to src/main/java/com/cedarsoftware/util/convert/DateConversions.java index fb2ca26a..d648dae4 100644 --- a/src/main/java/com/cedarsoftware/util/convert/DateConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/DateConversions.java @@ -11,7 +11,7 @@ import java.util.Date; import java.util.concurrent.atomic.AtomicLong; -public class DateConversion { +public class DateConversions { static long toLong(Object fromInstance) { return ((Date) fromInstance).getTime(); @@ -29,16 +29,43 @@ static long toLong(Object fromInstance, Converter converter, ConverterOptions op return toLong(fromInstance); } - static Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { + /** + * The input can be any of our Date type objects (java.sql.Date, Timestamp, Date, etc.) coming in so + * we need to force the conversion by creating a new instance. + * @param fromInstance - one of the date objects + * @param converter - converter instance + * @param options - converter options + * @return newly created java.sql.Date + */ + static java.sql.Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { return new java.sql.Date(toLong(fromInstance)); } + /** + * The input can be any of our Date type objects (java.sql.Date, Timestamp, Date, etc.) coming in so + * we need to force the conversion by creating a new instance. + * @param fromInstance - one of the date objects + * @param converter - converter instance + * @param options - converter options + * @return newly created Date + */ static Date toDate(Object fromInstance, Converter converter, ConverterOptions options) { + return new Date(toLong(fromInstance)); + } + + /** + * The input can be any of our Date type objects (java.sql.Date, Timestamp, Date, etc.) coming in so + * we need to force the conversion by creating a new instance. + * @param fromInstance - one of the date objects + * @param converter - converter instance + * @param options - converter options + * @return newly created Timestamp + */ static Timestamp toTimestamp(Object fromInstance, Converter converter, ConverterOptions options) { return new Timestamp(toLong(fromInstance)); } static Calendar toCalendar(Object fromInstance, Converter converter, ConverterOptions options) { - return CalendarConversion.create(toLong(fromInstance), options); + return CalendarConversions.create(toLong(fromInstance), options); } static BigDecimal toBigDecimal(Object fromInstance, Converter converter, ConverterOptions options) { diff --git a/src/main/java/com/cedarsoftware/util/convert/InstantConversion.java b/src/main/java/com/cedarsoftware/util/convert/InstantConversion.java deleted file mode 100644 index e8704d9b..00000000 --- a/src/main/java/com/cedarsoftware/util/convert/InstantConversion.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.cedarsoftware.util.convert; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.Calendar; -import java.util.Date; -import java.util.concurrent.atomic.AtomicLong; - -public class InstantConversion { - static long toLong(Object fromInstance, Converter converter, ConverterOptions options) { - Instant from = (Instant)fromInstance; - return from.toEpochMilli(); - } - - static float toFloat(Object fromInstance, Converter converter, ConverterOptions options) { - return toLong(fromInstance, converter, options); - } - - static double toDouble(Object fromInstance, Converter converter, ConverterOptions options) { - return toLong(fromInstance, converter, options); - } - - static AtomicLong toAtomicLong(Object fromInstance, Converter converter, ConverterOptions options) { - return new AtomicLong(toLong(fromInstance, converter, options)); - } - - static Timestamp toTimestamp(Object fromInstance, Converter converter, ConverterOptions options) { - return new Timestamp(toLong(fromInstance, converter, options)); - } - - static Calendar toCalendar(Object fromInstance, Converter converter, ConverterOptions options) { - long localDateMillis = toLong(fromInstance, converter, options); - return CalendarConversion.create(localDateMillis, options); - } - - static java.sql.Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { - return new java.sql.Date(toLong(fromInstance, converter, options)); - } - - static Date toDate(Object fromInstance, Converter converter, ConverterOptions options) { - return new Date(toLong(fromInstance, converter, options)); - } - - static BigInteger toBigInteger(Object fromInstance, Converter converter, ConverterOptions options) { - return BigInteger.valueOf(toLong(fromInstance, converter, options)); - } - - static BigDecimal toBigDecimal(Object fromInstance, Converter converter, ConverterOptions options) { - return BigDecimal.valueOf(toLong(fromInstance, converter, options)); - } - - static LocalDateTime toLocalDateTime(Object fromInstance, Converter converter, ConverterOptions options) { - Instant from = (Instant)fromInstance; - return from.atZone(options.getZoneId()).toLocalDateTime(); - } - - static LocalDate toLocalDate(Object fromInstance, Converter converter, ConverterOptions options) { - Instant from = (Instant)fromInstance; - return from.atZone(options.getZoneId()).toLocalDate(); - } - - -} diff --git a/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java b/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java new file mode 100644 index 00000000..581d84ac --- /dev/null +++ b/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java @@ -0,0 +1,76 @@ +package com.cedarsoftware.util.convert; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.Calendar; +import java.util.Date; +import java.util.concurrent.atomic.AtomicLong; + +public class InstantConversions { + + static long toLong(Object from) { + return ((Instant)from).toEpochMilli(); + } + + static ZonedDateTime toZonedDateTime(Object from, ConverterOptions options) { + return ((Instant)from).atZone(options.getZoneId()); + } + + static long toLong(Object from, Converter converter, ConverterOptions options) { + return toLong(from); + } + + static float toFloat(Object from, Converter converter, ConverterOptions options) { + return toLong(from); + } + + static double toDouble(Object from, Converter converter, ConverterOptions options) { + return toLong(from); + } + + static AtomicLong toAtomicLong(Object from, Converter converter, ConverterOptions options) { + return new AtomicLong(toLong(from)); + } + + static Timestamp toTimestamp(Object from, Converter converter, ConverterOptions options) { + return new Timestamp(toLong(from)); + } + + static java.sql.Date toSqlDate(Object from, Converter converter, ConverterOptions options) { + return new java.sql.Date(toLong(from)); + } + + static Date toDate(Object from, Converter converter, ConverterOptions options) { + return new Date(toLong(from)); + } + + static Calendar toCalendar(Object from, Converter converter, ConverterOptions options) { + return CalendarConversions.create(toLong(from), options); + } + + static BigInteger toBigInteger(Object from, Converter converter, ConverterOptions options) { + return BigInteger.valueOf(toLong(from)); + } + + static BigDecimal toBigDecimal(Object from, Converter converter, ConverterOptions options) { + return BigDecimal.valueOf(toLong(from)); + } + + static LocalDateTime toLocalDateTime(Object from, Converter converter, ConverterOptions options) { + return toZonedDateTime(from, options).toLocalDateTime(); + } + + static LocalDate toLocalDate(Object from, Converter converter, ConverterOptions options) { + return toZonedDateTime(from, options).toLocalDate(); + } + + static LocalTime toLocalTime(Object from, Converter converter, ConverterOptions options) { + return toZonedDateTime(from, options).toLocalTime(); + } +} diff --git a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversion.java b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java similarity index 96% rename from src/main/java/com/cedarsoftware/util/convert/LocalDateConversion.java rename to src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java index 0a5ef087..5e054c67 100644 --- a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java @@ -11,7 +11,7 @@ import java.util.Date; import java.util.concurrent.atomic.AtomicLong; -public class LocalDateConversion { +public class LocalDateConversions { private static ZonedDateTime toZonedDateTime(Object fromInstance, ConverterOptions options) { return ((LocalDate)fromInstance).atStartOfDay(options.getZoneId()); @@ -60,7 +60,7 @@ static Timestamp toTimestamp(Object fromInstance, Converter converter, Converter } static Calendar toCalendar(Object fromInstance, Converter converter, ConverterOptions options) { - return CalendarConversion.create(toLong(fromInstance, options), options); + return CalendarConversions.create(toLong(fromInstance, options), options); } static java.sql.Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { diff --git a/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversion.java b/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java similarity index 97% rename from src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversion.java rename to src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java index 0a433b21..86940ae5 100644 --- a/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java @@ -4,7 +4,6 @@ import java.math.BigInteger; import java.sql.Timestamp; import java.time.Instant; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.util.Calendar; @@ -12,7 +11,7 @@ import java.util.GregorianCalendar; import java.util.concurrent.atomic.AtomicLong; -public class LocalDateTimeConversion { +public class LocalDateTimeConversions { private static ZonedDateTime toZonedDateTime(Object fromInstance, ConverterOptions options) { return ((LocalDateTime)fromInstance).atZone(options.getSourceZoneIdForLocalDates()); } diff --git a/src/main/java/com/cedarsoftware/util/convert/MapConversion.java b/src/main/java/com/cedarsoftware/util/convert/MapConversions.java similarity index 57% rename from src/main/java/com/cedarsoftware/util/convert/MapConversion.java rename to src/main/java/com/cedarsoftware/util/convert/MapConversions.java index 1c688c95..51c90876 100644 --- a/src/main/java/com/cedarsoftware/util/convert/MapConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/MapConversions.java @@ -1,34 +1,42 @@ package com.cedarsoftware.util.convert; +import com.cedarsoftware.util.ArrayUtilities; import com.cedarsoftware.util.Convention; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.Arrays; +import java.sql.Timestamp; +import java.util.Date; import java.util.Map; -import java.util.Optional; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Supplier; -public class MapConversion { +public class MapConversions { private static final String V = "_v"; private static final String VALUE = "value"; + private static final String TIME = "time"; + private static final String NANOS = "nanos"; + + private static final String MOST_SIG_BITS = "mostSigBits"; + private static final String LEAST_SIG_BITS = "leastSigBits"; + + + public static final String KEY_VALUE_ERROR_MESSAGE = "To convert from Map to %s the map must include one of the following: %s[_v], or [value] with associated values."; + private static String[] UUID_PARAMS = new String[] { MOST_SIG_BITS, LEAST_SIG_BITS }; static Object toUUID(Object fromInstance, Converter converter, ConverterOptions options) { Map map = (Map) fromInstance; - if (map.containsKey("mostSigBits") && map.containsKey("leastSigBits")) { - long most = converter.convert(map.get("mostSigBits"), long.class, options); - long least = converter.convert(map.get("leastSigBits"), long.class, options); - + if (map.containsKey(MOST_SIG_BITS) && map.containsKey(LEAST_SIG_BITS)) { + long most = converter.convert(map.get(MOST_SIG_BITS), long.class, options); + long least = converter.convert(map.get(LEAST_SIG_BITS), long.class, options); return new UUID(most, least); } - throw new IllegalArgumentException("To convert Map to UUID, the Map must contain both 'mostSigBits' and 'leastSigBits' keys"); + return fromValueForMultiKey(fromInstance, converter, options, UUID.class, UUID_PARAMS); } static Byte toByte(Object fromInstance, Converter converter, ConverterOptions options) { @@ -83,50 +91,61 @@ static AtomicBoolean toAtomicBoolean(Object fromInstance, Converter converter, C return fromValue(fromInstance, converter, options, AtomicBoolean.class); } - private static final String TIME = "time"; - static java.sql.Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { - return fromKeyOrValue(fromInstance, TIME, java.sql.Date.class, converter, options); + return fromSingleKey(fromInstance, converter, options, TIME, java.sql.Date.class); + } + + static Date toDate(Object fromInstance, Converter converter, ConverterOptions options) { + return fromSingleKey(fromInstance, converter, options, TIME, Date.class); + } + + private static final String[] TIMESTAMP_PARAMS = new String[] { TIME, NANOS }; + static Timestamp toTimestamp(Object fromInstance, Converter converter, ConverterOptions options) { + Map map = (Map) fromInstance; + if (map.containsKey("time")) { + long time = converter.convert(map.get("time"), long.class, options); + int ns = converter.convert(map.get("nanos"), int.class, options); + Timestamp timeStamp = new Timestamp(time); + timeStamp.setNanos(ns); + return timeStamp; + } + + return fromValueForMultiKey(map, converter, options, Timestamp.class, TIMESTAMP_PARAMS); } + /** * Allows you to check for a single named key and convert that to a type of it exists, otherwise falls back * onto the value type V or VALUE. - * @return type if it exists, else returns what is in V or VALUE + * * @param type of object to convert the value. + * @return type if it exists, else returns what is in V or VALUE */ - static T fromKeyOrValue(final Object fromInstance, final String key, final Class type, final Converter converter, final ConverterOptions options) { - Convention.throwIfFalse(fromInstance instanceof Map, "fromInstance must be an instance of map"); - Convention.throwIfNullOrEmpty(key, "key cannot be null or empty"); - Convention.throwIfNull(type, "type cannot be null"); - Convention.throwIfNull(converter, "converter cannot be null"); - Convention.throwIfNull(options, "options cannot be null"); + static T fromSingleKey(final Object fromInstance, final Converter converter, final ConverterOptions options, final String key, final Class type) { + validateParams(converter, options, type); - Map map = (Map) fromInstance; + Map map = asMap(fromInstance); if (map.containsKey(key)) { return converter.convert(key, type, options); } - if (map.containsKey(V)) { - return converter.convert(map.get(V), type, options); - } + return extractValue(map, converter, options, type, key); + } - if (map.containsKey(VALUE)) { - return converter.convert(map.get(VALUE), type, options); - } + static T fromValueForMultiKey(Object from, Converter converter, ConverterOptions options, Class type, String[] keys) { + validateParams(converter, options, type); - throw new IllegalArgumentException(String.format("To convert from Map to %s the map must include keys: %s, '_v' or 'value' an associated value to convert from.", getShortName(type), key)); + return extractValue(asMap(from), converter, options, type, keys); } - static T fromValue(Object fromInstance, Converter converter, ConverterOptions options, Class type) { - Convention.throwIfFalse(fromInstance instanceof Map, "fromInstance must be an instance of map"); - Convention.throwIfNull(type, "type cannot be null"); - Convention.throwIfNull(converter, "converter cannot be null"); - Convention.throwIfNull(options, "options cannot be null"); + static T fromValue(Object from, Converter converter, ConverterOptions options, Class type) { + validateParams(converter, options, type); - Map map = (Map) fromInstance; + return extractValue(asMap(from), converter, options, type); + } + private static T extractValue(Map map, Converter converter, ConverterOptions options, Class type, String...keys) { if (map.containsKey(V)) { return converter.convert(map.get(V), type, options); } @@ -135,19 +154,22 @@ static T fromValue(Object fromInstance, Converter converter, ConverterOption return converter.convert(map.get(VALUE), type, options); } - throw new IllegalArgumentException(String.format("To convert from Map to %s the map must include keys: '_v' or 'value' an associated value to convert from.", getShortName(type))); - } - - static Optional convert(Map map, String key, Class type, Converter converter, ConverterOptions options) { - return map.containsKey(key) ? Optional.of(converter.convert(map.get(key), type, options)) : Optional.empty(); + String keyText = ArrayUtilities.isEmpty(keys) ? "" : "[" + String.join(",", keys) + "], "; + throw new IllegalArgumentException(String.format(KEY_VALUE_ERROR_MESSAGE, getShortName(type), keyText)); } - private static T getConvertedValue(Map map, String key, Class type, Converter converter, ConverterOptions options) { - // NOPE STUFF? - return converter.convert(map.get(key), type, options); + private static void validateParams(Converter converter, ConverterOptions options, Class type) { + Convention.throwIfNull(type, "type cannot be null"); + Convention.throwIfNull(converter, "converter cannot be null"); + Convention.throwIfNull(options, "options cannot be null"); } private static String getShortName(Class type) { return java.sql.Date.class.equals(type) ? type.getName() : type.getSimpleName(); } + + private static Map asMap(Object o) { + Convention.throwIfFalse(o instanceof Map, "fromInstance must be an instance of map"); + return (Map)o; + } } diff --git a/src/main/java/com/cedarsoftware/util/convert/NumberConversion.java b/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java similarity index 92% rename from src/main/java/com/cedarsoftware/util/convert/NumberConversion.java rename to src/main/java/com/cedarsoftware/util/convert/NumberConversions.java index 1c968e79..22abc99e 100644 --- a/src/main/java/com/cedarsoftware/util/convert/NumberConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java @@ -30,7 +30,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -public class NumberConversion { +public class NumberConversions { static byte toByte(Object from, Converter converter, ConverterOptions options) { return ((Number)from).byteValue(); @@ -100,7 +100,6 @@ static Double toDoubleZero(Object from, Converter converter, ConverterOptions op static BigDecimal integerTypeToBigDecimal(Object from, Converter converter, ConverterOptions options) { return BigDecimal.valueOf(toLong(from)); } - static BigInteger integerTypeToBigInteger(Object from, Converter converter, ConverterOptions options) { return BigInteger.valueOf(toLong(from)); } @@ -121,6 +120,10 @@ static BigInteger bigDecimalToBigInteger(Object from, Converter converter, Conve return ((BigDecimal)from).toBigInteger(); } + static BigDecimal bigDecimalToBigDecimal(Object from, Converter converter, ConverterOptions options) { + return new BigDecimal(from.toString()); + } + static AtomicBoolean toAtomicBoolean(Object from, Converter converter, ConverterOptions options) { return new AtomicBoolean(toLong(from) != 0); } @@ -129,6 +132,10 @@ static BigDecimal floatingPointToBigDecimal(Object from, Converter converter, Co return BigDecimal.valueOf(toDouble(from)); } + static BigInteger floatingPointToBigInteger(Object from, Converter converter, ConverterOptions options) { + return new BigInteger(String.format("%.0f", ((Number)from).doubleValue())); + } + static boolean isIntTypeNotZero(Object from, Converter converter, ConverterOptions options) { return toLong(from) != 0; } @@ -145,6 +152,11 @@ static boolean isBigDecimalNotZero(Object from, Converter converter, ConverterOp return ((BigDecimal)from).compareTo(BigDecimal.ZERO) != 0; } + static BigInteger toBigInteger(Object from, Converter converter, ConverterOptions options) { + return new BigInteger(from.toString()); + } + + /** * @param from Number instance to convert to char. * @return char that best represents the Number. The result will always be a value between @@ -188,7 +200,7 @@ static Timestamp toTimestamp(Object from, Converter converter, ConverterOptions } static Calendar toCalendar(Object from, Converter converter, ConverterOptions options) { - return CalendarConversion.create(toLong(from), options); + return CalendarConversions.create(toLong(from), options); } static LocalDate toLocalDate(Object from, Converter converter, ConverterOptions options) { diff --git a/src/main/java/com/cedarsoftware/util/convert/StringConversion.java b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java similarity index 85% rename from src/main/java/com/cedarsoftware/util/convert/StringConversion.java rename to src/main/java/com/cedarsoftware/util/convert/StringConversions.java index eb349f7e..a5638c3e 100644 --- a/src/main/java/com/cedarsoftware/util/convert/StringConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java @@ -3,16 +3,15 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; +import java.sql.Timestamp; +import java.time.Instant; import java.util.Date; -import java.util.HashSet; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import com.cedarsoftware.util.CaseInsensitiveSet; -import com.cedarsoftware.util.CollectionUtilities; import com.cedarsoftware.util.DateUtilities; +import com.cedarsoftware.util.StringUtilities; /** * @author John DeRegnaucourt (jdereg@gmail.com) @@ -31,7 +30,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -public class StringConversion { +public class StringConversions { private static final BigDecimal bigDecimalMinByte = BigDecimal.valueOf(Byte.MIN_VALUE); private static final BigDecimal bigDecimalMaxByte = BigDecimal.valueOf(Byte.MAX_VALUE); private static final BigDecimal bigDecimalMinShort = BigDecimal.valueOf(Short.MIN_VALUE); @@ -188,7 +187,7 @@ static AtomicInteger toAtomicInteger(Object from, Converter converter, Converter } static AtomicLong toAtomicLong(Object from, Converter converter, ConverterOptions options) { - String str = ((String) from).trim(); + String str = StringUtilities.trimToEmpty((String)from); if (str.isEmpty()) { return new AtomicLong(0L); } @@ -200,7 +199,7 @@ static AtomicLong toAtomicLong(Object from, Converter converter, ConverterOption } static Boolean toBoolean(Object from, Converter converter, ConverterOptions options) { - String str = ((String) from).trim(); + String str = StringUtilities.trimToEmpty((String)from); if (str.isEmpty()) { return false; } @@ -210,11 +209,11 @@ static Boolean toBoolean(Object from, Converter converter, ConverterOptions opti } else if ("false".equals(str)) { return false; } - return "true".equalsIgnoreCase(str) || "t".equalsIgnoreCase(str) || "1".equalsIgnoreCase(str); + return "true".equalsIgnoreCase(str) || "t".equalsIgnoreCase(str) || "1".equalsIgnoreCase(str) || "y".equalsIgnoreCase(str); } static char toCharacter(Object from, Converter converter, ConverterOptions options) { - String str = ((String) from); + String str = StringUtilities.trimToEmpty((String)from); if (str.isEmpty()) { return (char) 0; } @@ -226,7 +225,7 @@ static char toCharacter(Object from, Converter converter, ConverterOptions optio } static BigInteger toBigInteger(Object from, Converter converter, ConverterOptions options) { - String str = ((String) from).trim(); + String str = StringUtilities.trimToEmpty((String)from); if (str.isEmpty()) { return BigInteger.ZERO; } @@ -239,7 +238,7 @@ static BigInteger toBigInteger(Object from, Converter converter, ConverterOption } static BigDecimal toBigDecimal(Object from, Converter converter, ConverterOptions options) { - String str = ((String) from).trim(); + String str = StringUtilities.trimToEmpty((String)from); if (str.isEmpty()) { return BigDecimal.ZERO; } @@ -251,11 +250,34 @@ static BigDecimal toBigDecimal(Object from, Converter converter, ConverterOption } static java.sql.Date toSqlDate(Object from, Converter converter, ConverterOptions options) { - String str = ((String) from).trim(); + String str = StringUtilities.trimToNull((String)from); Date date = DateUtilities.parseDate(str); - if (date == null) { + return date == null ? null : new java.sql.Date(date.getTime()); + } + + static Timestamp toTimestamp(Object from, Converter converter, ConverterOptions options) { + String str = StringUtilities.trimToNull((String)from); + Date date = DateUtilities.parseDate(str); + return date == null ? null : new Timestamp(date.getTime()); + } + + static Date toDate(Object from, Converter converter, ConverterOptions options) { + String str = StringUtilities.trimToNull((String)from); + Date date = DateUtilities.parseDate(str); + return date; + } + + static Instant toInstant(Object from, Converter converter, ConverterOptions options) { + String s = StringUtilities.trimToEmpty((String)from); + if (s.isEmpty()) { return null; } - return new java.sql.Date(date.getTime()); + + try { + return Instant.parse(s); + } catch (Exception e) { + Date date = DateUtilities.parseDate(s); + return date == null ? null : date.toInstant(); + } } } diff --git a/src/main/java/com/cedarsoftware/util/convert/UUIDConversions.java b/src/main/java/com/cedarsoftware/util/convert/UUIDConversions.java new file mode 100644 index 00000000..cc7b4567 --- /dev/null +++ b/src/main/java/com/cedarsoftware/util/convert/UUIDConversions.java @@ -0,0 +1,28 @@ +package com.cedarsoftware.util.convert; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.UUID; + +public final class UUIDConversions { + + private UUIDConversions() { + } + + static BigDecimal toBigDecimal(Object from, Converter converter, ConverterOptions options) { + UUID uuid = (UUID) from; + BigInteger mostSignificant = BigInteger.valueOf(uuid.getMostSignificantBits()); + BigInteger leastSignificant = BigInteger.valueOf(uuid.getLeastSignificantBits()); + // Shift the most significant bits to the left and add the least significant bits + return new BigDecimal(mostSignificant.shiftLeft(64).add(leastSignificant)); + } + + static BigInteger toBigInteger(Object from, Converter converter, ConverterOptions options) { + UUID uuid = (UUID) from; + BigInteger mostSignificant = BigInteger.valueOf(uuid.getMostSignificantBits()); + BigInteger leastSignificant = BigInteger.valueOf(uuid.getLeastSignificantBits()); + // Shift the most significant bits to the left and add the least significant bits + return mostSignificant.shiftLeft(64).add(leastSignificant); + } +} + diff --git a/src/main/java/com/cedarsoftware/util/convert/VoidConversion.java b/src/main/java/com/cedarsoftware/util/convert/VoidConversions.java similarity index 94% rename from src/main/java/com/cedarsoftware/util/convert/VoidConversion.java rename to src/main/java/com/cedarsoftware/util/convert/VoidConversions.java index 6ca23ae2..08218952 100644 --- a/src/main/java/com/cedarsoftware/util/convert/VoidConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/VoidConversions.java @@ -17,7 +17,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -public class VoidConversion { +public final class VoidConversions { + + private VoidConversions() { + } static Object toNull(Object from, Converter converter, ConverterOptions options) { return null; diff --git a/src/main/java/com/cedarsoftware/util/convert/ZonedDateTimeConversion.java b/src/main/java/com/cedarsoftware/util/convert/ZonedDateTimeConversions.java similarity index 95% rename from src/main/java/com/cedarsoftware/util/convert/ZonedDateTimeConversion.java rename to src/main/java/com/cedarsoftware/util/convert/ZonedDateTimeConversions.java index 1a765188..4395d4bb 100644 --- a/src/main/java/com/cedarsoftware/util/convert/ZonedDateTimeConversion.java +++ b/src/main/java/com/cedarsoftware/util/convert/ZonedDateTimeConversions.java @@ -12,7 +12,7 @@ import java.util.Date; import java.util.concurrent.atomic.AtomicLong; -public class ZonedDateTimeConversion { +public class ZonedDateTimeConversions { static ZonedDateTime toDifferentZone(Object fromInstance, ConverterOptions options) { return ((ZonedDateTime)fromInstance).withZoneSameInstant(options.getZoneId()); @@ -55,7 +55,7 @@ static Timestamp toTimestamp(Object fromInstance, Converter converter, Converter } static Calendar toCalendar(Object fromInstance, Converter converter, ConverterOptions options) { - return CalendarConversion.create(toLong(fromInstance), options); + return CalendarConversions.create(toLong(fromInstance), options); } static java.sql.Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { diff --git a/src/test/java/com/cedarsoftware/util/TestStringUtilities.java b/src/test/java/com/cedarsoftware/util/TestStringUtilities.java index cffc8833..bb44b3af 100644 --- a/src/test/java/com/cedarsoftware/util/TestStringUtilities.java +++ b/src/test/java/com/cedarsoftware/util/TestStringUtilities.java @@ -2,12 +2,24 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; +import java.nio.ByteBuffer; import java.util.Random; import java.util.Set; import java.util.TreeSet; +import java.util.stream.Stream; +import com.cedarsoftware.util.convert.CommonValues; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.mockito.internal.util.StringUtil; +import javax.swing.text.Segment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -37,7 +49,7 @@ public class TestStringUtilities { @Test - public void testConstructorIsPrivate() throws Exception { + void testConstructorIsPrivate() throws Exception { Class c = StringUtilities.class; assertEquals(Modifier.FINAL, c.getModifiers() & Modifier.FINAL); @@ -48,6 +60,111 @@ public void testConstructorIsPrivate() throws Exception { assertNotNull(con.newInstance()); } + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testIsEmpty_whenStringHasWhitespace_returnsFalse(String s) + { + assertFalse(StringUtilities.isEmpty(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testIsEmpty_whenStringHasContent_returnsFalse(String s) + { + assertFalse(StringUtilities.isEmpty(s)); + } + + @ParameterizedTest + @NullAndEmptySource + void testIsEmpty_whenNullOrEmpty_returnsTrue(String s) + { + assertTrue(StringUtilities.isEmpty(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testIsNotEmpty_whenStringHasWhitespace_returnsTrue(String s) + { + assertTrue(StringUtilities.isNotEmpty(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testIsNotEmpty_whenStringHasContent_returnsTrue(String s) + { + assertTrue(StringUtilities.isNotEmpty(s)); + } + + @ParameterizedTest + @NullAndEmptySource + void testIsNotEmpty_whenNullOrEmpty_returnsFalse(String s) + { + assertFalse(StringUtilities.isNotEmpty(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testIsWhiteSpace_whenStringHasWhitespace_returnsTrue(String s) + { + assertTrue(StringUtilities.isWhitespace(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testIsWhiteSpace_whenStringHasContent_returnsFalse(String s) + { + assertFalse(StringUtilities.isWhitespace(s)); + } + + @ParameterizedTest + @NullAndEmptySource + void testIsWhiteSpace_whenNullOrEmpty_returnsTrue(String s) + { + assertTrue(StringUtilities.isWhitespace(s)); + } + + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testHasContent_whenStringHasWhitespace_returnsFalse(String s) + { + assertFalse(StringUtilities.hasContent(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testHasContent_whenStringHasContent_returnsTrue(String s) + { + assertTrue(StringUtilities.hasContent(s)); + } + + @ParameterizedTest + @NullAndEmptySource + void testHasContent_whenNullOrEmpty_returnsFalse(String s) + { + assertFalse(StringUtilities.hasContent(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testIsNotWhitespace_whenStringHasWhitespace_returnsFalse(String s) + { + assertFalse(StringUtilities.isNotWhitespace(s)); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testIsNotWhitespace_whenStringHasContent_returnsTrue(String s) + { + assertTrue(StringUtilities.isNotWhitespace(s)); + } + + @ParameterizedTest + @NullAndEmptySource + void testIsNotWhitespace_whenNullOrEmpty_returnsFalse(String s) + { + assertFalse(StringUtilities.isNotWhitespace(s)); + } @Test public void testIsEmpty() { @@ -57,14 +174,14 @@ public void testIsEmpty() } @Test - public void testHasContent() { + void testHasContent() { assertFalse(StringUtilities.hasContent(null)); assertFalse(StringUtilities.hasContent("")); assertTrue(StringUtilities.hasContent("foo")); } @Test - public void testTrimLength() { + void testTrimLength() { assertEquals(0, StringUtilities.trimLength(null)); assertEquals(0, StringUtilities.trimLength("")); assertEquals(3, StringUtilities.trimLength(" abc ")); @@ -75,7 +192,7 @@ public void testTrimLength() { } @Test - public void testEqualsWithTrim() { + void testEqualsWithTrim() { assertTrue(StringUtilities.equalsWithTrim("abc", " abc ")); assertTrue(StringUtilities.equalsWithTrim(" abc ", "abc")); assertFalse(StringUtilities.equalsWithTrim("abc", " AbC ")); @@ -86,7 +203,7 @@ public void testEqualsWithTrim() { } @Test - public void testEqualsIgnoreCaseWithTrim() { + void testEqualsIgnoreCaseWithTrim() { assertTrue(StringUtilities.equalsIgnoreCaseWithTrim("abc", " abc ")); assertTrue(StringUtilities.equalsIgnoreCaseWithTrim(" abc ", "abc")); assertTrue(StringUtilities.equalsIgnoreCaseWithTrim("abc", " AbC ")); @@ -97,7 +214,7 @@ public void testEqualsIgnoreCaseWithTrim() { } @Test - public void testCount() { + void testCount() { assertEquals(2, StringUtilities.count("abcabc", 'a')); assertEquals(0, StringUtilities.count("foo", 'a')); assertEquals(0, StringUtilities.count(null, 'a')); @@ -105,7 +222,7 @@ public void testCount() { } @Test - public void testString() + void testString() { assertTrue(StringUtilities.isEmpty(null)); assertFalse(StringUtilities.hasContent(null)); @@ -118,12 +235,12 @@ public void testString() } @Test - public void testEncode() { + void testEncode() { assertEquals("1A", StringUtilities.encode(new byte[]{0x1A})); assertEquals("", StringUtilities.encode(new byte[]{})); } - public void testEncodeWithNull() + void testEncodeWithNull() { try { @@ -136,13 +253,13 @@ public void testEncodeWithNull() } @Test - public void testDecode() { + void testDecode() { assertArrayEquals(new byte[]{0x1A}, StringUtilities.decode("1A")); assertArrayEquals(new byte[]{}, StringUtilities.decode("")); assertNull(StringUtilities.decode("1AB")); } - public void testDecodeWithNull() + void testDecodeWithNull() { try { @@ -154,31 +271,174 @@ public void testDecodeWithNull() } } - @Test - public void testEquals() + + private static Stream charSequenceEquals_caseSensitive() { + return Stream.of( + Arguments.of(null, null), + Arguments.of("", ""), + Arguments.of("foo", "foo"), + Arguments.of(new StringBuffer("foo"), "foo"), + Arguments.of(new StringBuilder("foo"), "foo"), + Arguments.of(new Segment("foobar".toCharArray(), 0, 3), "foo") + ); + } + + + + @ParameterizedTest + @MethodSource("charSequenceEquals_caseSensitive") + void testEquals_whenStringsAreEqualCaseSensitive_returnsTrue(CharSequence one, CharSequence two) + { + assertThat(StringUtilities.equals(one, two)).isTrue(); + } + + private static Stream charSequenceNotEqual_caseSensitive() { + return Stream.of( + Arguments.of(null, ""), + Arguments.of("", null), + Arguments.of("foo", "bar"), + Arguments.of(" foo", "bar"), + Arguments.of("foO", "foo"), + Arguments.of("foo", "food"), + Arguments.of(new StringBuffer("foo"), "bar"), + Arguments.of(new StringBuffer("foo"), " foo"), + Arguments.of(new StringBuffer("foO"), "foo"), + Arguments.of(new StringBuilder("foo"), "bar"), + Arguments.of(new StringBuilder("foo"), " foo "), + Arguments.of(new StringBuilder("foO"), "foo"), + Arguments.of(new Segment("foobar".toCharArray(), 0, 3), "bar"), + Arguments.of(new Segment(" foo ".toCharArray(), 0, 5), "bar"), + Arguments.of(new Segment("FOOBAR".toCharArray(), 0, 3), "foo") + ); + } + @ParameterizedTest + @MethodSource("charSequenceNotEqual_caseSensitive") + void testEquals_whenStringsAreNotEqualCaseSensitive_returnsFalse(CharSequence one, CharSequence two) + { + assertThat(StringUtilities.equals(one, two)).isFalse(); + } + + private static Stream charSequenceEquals_ignoringCase() { + return Stream.of( + Arguments.of(null, null), + Arguments.of("", ""), + Arguments.of("foo", "foo"), + Arguments.of("FOO", "foo"), + Arguments.of(new StringBuffer("foo"), "foo"), + Arguments.of(new StringBuffer("FOO"), "foo"), + Arguments.of(new StringBuilder("foo"), "foo"), + Arguments.of(new StringBuilder("FOO"), "foo"), + Arguments.of(new Segment("foobar".toCharArray(), 0, 3), "foo"), + Arguments.of(new Segment("FOOBAR".toCharArray(), 0, 3), "foo") + ); + } + + @ParameterizedTest + @MethodSource("charSequenceEquals_ignoringCase") + void testEqualsIgnoreCase_whenStringsAreEqualIgnoringCase_returnsTrue(CharSequence one, CharSequence two) { - assertTrue(StringUtilities.equals(null, null)); - assertFalse(StringUtilities.equals(null, "")); - assertFalse(StringUtilities.equals("", null)); - assertFalse(StringUtilities.equals("foo", "bar")); - assertFalse(StringUtilities.equals("Foo", "foo")); - assertTrue(StringUtilities.equals("foo", "foo")); + assertThat(StringUtilities.equalsIgnoreCase(one, two)).isTrue(); + } + + private static Stream charSequenceNotEqual_ignoringCase() { + return Stream.of( + Arguments.of(null, ""), + Arguments.of("", null), + Arguments.of("foo", "bar"), + Arguments.of(" foo ", "foo"), + Arguments.of(" foo ", "food"), + Arguments.of(" foo ", "foo"), + Arguments.of(new StringBuffer("foo"), "bar"), + Arguments.of(new StringBuffer("foo "), "foo"), + Arguments.of(new StringBuilder("foo"), "bar"), + Arguments.of(new StringBuilder("foo "), "foo"), + Arguments.of(new Segment("foobar".toCharArray(), 0, 3), "bar"), + Arguments.of(new Segment("foo bar".toCharArray(), 0, 4), "foo") + ); + } + + @ParameterizedTest + @MethodSource("charSequenceNotEqual_ignoringCase") + void testEqualsIgnoreCase_whenStringsAreNotEqualIgnoringCase_returnsFalse(CharSequence one, CharSequence two) + { + assertThat(StringUtilities.equalsIgnoreCase(one, two)).isFalse(); } - @Test - public void testEqualsIgnoreCase() + private static Stream charSequenceEquals_afterTrimCaseSensitive() { + return Stream.of( + Arguments.of(null, null), + Arguments.of("", ""), + Arguments.of("foo", "foo"), + Arguments.of(" foo", "foo"), + Arguments.of("foo\r\n", "foo"), + Arguments.of("foo ", "\tfoo ") + ); + } + + @ParameterizedTest + @MethodSource("charSequenceEquals_afterTrimCaseSensitive") + void testEqualsWithTrim_whenStringsAreEqual_afterTrimCaseSensitive_returnsTrue(String one, String two) + { + assertThat(StringUtilities.equalsWithTrim(one, two)).isTrue(); + } + + private static Stream charSequenceNotEqual_afterTrimCaseSensitive() { + return Stream.of( + Arguments.of(null, ""), + Arguments.of("", null), + Arguments.of("foo", "bar"), + Arguments.of("F00", "foo"), + Arguments.of("food", "foo"), + Arguments.of("foo", "food") + + ); + } + + @ParameterizedTest + @MethodSource("charSequenceNotEqual_afterTrimCaseSensitive") + void testEqualsWithTrim_whenStringsAreNotEqual_returnsFalse(String one, String two) { - assertTrue(StringUtilities.equalsIgnoreCase(null, null)); - assertFalse(StringUtilities.equalsIgnoreCase(null, "")); - assertFalse(StringUtilities.equalsIgnoreCase("", null)); - assertFalse(StringUtilities.equalsIgnoreCase("foo", "bar")); - assertTrue(StringUtilities.equalsIgnoreCase("Foo", "foo")); - assertTrue(StringUtilities.equalsIgnoreCase("foo", "foo")); + assertThat(StringUtilities.equalsWithTrim(one, two)).isFalse(); } + private static Stream charSequenceEquals_afterTrimAndIgnoringCase() { + return Stream.of( + Arguments.of(null, null), + Arguments.of("", ""), + Arguments.of("foo", "foo"), + Arguments.of(" foo", "foo"), + Arguments.of("foo\r\n", "foo"), + Arguments.of("foo ", "\tfoo "), + Arguments.of("FOO", "foo") + ); + } + + @ParameterizedTest + @MethodSource("charSequenceEquals_afterTrimAndIgnoringCase") + void testEqualsIgnoreCaseWithTrim_whenStringsAreEqual_caseSensitive_returnsTrue(String one, String two) + { + assertThat(StringUtilities.equalsIgnoreCaseWithTrim(one, two)).isTrue(); + } + + private static Stream charSequenceNotEqual_afterTrimIgnoringCase() { + return Stream.of( + Arguments.of(null, ""), + Arguments.of("", null), + Arguments.of("foo", "bar"), + Arguments.of("foo", "food") + + ); + } + + @ParameterizedTest + @MethodSource("charSequenceNotEqual_afterTrimIgnoringCase") + void testEqualsIgnoreCaseWithTrim_whenStringsAreNotEqualIgnoringCase_returnsFalse(String one, String two) + { + assertThat(StringUtilities.equalsIgnoreCaseWithTrim(one, two)).isFalse(); + } @Test - public void testLastIndexOf() + void testLastIndexOf() { assertEquals(-1, StringUtilities.lastIndexOf(null, 'a')); assertEquals(-1, StringUtilities.lastIndexOf("foo", 'a')); @@ -186,7 +446,7 @@ public void testLastIndexOf() } @Test - public void testLength() + void testLength() { assertEquals(0, StringUtilities.length("")); assertEquals(0, StringUtilities.length(null)); @@ -194,7 +454,7 @@ public void testLength() } @Test - public void testLevenshtein() + void testLevenshtein() { assertEquals(3, StringUtilities.levenshteinDistance("example", "samples")); assertEquals(6, StringUtilities.levenshteinDistance("sturgeon", "urgently")); @@ -214,7 +474,7 @@ public void testLevenshtein() } @Test - public void testDamerauLevenshtein() throws Exception + void testDamerauLevenshtein() throws Exception { assertEquals(3, StringUtilities.damerauLevenshteinDistance("example", "samples")); assertEquals(6, StringUtilities.damerauLevenshteinDistance("sturgeon", "urgently")); @@ -239,7 +499,7 @@ public void testDamerauLevenshtein() throws Exception } @Test - public void testRandomString() + void testRandomString() { Random random = new Random(42); Set strings = new TreeSet(); @@ -255,7 +515,7 @@ public void testRandomString() } } - public void testGetBytesWithInvalidEncoding() { + void testGetBytesWithInvalidEncoding() { try { StringUtilities.getBytes("foo", "foo"); @@ -267,31 +527,31 @@ public void testGetBytesWithInvalidEncoding() { } @Test - public void testGetBytes() + void testGetBytes() { assertArrayEquals(new byte[]{102, 111, 111}, StringUtilities.getBytes("foo", "UTF-8")); } @Test - public void testGetUTF8Bytes() + void testGetUTF8Bytes() { assertArrayEquals(new byte[]{102, 111, 111}, StringUtilities.getUTF8Bytes("foo")); } @Test - public void testGetBytesWithNull() + void testGetBytesWithNull() { assert StringUtilities.getBytes(null, "UTF-8") == null; } @Test - public void testGetBytesWithEmptyString() + void testGetBytesWithEmptyString() { assert DeepEquals.deepEquals(new byte[]{}, StringUtilities.getBytes("", "UTF-8")); } @Test - public void testWildcard() + void testWildcard() { String name = "George Washington"; assertTrue(name.matches(StringUtilities.wildcardToRegexString("*"))); @@ -309,37 +569,37 @@ public void testWildcard() } @Test - public void testCreateString() + void testCreateString() { assertEquals("foo", StringUtilities.createString(new byte[]{102, 111, 111}, "UTF-8")); } @Test - public void testCreateUTF8String() + void testCreateUTF8String() { assertEquals("foo", StringUtilities.createUTF8String(new byte[]{102, 111, 111})); } @Test - public void testCreateStringWithNull() + void testCreateStringWithNull() { assertNull(null, StringUtilities.createString(null, "UTF-8")); } @Test - public void testCreateStringWithEmptyArray() + void testCreateStringWithEmptyArray() { assertEquals("", StringUtilities.createString(new byte[]{}, "UTF-8")); } @Test - public void testCreateUTF8StringWithEmptyArray() + void testCreateUTF8StringWithEmptyArray() { assertEquals("", StringUtilities.createUTF8String(new byte[]{})); } @Test - public void testCreateStringWithInvalidEncoding() + void testCreateStringWithInvalidEncoding() { try { @@ -351,25 +611,25 @@ public void testCreateStringWithInvalidEncoding() } @Test - public void testCreateUtf8String() + void testCreateUtf8String() { assertEquals("foo", StringUtilities.createUtf8String(new byte[] {102, 111, 111})); } @Test - public void testCreateUtf8StringWithNull() + void testCreateUtf8StringWithNull() { assertNull(null, StringUtilities.createUtf8String(null)); } @Test - public void testCreateUtf8StringWithEmptyArray() + void testCreateUtf8StringWithEmptyArray() { assertEquals("", StringUtilities.createUtf8String(new byte[]{})); } @Test - public void testHashCodeIgnoreCase() + void testHashCodeIgnoreCase() { String s = "Hello"; String t = "HELLO"; @@ -383,7 +643,14 @@ public void testHashCodeIgnoreCase() } @Test - public void testCount2() + void testGetBytes_withInvalidEncoding_throwsException() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> StringUtilities.getBytes("Some text", "foo-bar")) + .withMessageContaining("Encoding (foo-bar) is not supported"); + } + + @Test + void testCount2() { assert 0 == StringUtilities.count("alphabet", null); assert 0 == StringUtilities.count(null, "al"); @@ -392,4 +659,138 @@ public void testCount2() assert 1 == StringUtilities.count("alphabet", "al"); assert 2 == StringUtilities.count("halal", "al"); } + + private static Stream stringsWithAllWhitespace() { + return Stream.of( + Arguments.of(" "), + Arguments.of(" \t "), + Arguments.of("\r\n ") + ); + } + + private static Stream stringsWithContentOtherThanWhitespace() { + return Stream.of( + Arguments.of("jfk"), + Arguments.of(" jfk\r\n"), + Arguments.of("\tjfk "), + Arguments.of(" jfk ") + ); + } + + @ParameterizedTest + @NullAndEmptySource + void testTrimToEmpty_whenNullOrEmpty_returnsEmptyString(String value) { + assertThat(StringUtilities.trimToEmpty(value)).isSameAs(StringUtilities.EMPTY); + } + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testTrimToEmpty_whenStringIsAllWhitespace_returnsEmptyString(String value) { + assertThat(StringUtilities.trimToEmpty(value)).isSameAs(StringUtilities.EMPTY); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testTrimToEmpty_whenStringHasContent_returnsTrimmedString(String value) { + assertThat(StringUtilities.trimToEmpty(value)).isEqualTo(value.trim()); + } + + @ParameterizedTest + @NullAndEmptySource + void testTrimToNull_whenNullOrEmpty_returnsNull(String value) { + assertThat(StringUtilities.trimToNull(value)).isNull(); + } + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testTrimToNull_whenStringIsAllWhitespace_returnsNull(String value) { + assertThat(StringUtilities.trimToNull(value)).isNull(); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testTrimToNull_whenStringHasContent_returnsTrimmedString(String value) { + assertThat(StringUtilities.trimToNull(value)).isEqualTo(value.trim()); + } + + @ParameterizedTest + @NullAndEmptySource + void testTrimToDefault_whenNullOrEmpty_returnsDefault(String value) { + assertThat(StringUtilities.trimEmptyToDefault(value, "foo")).isEqualTo("foo"); + } + + @ParameterizedTest + @MethodSource("stringsWithAllWhitespace") + void testTrimToDefault_whenStringIsAllWhitespace_returnsDefault(String value) { + assertThat(StringUtilities.trimEmptyToDefault(value, "foo")).isEqualTo("foo"); + } + + @ParameterizedTest + @MethodSource("stringsWithContentOtherThanWhitespace") + void testTrimToDefault_whenStringHasContent_returnsTrimmedString(String value) { + assertThat(StringUtilities.trimEmptyToDefault(value, "foo")).isEqualTo(value.trim()); + } + + + private static Stream regionMatches_returnsTrue() { + return Stream.of( + Arguments.of("a", true, 0, "abc", 0, 0), + Arguments.of("a", true, 0, "abc", 0, 1), + Arguments.of("Abc", true, 0, "abc", 0, 3), + Arguments.of("Abc", true, 1, "abc", 1, 2), + Arguments.of("Abc", false, 1, "abc", 1, 2), + Arguments.of("Abcd", true, 1, "abcD", 1, 2), + Arguments.of("Abcd", false, 1, "abcD", 1, 2), + Arguments.of(new StringBuilder("a"), true, 0, new StringBuffer("abc"), 0, 0), + Arguments.of(new StringBuilder("a"), true, 0, new StringBuffer("abc"), 0, 1), + Arguments.of(new StringBuilder("Abc"), true, 0, new StringBuffer("abc"), 0, 3), + Arguments.of(new StringBuilder("Abc"), true, 1, new StringBuffer("abc"), 1, 2), + Arguments.of(new StringBuilder("Abc"), false, 1, new StringBuffer("abc"), 1, 2), + Arguments.of(new StringBuilder("Abcd"), true, 1, new StringBuffer("abcD"), 1, 2), + Arguments.of(new StringBuilder("Abcd"), false, 1, new StringBuffer("abcD"), 1, 2) + + ); + } + @ParameterizedTest + @MethodSource("regionMatches_returnsTrue") + void testRegionMatches_returnsTrue(CharSequence s, boolean ignoreCase, int start, CharSequence substring, int subStart, int length) { + boolean matches = StringUtilities.regionMatches(s, ignoreCase, start, substring, subStart, length); + assertThat(matches).isTrue(); + } + + private static Stream regionMatches_returnsFalse() { + return Stream.of( + Arguments.of("", true, -1, "", -1, -1), + Arguments.of("", true, 0, "", 0, 1), + Arguments.of("Abc", false, 0, "abc", 0, 3), + Arguments.of(new StringBuilder(""), true, -1, new StringBuffer(""), -1, -1), + Arguments.of(new StringBuilder(""), true, 0, new StringBuffer(""), 0, 1), + Arguments.of(new StringBuilder("Abc"), false, 0, new StringBuffer("abc"), 0, 3) + ); + } + + @ParameterizedTest + @MethodSource("regionMatches_returnsFalse") + void testRegionMatches_returnsFalse(CharSequence s, boolean ignoreCase, int start, CharSequence substring, int subStart, int length) { + boolean matches = StringUtilities.regionMatches(s, ignoreCase, start, substring, subStart, length); + assertThat(matches).isFalse(); + } + + + private static Stream regionMatches_throwsNullPointerException() { + return Stream.of( + Arguments.of("a", true, 0, null, 0, 0, "substring cannot be null"), + Arguments.of(null, true, 0, null, 0, 0, "cs to be processed cannot be null"), + Arguments.of(null, true, 0, "", 0, 0, "cs to be processed cannot be null") + ); + } + + @ParameterizedTest + @MethodSource("regionMatches_throwsNullPointerException") + void testRegionMatches_withStrings_throwsIllegalArgumentException(CharSequence s, boolean ignoreCase, int start, CharSequence substring, int subStart, int length, String exText) { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> StringUtilities.regionMatches(s, ignoreCase, start, substring, subStart, length)) + .withMessageContaining(exText); + } + } diff --git a/src/test/java/com/cedarsoftware/util/convert/AtomicBooleanConversionsTests.java b/src/test/java/com/cedarsoftware/util/convert/AtomicBooleanConversionsTests.java new file mode 100644 index 00000000..e574e5b2 --- /dev/null +++ b/src/test/java/com/cedarsoftware/util/convert/AtomicBooleanConversionsTests.java @@ -0,0 +1,210 @@ +package com.cedarsoftware.util.convert; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AtomicBooleanConversionsTests { + + private static Stream toByteParams() { + return Stream.of( + Arguments.of(true, CommonValues.BYTE_ONE), + Arguments.of(false, CommonValues.BYTE_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toByteParams") + void testToByte(boolean value, Byte expected) { + Byte actual = AtomicBooleanConversions.toByte(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toShortParams() { + return Stream.of( + Arguments.of(true, CommonValues.SHORT_ONE), + Arguments.of(false, CommonValues.SHORT_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toShortParams") + void testToShort(boolean value, Short expected) { + Short actual = AtomicBooleanConversions.toShort(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toIntegerParams() { + return Stream.of( + Arguments.of(true, CommonValues.INTEGER_ONE), + Arguments.of(false, CommonValues.INTEGER_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toIntegerParams") + void testToInteger(boolean value, Integer expected) { + Integer actual = AtomicBooleanConversions.toInteger(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toLongParams() { + return Stream.of( + Arguments.of(true, CommonValues.LONG_ONE), + Arguments.of(false, CommonValues.LONG_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toLongParams") + void testToLong(boolean value, long expected) { + long actual = AtomicBooleanConversions.toLong(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toFloatParams() { + return Stream.of( + Arguments.of(true, CommonValues.FLOAT_ONE), + Arguments.of(false, CommonValues.FLOAT_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toFloatParams") + void testToFloat(boolean value, Float expected) { + Float actual = AtomicBooleanConversions.toFloat(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + + private static Stream toDoubleParams() { + return Stream.of( + Arguments.of(true, CommonValues.DOUBLE_ONE), + Arguments.of(false, CommonValues.DOUBLE_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toDoubleParams") + void testToDouble(boolean value, Double expected) { + Double actual = AtomicBooleanConversions.toDouble(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + + private static Stream toBooleanParams() { + return Stream.of( + Arguments.of(true), + Arguments.of(false) + ); + } + + @ParameterizedTest + @MethodSource("toBooleanParams") + void testToBoolean(boolean value) { + boolean actual = AtomicBooleanConversions.toBoolean(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(Boolean.valueOf(value)); + } + + @ParameterizedTest + @MethodSource("toIntegerParams") + void testToAtomicInteger(boolean value, int integer) { + AtomicInteger expected = new AtomicInteger(integer);; + AtomicInteger actual = AtomicBooleanConversions.toAtomicInteger(new AtomicBoolean(value), null, null); + assertThat(actual.get()).isEqualTo(expected.get()); + } + + @ParameterizedTest + @MethodSource("toLongParams") + void testToAtomicLong(boolean value, long expectedLong) { + AtomicLong expected = new AtomicLong(expectedLong); + AtomicLong actual = AtomicBooleanConversions.toAtomicLong(new AtomicBoolean(value), null, null); + assertThat(actual.get()).isEqualTo(expected.get()); + } + + private static Stream toCharacter_withDefaultParams() { + return Stream.of( + Arguments.of(true, CommonValues.CHARACTER_ONE), + Arguments.of(false, CommonValues.CHARACTER_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toCharacter_withDefaultParams") + void testToCharacter_withDefaultParams(boolean value, char expected) { + ConverterOptions options = createConvertOptions(CommonValues.CHARACTER_ONE, CommonValues.CHARACTER_ZERO); + Character actual = AtomicBooleanConversions.toCharacter(new AtomicBoolean(value), null, options); + assertThat(actual).isSameAs(expected); + } + + private static Stream toCharacterCustomParams() { + return Stream.of( + Arguments.of('T', 'F', true, 'T'), + Arguments.of('T', 'F', false, 'F') + ); + } + + + @ParameterizedTest + @MethodSource("toCharacterCustomParams") + void testToCharacter_withCustomChars(char trueChar, char falseChar, boolean value, char expected) { + ConverterOptions options = createConvertOptions(trueChar, falseChar); + char actual = BooleanConversions.toCharacter(value, null, options); + assertThat(actual).isEqualTo(expected); + } + + + private static Stream toBigDecimalParams() { + return Stream.of( + Arguments.of(true, BigDecimal.ONE), + Arguments.of(false, BigDecimal.ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toBigDecimalParams") + void testToBigDecimal(boolean value, BigDecimal expected) { + BigDecimal actual = AtomicBooleanConversions.toBigDecimal(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toBigIntegerParams() { + return Stream.of( + Arguments.of(true, BigInteger.ONE), + Arguments.of(false, BigInteger.ZERO) + ); + } + @ParameterizedTest + @MethodSource("toBigIntegerParams") + void testToBigDecimal(boolean value, BigInteger expected) { + BigInteger actual = AtomicBooleanConversions.toBigInteger(new AtomicBoolean(value), null, null); + assertThat(actual).isSameAs(expected); + } + + private ConverterOptions createConvertOptions(final char t, final char f) + { + return new ConverterOptions() { + @Override + public T getCustomOption(String name) { + return null; + } + + @Override + public Character trueChar() { return t; } + + @Override + public Character falseChar() { return f; } + }; + } +} + diff --git a/src/test/java/com/cedarsoftware/util/convert/BooleanConversionsTests.java b/src/test/java/com/cedarsoftware/util/convert/BooleanConversionsTests.java new file mode 100644 index 00000000..208b0c72 --- /dev/null +++ b/src/test/java/com/cedarsoftware/util/convert/BooleanConversionsTests.java @@ -0,0 +1,229 @@ +package com.cedarsoftware.util.convert; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.math.BigDecimal; +import java.math.BigInteger; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class BooleanConversionsTests { + + + @Test + public void testClassCompliance() throws Exception { + Class c = BooleanConversions.class; + assertEquals(Modifier.FINAL, c.getModifiers() & Modifier.FINAL); + + Constructor con = c.getDeclaredConstructor(); + assertEquals(Modifier.PRIVATE, con.getModifiers() & Modifier.PRIVATE); + + con.setAccessible(true); + assertNotNull(con.newInstance()); + } + + private static Stream toByteParams() { + return Stream.of( + Arguments.of(true, CommonValues.BYTE_ONE), + Arguments.of(false, CommonValues.BYTE_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toByteParams") + void testToByte(boolean value, Byte expected) { + Byte actual = BooleanConversions.toByte(value, null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toShortParams() { + return Stream.of( + Arguments.of(true, CommonValues.SHORT_ONE), + Arguments.of(false, CommonValues.SHORT_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toShortParams") + void testToShort(boolean value, Short expected) { + Short actual = BooleanConversions.toShort(value, null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toIntegerParams() { + return Stream.of( + Arguments.of(true, CommonValues.INTEGER_ONE), + Arguments.of(false, CommonValues.INTEGER_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toIntegerParams") + void testToInteger(boolean value, Integer expected) { + Integer actual = BooleanConversions.toInteger(value, null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toLongParams() { + return Stream.of( + Arguments.of(true, CommonValues.LONG_ONE), + Arguments.of(false, CommonValues.LONG_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toLongParams") + void testToLong(boolean value, long expected) { + long actual = BooleanConversions.toLong(value, null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toFloatParams() { + return Stream.of( + Arguments.of(true, CommonValues.FLOAT_ONE), + Arguments.of(false, CommonValues.FLOAT_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toFloatParams") + void testToFloat(boolean value, Float expected) { + Float actual = BooleanConversions.toFloat(value, null, null); + assertThat(actual).isSameAs(expected); + } + + + private static Stream toDoubleParams() { + return Stream.of( + Arguments.of(true, CommonValues.DOUBLE_ONE), + Arguments.of(false, CommonValues.DOUBLE_ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toDoubleParams") + void testToDouble(boolean value, Double expected) { + Double actual = BooleanConversions.toDouble(value, null, null); + assertThat(actual).isSameAs(expected); + } + + + private static Stream toBooleanParams() { + return Stream.of( + Arguments.of(true), + Arguments.of(false) + ); + } + + @ParameterizedTest + @MethodSource("toBooleanParams") + void testToAtomicBoolean(boolean value) { + AtomicBoolean expected = new AtomicBoolean(value);; + AtomicBoolean actual = BooleanConversions.toAtomicBoolean(value, null, null); + assertThat(actual.get()).isEqualTo(expected.get()); + } + + @ParameterizedTest + @MethodSource("toIntegerParams") + void testToAtomicInteger(boolean value, int integer) { + AtomicInteger expected = new AtomicInteger(integer);; + AtomicInteger actual = BooleanConversions.toAtomicInteger(value, null, null); + assertThat(actual.get()).isEqualTo(expected.get()); + } + + @ParameterizedTest + @MethodSource("toLongParams") + void testToAtomicLong(boolean value, long expectedLong) { + AtomicLong expected = new AtomicLong(expectedLong); + AtomicLong actual = BooleanConversions.toAtomicLong(value, null, null); + assertThat(actual.get()).isEqualTo(expected.get()); + } + + private static Stream toCharacterDefaultParams() { + return Stream.of( + Arguments.of(true, CommonValues.CHARACTER_ONE), + Arguments.of(false, CommonValues.CHARACTER_ZERO) + ); + } + + + @ParameterizedTest + @MethodSource("toCharacterDefaultParams") + void testToCharacter_withDefaultChars(boolean value, char expected) { + ConverterOptions options = createConvertOptions(CommonValues.CHARACTER_ONE, CommonValues.CHARACTER_ZERO); + Character actual = BooleanConversions.toCharacter(value, null, options); + assertThat(actual).isSameAs(expected); + } + + private static Stream toCharacterCustomParams() { + return Stream.of( + Arguments.of('T', 'F', true, 'T'), + Arguments.of('T', 'F', false, 'F') + ); + } + + + @ParameterizedTest + @MethodSource("toCharacterCustomParams") + void testToCharacter_withCustomChars(char trueChar, char falseChar, boolean value, char expected) { + ConverterOptions options = createConvertOptions(trueChar, falseChar); + char actual = BooleanConversions.toCharacter(value, null, options); + assertThat(actual).isEqualTo(expected); + } + + private static Stream toBigDecimalParams() { + return Stream.of( + Arguments.of(true, BigDecimal.ONE), + Arguments.of(false, BigDecimal.ZERO) + ); + } + + @ParameterizedTest + @MethodSource("toBigDecimalParams") + void testToBigDecimal(boolean value, BigDecimal expected) { + BigDecimal actual = BooleanConversions.toBigDecimal(value, null, null); + assertThat(actual).isSameAs(expected); + } + + private static Stream toBigIntegerParams() { + return Stream.of( + Arguments.of(true, BigInteger.ONE), + Arguments.of(false, BigInteger.ZERO) + ); + } + @ParameterizedTest + @MethodSource("toBigIntegerParams") + void testToBigDecimal(boolean value, BigInteger expected) { + BigInteger actual = BooleanConversions.toBigInteger(value, null, null); + assertThat(actual).isSameAs(expected); + } + + private ConverterOptions createConvertOptions(final char t, final char f) + { + return new ConverterOptions() { + @Override + public T getCustomOption(String name) { + return null; + } + + @Override + public Character trueChar() { return t; } + + @Override + public Character falseChar() { return f; } + }; + } +} + diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java index d7767f0f..0144f4cc 100644 --- a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java +++ b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java @@ -1786,84 +1786,65 @@ void testBogusSqlDate2() .hasMessageContaining("Unsupported conversion, source type [Boolean (true)] target type 'java.sql.Date'"); } - @Test - void testCalendar() - { - // Date to Calendar - Date now = new Date(); - Calendar calendar = this.converter.convert(new Date(), Calendar.class); - assertEquals(calendar.getTime(), now); - - // SqlDate to Calendar - java.sql.Date sqlDate = this.converter.convert(now, java.sql.Date.class); - calendar = this.converter.convert(sqlDate, Calendar.class); - assertEquals(calendar.getTime(), sqlDate); - - // Timestamp to Calendar - Timestamp timestamp = this.converter.convert(now, Timestamp.class); - calendar = this.converter.convert(timestamp, Calendar.class); - assertEquals(calendar.getTime(), timestamp); - - // Long to Calendar - calendar = this.converter.convert(now.getTime(), Calendar.class); - assertEquals(calendar.getTime(), now); - - // AtomicLong to Calendar - AtomicLong atomicLong = new AtomicLong(now.getTime()); - calendar = this.converter.convert(atomicLong, Calendar.class); - assertEquals(calendar.getTime(), now); - - // String to Calendar - String strDate = this.converter.convert(now, String.class); - calendar = this.converter.convert(strDate, Calendar.class); - String strDate2 = this.converter.convert(calendar, String.class); - assertEquals(strDate, strDate2); - - // BigInteger to Calendar - BigInteger bigInt = new BigInteger("" + now.getTime()); - calendar = this.converter.convert(bigInt, Calendar.class); - assertEquals(calendar.getTime(), now); - - // BigDecimal to Calendar - BigDecimal bigDec = new BigDecimal(now.getTime()); - calendar = this.converter.convert(bigDec, Calendar.class); - assertEquals(calendar.getTime(), now); - - // Other direction --> Calendar to other date types - - // Calendar to Date - calendar = this.converter.convert(now, Calendar.class); - Date date = this.converter.convert(calendar, Date.class); - assertEquals(calendar.getTime(), date); - - // Calendar to SqlDate - sqlDate = this.converter.convert(calendar, java.sql.Date.class); - assertEquals(calendar.getTime().getTime(), sqlDate.getTime()); - - // Calendar to Timestamp - timestamp = this.converter.convert(calendar, Timestamp.class); - assertEquals(calendar.getTime().getTime(), timestamp.getTime()); - - // Calendar to Long - long tnow = this.converter.convert(calendar, long.class); - assertEquals(calendar.getTime().getTime(), tnow); - - // Calendar to AtomicLong - atomicLong = this.converter.convert(calendar, AtomicLong.class); - assertEquals(calendar.getTime().getTime(), atomicLong.get()); + private static Stream toCalendarParams() { + return Stream.of( + Arguments.of(new Date(1687622249729L)), + Arguments.of(new java.sql.Date(1687622249729L)), + Arguments.of(new Timestamp(1687622249729L)), + Arguments.of(Instant.ofEpochMilli(1687622249729L)), + Arguments.of(1687622249729L), + Arguments.of(BigInteger.valueOf(1687622249729L)), + Arguments.of(BigDecimal.valueOf(1687622249729L)), + Arguments.of("1687622249729"), + Arguments.of(new AtomicLong(1687622249729L)) + ); + } - // Calendar to String - strDate = this.converter.convert(calendar, String.class); - strDate2 = this.converter.convert(now, String.class); - assertEquals(strDate, strDate2); + @ParameterizedTest + @MethodSource("toCalendarParams") + void toCalendar(Object source) + { + Long epochMilli = 1687622249729L; - // Calendar to BigInteger - bigInt = this.converter.convert(calendar, BigInteger.class); - assertEquals(now.getTime(), bigInt.longValue()); + Calendar calendar = this.converter.convert(source, Calendar.class); + assertEquals(calendar.getTime().getTime(), epochMilli); - // Calendar to BigDecimal - bigDec = this.converter.convert(calendar, BigDecimal.class); - assertEquals(now.getTime(), bigDec.longValue()); +// // BigInteger to Calendar +// // Other direction --> Calendar to other date types +// +// // Calendar to Date +// calendar = this.converter.convert(now, Calendar.class); +// Date date = this.converter.convert(calendar, Date.class); +// assertEquals(calendar.getTime(), date); +// +// // Calendar to SqlDate +// sqlDate = this.converter.convert(calendar, java.sql.Date.class); +// assertEquals(calendar.getTime().getTime(), sqlDate.getTime()); +// +// // Calendar to Timestamp +// timestamp = this.converter.convert(calendar, Timestamp.class); +// assertEquals(calendar.getTime().getTime(), timestamp.getTime()); +// +// // Calendar to Long +// long tnow = this.converter.convert(calendar, long.class); +// assertEquals(calendar.getTime().getTime(), tnow); +// +// // Calendar to AtomicLong +// atomicLong = this.converter.convert(calendar, AtomicLong.class); +// assertEquals(calendar.getTime().getTime(), atomicLong.get()); +// +// // Calendar to String +// strDate = this.converter.convert(calendar, String.class); +// strDate2 = this.converter.convert(now, String.class); +// assertEquals(strDate, strDate2); +// +// // Calendar to BigInteger +// bigInt = this.converter.convert(calendar, BigInteger.class); +// assertEquals(now.getTime(), bigInt.longValue()); +// +// // Calendar to BigDecimal +// bigDec = this.converter.convert(calendar, BigDecimal.class); +// assertEquals(now.getTime(), bigDec.longValue()); } @@ -2337,7 +2318,7 @@ void testMapToAtomicBoolean() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, AtomicBoolean.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("the map must include keys: '_v' or 'value'"); + .hasMessageContaining("To convert from Map to AtomicBoolean the map must include one of the following"); } @Test @@ -2360,21 +2341,21 @@ void testMapToAtomicInteger() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, AtomicInteger.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("the map must include keys: '_v' or 'value'"); + .hasMessageContaining("To convert from Map to AtomicInteger the map must include one of the following"); } @Test void testMapToAtomicLong() { final Map map = new HashMap(); - map.put("value", 58); - AtomicLong al = this.converter.convert(map, AtomicLong.class); - assert 58 == al.get(); - - map.clear(); - map.put("value", ""); - al = this.converter.convert(map, AtomicLong.class); - assert 0L == al.longValue(); +// map.put("value", 58); +// AtomicLong al = this.converter.convert(map, AtomicLong.class); +// assert 58 == al.get(); +// +// map.clear(); +// map.put("value", ""); +// al = this.converter.convert(map, AtomicLong.class); +// assert 0L == al.longValue(); map.clear(); map.put("value", null); @@ -2383,17 +2364,21 @@ void testMapToAtomicLong() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, AtomicLong.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("the map must include keys: '_v' or 'value'"); + .hasMessageContaining("To convert from Map to AtomicLong the map must include one of the following"); } - @Test - void testMapToCalendar() + + + + @ParameterizedTest + @MethodSource("toCalendarParams") + void testMapToCalendar(Object value) { - long now = System.currentTimeMillis(); final Map map = new HashMap(); - map.put("value", new Date(now)); + map.put("value", value); + Calendar cal = this.converter.convert(map, Calendar.class); - assert now == cal.getTimeInMillis(); + assertThat(cal).isNotNull(); map.clear(); map.put("value", ""); @@ -2487,7 +2472,7 @@ void testMapToDate() { map.clear(); assertThatThrownBy(() -> this.converter.convert(map, Date.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("the map must include keys: [time], or '_v' or 'value'"); + .hasMessageContaining("To convert from Map to Date the map must include one of the following"); } @Test @@ -2510,7 +2495,7 @@ void testMapToSqlDate() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, java.sql.Date.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("map must include keys"); + .hasMessageContaining("To convert from Map to java.sql.Date the map must include"); } @Test @@ -2533,7 +2518,7 @@ void testMapToTimestamp() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, Timestamp.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("the map must include keys: [time, nanos], or '_v' or 'value'"); + .hasMessageContaining("To convert from Map to Timestamp the map must include one of the following"); } @Test @@ -2556,7 +2541,7 @@ void testMapToLocalDate() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, LocalDate.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Map to LocalDate, the map must include keys: [year, month, day], or '_v' or 'value'"); + .hasMessageContaining("To convert from Map to LocalDate, the map must include"); } @Test @@ -2579,7 +2564,7 @@ void testMapToLocalDateTime() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, LocalDateTime.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Map to LocalDateTime, the map must include keys: '_v' or 'value'"); + .hasMessageContaining("To convert from Map to LocalDateTime, the map must include"); } @Test @@ -2598,7 +2583,7 @@ void testMapToZonedDateTime() map.clear(); assertThatThrownBy(() -> this.converter.convert(map, ZonedDateTime.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Map to ZonedDateTime, the map must include keys: '_v' or 'value'"); + .hasMessageContaining("To convert from Map to ZonedDateTime, the map must include"); } @@ -2968,7 +2953,7 @@ void testBadMapToUUID() map.put("leastSigBits", uuid.getLeastSignificantBits()); assertThatThrownBy(() -> this.converter.convert(map, UUID.class)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("To convert Map to UUID, the Map must contain both 'mostSigBits' and 'leastSigBits' keys"); + .hasMessageContaining("To convert from Map to UUID the map must include one of the following"); } @Test @@ -3298,8 +3283,6 @@ void testIsConversionSupport() { assert this.converter.isConversionSupportedFor(int.class, LocalDate.class); assert this.converter.isConversionSupportedFor(Integer.class, LocalDate.class); - assert this.converter.isConversionSupportedFor(LocalDate.class, int.class); - assert this.converter.isConversionSupportedFor(LocalDate.class, Integer.class); assert !this.converter.isDirectConversionSupportedFor(byte.class, LocalDate.class); assert this.converter.isConversionSupportedFor(byte.class, LocalDate.class); // byte is upgraded to Byte, which is found as Number. From 69fd6707a0f575d804b12797878c94f1f6fcaf9d Mon Sep 17 00:00:00 2001 From: Ken Partlow Date: Thu, 25 Jan 2024 00:46:15 -0500 Subject: [PATCH 2/6] Changed check from isSameAs to isEqualTo --- src/test/java/com/cedarsoftware/util/TestStringUtilities.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/cedarsoftware/util/TestStringUtilities.java b/src/test/java/com/cedarsoftware/util/TestStringUtilities.java index bb44b3af..c55f97a2 100644 --- a/src/test/java/com/cedarsoftware/util/TestStringUtilities.java +++ b/src/test/java/com/cedarsoftware/util/TestStringUtilities.java @@ -680,13 +680,13 @@ private static Stream stringsWithContentOtherThanWhitespace() { @ParameterizedTest @NullAndEmptySource void testTrimToEmpty_whenNullOrEmpty_returnsEmptyString(String value) { - assertThat(StringUtilities.trimToEmpty(value)).isSameAs(StringUtilities.EMPTY); + assertThat(StringUtilities.trimToEmpty(value)).isEqualTo(StringUtilities.EMPTY); } @ParameterizedTest @MethodSource("stringsWithAllWhitespace") void testTrimToEmpty_whenStringIsAllWhitespace_returnsEmptyString(String value) { - assertThat(StringUtilities.trimToEmpty(value)).isSameAs(StringUtilities.EMPTY); + assertThat(StringUtilities.trimToEmpty(value)).isEqualTo(StringUtilities.EMPTY); } @ParameterizedTest From b6bc1c01524ddfb59c865ea1343b20a56c16e261 Mon Sep 17 00:00:00 2001 From: Ken Partlow Date: Thu, 25 Jan 2024 13:27:15 -0500 Subject: [PATCH 3/6] Updated LocalDateConversions --- .../util/convert/CalendarConversions.java | 5 + .../cedarsoftware/util/convert/Converter.java | 36 +- .../util/convert/DateConversions.java | 5 + .../util/convert/InstantConversions.java | 4 + .../util/convert/LocalDateConversions.java | 13 +- .../convert/LocalDateTimeConversions.java | 18 +- .../util/convert/NumberConversions.java | 19 +- .../util/convert/ConverterTest.java | 348 ++++++++++++++---- 8 files changed, 372 insertions(+), 76 deletions(-) diff --git a/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java b/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java index bef02a73..5cc42f64 100644 --- a/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java @@ -6,6 +6,7 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; @@ -71,6 +72,10 @@ static LocalDate toLocalDate(Object fromInstance, Converter converter, Converter return toZonedDateTime(fromInstance, options).toLocalDate(); } + static LocalTime toLocalTime(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalTime(); + } + static BigDecimal toBigDecimal(Object fromInstance, Converter converter, ConverterOptions options) { return BigDecimal.valueOf(toLong(fromInstance)); } diff --git a/src/main/java/com/cedarsoftware/util/convert/Converter.java b/src/main/java/com/cedarsoftware/util/convert/Converter.java index cd6aef13..533bc69b 100644 --- a/src/main/java/com/cedarsoftware/util/convert/Converter.java +++ b/src/main/java/com/cedarsoftware/util/convert/Converter.java @@ -36,6 +36,7 @@ import com.cedarsoftware.util.ClassUtilities; import com.cedarsoftware.util.CollectionUtilities; import com.cedarsoftware.util.DateUtilities; +import com.cedarsoftware.util.StringUtilities; /** * Instance conversion utility. Convert from primitive to other primitives, plus support for Number, Date, @@ -229,7 +230,7 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Double.class, Double.class), Converter::identity); DEFAULT_FACTORY.put(pair(Boolean.class, Double.class), BooleanConversions::toDouble); DEFAULT_FACTORY.put(pair(Character.class, Double.class), CharacterConversions::toDouble); - DEFAULT_FACTORY.put(pair(Instant.class, Double.class), InstantConversions::toLong); + DEFAULT_FACTORY.put(pair(Instant.class, Double.class), InstantConversions::toDouble); DEFAULT_FACTORY.put(pair(LocalDate.class, Double.class), LocalDateConversions::toLong); DEFAULT_FACTORY.put(pair(LocalDateTime.class, Double.class), LocalDateTimeConversions::toLong); DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Double.class), ZonedDateTimeConversions::toLong); @@ -607,6 +608,36 @@ private static void buildFactoryConversions() { return date.toInstant().atZone(options.getZoneId()).toLocalDateTime(); }); + DEFAULT_FACTORY.put(pair(Void.class, LocalTime.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Long.class, LocalTime.class), NumberConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Double.class, LocalTime.class), NumberConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(BigInteger.class, LocalTime.class), NumberConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(BigDecimal.class, LocalTime.class), NumberConversions::toLocalDateTime); + DEFAULT_FACTORY.put(pair(AtomicLong.class, LocalTime.class), NumberConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(java.sql.Date.class, LocalTime.class), DateConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Timestamp.class, LocalTime.class), DateConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Date.class, LocalTime.class), DateConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Instant.class, LocalTime.class), InstantConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalTime.class), LocalDateTimeConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(LocalDate.class, LocalTime.class), LocalDateConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(LocalTime.class, LocalTime.class), Converter::identity); + DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalTime.class), ZonedDateTimeConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Calendar.class, LocalTime.class), CalendarConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Number.class, LocalTime.class), NumberConversions::toLocalTime); + DEFAULT_FACTORY.put(pair(Map.class, LocalTime.class), (fromInstance, converter, options) -> { + Map map = (Map) fromInstance; + return converter.fromValueMap(map, LocalTime.class, null, options); + }); + DEFAULT_FACTORY.put(pair(String.class, LocalTime.class), (fromInstance, converter, options) -> { + String str = StringUtilities.trimToEmpty((String)fromInstance); + Date date = DateUtilities.parseDate(str); + if (date == null) { + return null; + } + return converter.convert(date, LocalTime.class, options); + }); + + // ZonedDateTime conversions supported DEFAULT_FACTORY.put(pair(Void.class, ZonedDateTime.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(Long.class, ZonedDateTime.class), NumberConversions::toZonedDateTime); @@ -617,6 +648,7 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(java.sql.Date.class, ZonedDateTime.class), DateConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(Timestamp.class, ZonedDateTime.class), DateConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(Date.class, ZonedDateTime.class), DateConversions::toZonedDateTime); + DEFAULT_FACTORY.put(pair(Instant.class, ZonedDateTime.class), InstantConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(LocalDate.class, ZonedDateTime.class), LocalDateConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(LocalDateTime.class, ZonedDateTime.class), LocalDateTimeConversions::toZonedDateTime); DEFAULT_FACTORY.put(pair(ZonedDateTime.class, ZonedDateTime.class), Converter::identity); @@ -632,7 +664,7 @@ private static void buildFactoryConversions() { if (date == null) { return null; } - return date.toInstant().atZone(options.getZoneId()); + return converter.convert(date, ZonedDateTime.class, options); }); // UUID conversions supported diff --git a/src/main/java/com/cedarsoftware/util/convert/DateConversions.java b/src/main/java/com/cedarsoftware/util/convert/DateConversions.java index d648dae4..0c733564 100644 --- a/src/main/java/com/cedarsoftware/util/convert/DateConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/DateConversions.java @@ -6,6 +6,7 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; @@ -88,6 +89,10 @@ static LocalDate toLocalDate(Object fromInstance, Converter converter, Converter return toZonedDateTime(fromInstance, options).toLocalDate(); } + static LocalTime toLocalTime(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalTime(); + } + static BigInteger toBigInteger(Object fromInstance, Converter converter, ConverterOptions options) { return BigInteger.valueOf(toLong(fromInstance)); } diff --git a/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java b/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java index 581d84ac..06ef1184 100644 --- a/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/InstantConversions.java @@ -62,6 +62,10 @@ static BigDecimal toBigDecimal(Object from, Converter converter, ConverterOption return BigDecimal.valueOf(toLong(from)); } + static ZonedDateTime toZonedDateTime(Object from, Converter converter, ConverterOptions options) { + return toZonedDateTime(from, options); + } + static LocalDateTime toLocalDateTime(Object from, Converter converter, ConverterOptions options) { return toZonedDateTime(from, options).toLocalDateTime(); } diff --git a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java index 5e054c67..c5931025 100644 --- a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java @@ -6,15 +6,17 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.concurrent.atomic.AtomicLong; public class LocalDateConversions { private static ZonedDateTime toZonedDateTime(Object fromInstance, ConverterOptions options) { - return ((LocalDate)fromInstance).atStartOfDay(options.getZoneId()); + return ((LocalDate)fromInstance).atStartOfDay(options.getSourceZoneIdForLocalDates()).withZoneSameInstant(options.getZoneId()); } static Instant toInstant(Object fromInstance, ConverterOptions options) { @@ -29,6 +31,10 @@ static LocalDateTime toLocalDateTime(Object fromInstance, Converter converter, C return toZonedDateTime(fromInstance, options).toLocalDateTime(); } + static LocalTime toLocalTime(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalTime(); + } + static ZonedDateTime toZonedDateTime(Object fromInstance, Converter converter, ConverterOptions options) { return toZonedDateTime(fromInstance, options).withZoneSameInstant(options.getZoneId()); } @@ -60,7 +66,10 @@ static Timestamp toTimestamp(Object fromInstance, Converter converter, Converter } static Calendar toCalendar(Object fromInstance, Converter converter, ConverterOptions options) { - return CalendarConversions.create(toLong(fromInstance, options), options); + ZonedDateTime time = toZonedDateTime(fromInstance, options); + GregorianCalendar calendar = new GregorianCalendar(options.getTimeZone()); + calendar.setTimeInMillis(time.toInstant().toEpochMilli()); + return calendar; } static java.sql.Date toSqlDate(Object fromInstance, Converter converter, ConverterOptions options) { diff --git a/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java b/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java index 86940ae5..d98a2e0c 100644 --- a/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/LocalDateTimeConversions.java @@ -4,7 +4,9 @@ import java.math.BigInteger; import java.sql.Timestamp; import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; @@ -13,7 +15,7 @@ public class LocalDateTimeConversions { private static ZonedDateTime toZonedDateTime(Object fromInstance, ConverterOptions options) { - return ((LocalDateTime)fromInstance).atZone(options.getSourceZoneIdForLocalDates()); + return ((LocalDateTime)fromInstance).atZone(options.getSourceZoneIdForLocalDates()).withZoneSameInstant(options.getZoneId()); } private static Instant toInstant(Object fromInstance, ConverterOptions options) { @@ -25,7 +27,19 @@ private static long toLong(Object fromInstance, ConverterOptions options) { } static ZonedDateTime toZonedDateTime(Object fromInstance, Converter converter, ConverterOptions options) { - return toZonedDateTime(fromInstance, options).withZoneSameInstant(options.getZoneId()); + return toZonedDateTime(fromInstance, options); + } + + static LocalDateTime toLocalDateTime(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalDateTime(); + } + + static LocalDate toLocalDate(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalDate(); + } + + static LocalTime toLocalTime(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalTime(); } static Instant toInstant(Object fromInstance, Converter converter, ConverterOptions options) { diff --git a/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java b/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java index 22abc99e..2e163243 100644 --- a/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/NumberConversions.java @@ -6,6 +6,7 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; @@ -187,8 +188,10 @@ static Date toDate(Object from, Converter converter, ConverterOptions options) { return new Date(toLong(from)); } + static Instant toInstant(Object from) { return Instant.ofEpochMilli(toLong(from)); } + static Instant toInstant(Object from, Converter converter, ConverterOptions options) { - return Instant.ofEpochMilli(toLong(from)); + return toInstant(from); } static java.sql.Date toSqlDate(Object from, Converter converter, ConverterOptions options) { @@ -204,14 +207,22 @@ static Calendar toCalendar(Object from, Converter converter, ConverterOptions op } static LocalDate toLocalDate(Object from, Converter converter, ConverterOptions options) { - return Instant.ofEpochMilli(toLong(from)).atZone(options.getZoneId()).toLocalDate(); + return toZonedDateTime(from, options).toLocalDate(); } static LocalDateTime toLocalDateTime(Object from, Converter converter, ConverterOptions options) { - return Instant.ofEpochMilli(toLong(from)).atZone(options.getZoneId()).toLocalDateTime(); + return toZonedDateTime(from, options).toLocalDateTime(); + } + + static LocalTime toLocalTime(Object from, Converter converter, ConverterOptions options) { + return toZonedDateTime(from, options).toLocalTime(); + } + + static ZonedDateTime toZonedDateTime(Object from, ConverterOptions options) { + return toInstant(from).atZone(options.getZoneId()); } static ZonedDateTime toZonedDateTime(Object from, Converter converter, ConverterOptions options) { - return Instant.ofEpochMilli(toLong(from)).atZone(options.getZoneId()); + return toZonedDateTime(from, options); } } diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java index 0144f4cc..4b4be2a1 100644 --- a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java +++ b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java @@ -6,6 +6,7 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Calendar; @@ -22,7 +23,6 @@ import java.util.stream.Stream; import com.cedarsoftware.util.DeepEquals; -import com.cedarsoftware.util.TestUtil; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -32,8 +32,6 @@ import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.NullSource; -import static com.cedarsoftware.util.Converter.localDateTimeToMillis; -import static com.cedarsoftware.util.Converter.localDateToMillis; import static com.cedarsoftware.util.Converter.zonedDateTimeToMillis; import static com.cedarsoftware.util.convert.ConverterTest.fubar.bar; import static com.cedarsoftware.util.convert.ConverterTest.fubar.foo; @@ -66,8 +64,26 @@ class ConverterTest { + private static final LocalDateTime LDT_2023_TOKYO = LocalDateTime.of(2023, 6, 25, 0, 57, 29, 729000000); + private static final LocalDateTime LDT_2023_PARIS = LocalDateTime.of(2023, 6, 24, 17, 57, 29, 729000000); + private static final LocalDateTime LDT_2023_GMT = LocalDateTime.of(2023, 6, 24, 15, 57, 29, 729000000); + private static final LocalDateTime LDT_2023_NY = LocalDateTime.of(2023, 6, 24, 11, 57, 29, 729000000); + private static final LocalDateTime LDT_2023_CHICAGO = LocalDateTime.of(2023, 6, 24, 10, 57, 29, 729000000); + private static final LocalDateTime LDT_2023_LA = LocalDateTime.of(2023, 6, 24, 8, 57, 29, 729000000); + private static final LocalDateTime LDT_MILLENNIUM_TOKYO = LocalDateTime.of(2000, 1, 1, 13, 59, 59, 959000000); + private static final LocalDateTime LDT_MILLENNIUM_PARIS = LocalDateTime.of(2000, 1, 1, 5, 59, 59, 959000000); + private static final LocalDateTime LDT_MILLENNIUM_GMT = LocalDateTime.of(2000, 1, 1, 4, 59, 59, 959000000); + private static final LocalDateTime LDT_MILLENNIUM_NY = LocalDateTime.of(1999, 12, 31, 23, 59, 59, 959000000); + private static final LocalDateTime LDT_MILLENNIUM_CHICAGO = LocalDateTime.of(1999, 12, 31, 22, 59, 59, 959000000); + private static final LocalDateTime LDT_MILLENNIUM_LA = LocalDateTime.of(1999, 12, 31, 20, 59, 59, 959000000); private Converter converter; + + private static final LocalDate LD_MILLINNIUM_NY = LocalDate.of(1999, 12, 31); + private static final LocalDate LD_MILLINNIUM_TOKYO = LocalDate.of(2000, 1, 1); + + private static final LocalDate LD_MILLENNIUM_CHICAGO = LocalDate.of(1999, 12, 31); + enum fubar { foo, bar, baz, quz @@ -700,18 +716,18 @@ void testToBoolean_falseCases(Object input) { private static Stream epochMillis_withLocalDateTimeInformation() { return Stream.of( - Arguments.of(1687622249729L, TOKYO, LocalDateTime.of(2023, 6, 25, 0, 57, 29, 729000000)), - Arguments.of(1687622249729L, PARIS, LocalDateTime.of(2023, 6, 24, 17, 57, 29, 729000000)), - Arguments.of(1687622249729L, GMT, LocalDateTime.of(2023, 6, 24, 15, 57, 29, 729000000)), - Arguments.of(1687622249729L, NEW_YORK, LocalDateTime.of(2023, 6, 24, 11, 57, 29, 729000000)), - Arguments.of(1687622249729L, CHICAGO, LocalDateTime.of(2023, 6, 24, 10, 57, 29, 729000000)), - Arguments.of(1687622249729L, LOS_ANGELES, LocalDateTime.of(2023, 6, 24, 8, 57, 29, 729000000)), - Arguments.of(946702799959L, TOKYO, LocalDateTime.of(2000, 1, 1, 13, 59, 59, 959000000)), - Arguments.of(946702799959L, PARIS, LocalDateTime.of(2000, 1, 1, 5, 59, 59, 959000000)), - Arguments.of(946702799959L, GMT, LocalDateTime.of(2000, 1, 1, 4, 59, 59, 959000000)), - Arguments.of(946702799959L, NEW_YORK, LocalDateTime.of(1999, 12, 31, 23, 59, 59, 959000000)), - Arguments.of(946702799959L, CHICAGO, LocalDateTime.of(1999, 12, 31, 22, 59, 59, 959000000)), - Arguments.of(946702799959L, LOS_ANGELES, LocalDateTime.of(1999, 12, 31, 20, 59, 59, 959000000)) + Arguments.of(1687622249729L, TOKYO, LDT_2023_TOKYO), + Arguments.of(1687622249729L, PARIS, LDT_2023_PARIS), + Arguments.of(1687622249729L, GMT, LDT_2023_GMT), + Arguments.of(1687622249729L, NEW_YORK, LDT_2023_NY), + Arguments.of(1687622249729L, CHICAGO, LDT_2023_CHICAGO), + Arguments.of(1687622249729L, LOS_ANGELES, LDT_2023_LA), + Arguments.of(946702799959L, TOKYO, LDT_MILLENNIUM_TOKYO), + Arguments.of(946702799959L, PARIS, LDT_MILLENNIUM_PARIS), + Arguments.of(946702799959L, GMT, LDT_MILLENNIUM_GMT), + Arguments.of(946702799959L, NEW_YORK, LDT_MILLENNIUM_NY), + Arguments.of(946702799959L, CHICAGO, LDT_MILLENNIUM_CHICAGO), + Arguments.of(946702799959L, LOS_ANGELES, LDT_MILLENNIUM_LA) ); } @@ -727,6 +743,7 @@ void testCalendarToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateTime e assertThat(localDateTime).isEqualTo(expected); } + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") void testCalendarToLocalDateTime_whenCalendarTimeZoneMatches(long epochMilli, ZoneId zoneId, LocalDateTime expected) { @@ -734,64 +751,78 @@ void testCalendarToLocalDateTime_whenCalendarTimeZoneMatches(long epochMilli, Zo calendar.setTimeInMillis(epochMilli); LocalDateTime localDateTime = this.converter.convert(calendar, LocalDateTime.class, createConvertOptions(zoneId, zoneId)); + assertThat(localDateTime).isEqualTo(expected); } - @Test - void testCalendarToLocalDateTime_whenCalendarTimeZoneDoesNotMatch() { + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testCalendarToLocalDateTime_whenCalendarTimeZoneDoesNotMatch(long epochMilli, ZoneId zoneId, LocalDateTime expected) { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(NEW_YORK)); - calendar.setTimeInMillis(1687622249729L); + calendar.setTimeInMillis(epochMilli); - LocalDateTime localDateTime = this.converter.convert(calendar, LocalDateTime.class, createConvertOptions(NEW_YORK, TOKYO)); + LocalDateTime localDateTime = this.converter.convert(calendar, LocalDateTime.class, createConvertOptions(NEW_YORK, zoneId)); - System.out.println(localDateTime); + assertThat(localDateTime).isEqualTo(expected); + } - assertThat(localDateTime) - .hasYear(2023) - .hasMonthValue(6) - .hasDayOfMonth(25) - .hasHour(0) - .hasMinute(57) - .hasSecond(29) - .hasNano(729000000); + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testCalendar_roundTrip(long epochMilli, ZoneId zoneId, LocalDateTime expected) { + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); + calendar.setTimeInMillis(epochMilli); + + assertThat(calendar.get(Calendar.YEAR)).isEqualTo(expected.getYear()); + assertThat(calendar.get(Calendar.MONTH)).isEqualTo(expected.getMonthValue()-1); + assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(expected.getDayOfMonth()); + assertThat(calendar.get(Calendar.HOUR_OF_DAY)).isEqualTo(expected.getHour()); + assertThat(calendar.get(Calendar.MINUTE)).isEqualTo(expected.getMinute()); + assertThat(calendar.get(Calendar.SECOND)).isEqualTo(expected.getSecond()); + assertThat(calendar.getTimeInMillis()).isEqualTo(epochMilli); + + + LocalDateTime localDateTime = this.converter.convert(calendar, LocalDateTime.class, createConvertOptions(zoneId, TOKYO)); + + Calendar actual = this.converter.convert(localDateTime, Calendar.class, createConvertOptions(TOKYO, zoneId)); + + assertThat(actual.get(Calendar.YEAR)).isEqualTo(expected.getYear()); + assertThat(actual.get(Calendar.MONTH)).isEqualTo(expected.getMonthValue()-1); + assertThat(actual.get(Calendar.DAY_OF_MONTH)).isEqualTo(expected.getDayOfMonth()); + assertThat(actual.get(Calendar.HOUR_OF_DAY)).isEqualTo(expected.getHour()); + assertThat(actual.get(Calendar.MINUTE)).isEqualTo(expected.getMinute()); + assertThat(actual.get(Calendar.SECOND)).isEqualTo(expected.getSecond()); + assertThat(actual.getTimeInMillis()).isEqualTo(epochMilli); } - @Test - void testCalendar_roundTrip() { - // Create LocalDateTime as CHICAGO TIME. - GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone(CHICAGO)); - calendar.setTimeInMillis(1687622249729L); + private static Stream roundTrip_localDates() { + return Stream.of( + Arguments.of(946652400000L, TOKYO, LD_MILLINNIUM_TOKYO), + Arguments.of(946652400000L, NEW_YORK, LD_MILLINNIUM_NY), + Arguments.of(946652400000L, CHICAGO, LD_MILLENNIUM_CHICAGO) + ); + } + @ParameterizedTest + @MethodSource("roundTrip_localDates") + void testCalendar_roundTrip_withLocalDate(long epochMilli, ZoneId zoneId, LocalDate expected) { + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); + calendar.setTimeInMillis(epochMilli); - assertThat(calendar.get(Calendar.MONTH)).isEqualTo(5); - assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(24); - assertThat(calendar.get(Calendar.YEAR)).isEqualTo(2023); - assertThat(calendar.get(Calendar.HOUR_OF_DAY)).isEqualTo(10); - assertThat(calendar.get(Calendar.MINUTE)).isEqualTo(57); - assertThat(calendar.getTimeInMillis()).isEqualTo(1687622249729L); + assertThat(calendar.get(Calendar.YEAR)).isEqualTo(expected.getYear()); + assertThat(calendar.get(Calendar.MONTH)).isEqualTo(expected.getMonthValue()-1); + assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(expected.getDayOfMonth()); + assertThat(calendar.getTimeInMillis()).isEqualTo(epochMilli); - // Convert calendar calendar to TOKYO LocalDateTime - LocalDateTime localDateTime = this.converter.convert(calendar, LocalDateTime.class, createConvertOptions(CHICAGO, TOKYO)); - assertThat(localDateTime) - .hasYear(2023) - .hasMonthValue(6) - .hasDayOfMonth(25) - .hasHour(0) - .hasMinute(57) - .hasSecond(29) - .hasNano(729000000); + LocalDate localDate = this.converter.convert(calendar, LocalDate.class, createConvertOptions(zoneId, TOKYO)); - // Convert Tokyo local date time to CHICAGO Calendar - // We don't know the source ZoneId we are trying to convert. - Calendar actual = this.converter.convert(localDateTime, Calendar.class, createConvertOptions(TOKYO, CHICAGO)); + Calendar actual = this.converter.convert(localDate, Calendar.class, createConvertOptions(TOKYO, zoneId)); - assertThat(actual.get(Calendar.MONTH)).isEqualTo(5); - assertThat(actual.get(Calendar.DAY_OF_MONTH)).isEqualTo(24); - assertThat(actual.get(Calendar.YEAR)).isEqualTo(2023); - assertThat(actual.get(Calendar.HOUR_OF_DAY)).isEqualTo(10); - assertThat(actual.get(Calendar.MINUTE)).isEqualTo(57); - assertThat(actual.getTimeInMillis()).isEqualTo(1687622249729L); + assertThat(actual.get(Calendar.YEAR)).isEqualTo(expected.getYear()); + assertThat(actual.get(Calendar.MONTH)).isEqualTo(expected.getMonthValue()-1); + assertThat(actual.get(Calendar.DAY_OF_MONTH)).isEqualTo(expected.getDayOfMonth()); + + assertThat(actual.getTimeInMillis()).isEqualTo(epochMilli); } @ParameterizedTest @@ -875,6 +906,24 @@ void testDateToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expec assertThat(localDateTime).isEqualTo(expected); } + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testDateToZonedDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Date date = new Date(epochMilli); + ZonedDateTime zonedDateTime = this.converter.convert(date, ZonedDateTime.class, createConvertOptions(null, zoneId)); + assertThat(zonedDateTime.toLocalDateTime()).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testDateToInstant(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Date date = new Date(epochMilli); + Instant actual = this.converter.convert(date, Instant.class, createConvertOptions(null, zoneId)); + assertThat(actual.toEpochMilli()).isEqualTo(epochMilli); + } + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") @@ -885,6 +934,117 @@ void testSqlDateToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateTime ex assertThat(localDateTime).isEqualTo(expected); } + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToLong(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + long actual = this.converter.convert(instant, long.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToAtomicLong(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + AtomicLong actual = this.converter.convert(instant, AtomicLong.class, createConvertOptions(null, zoneId)); + assertThat(actual.get()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToFloat(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + float actual = this.converter.convert(instant, float.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo((float)epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToDouble(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + double actual = this.converter.convert(instant, double.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo((double)epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToTimestamp(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + Timestamp actual = this.converter.convert(instant, Timestamp.class, createConvertOptions(null, zoneId)); + assertThat(actual.getTime()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToDate(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + Date actual = this.converter.convert(instant, Date.class, createConvertOptions(null, zoneId)); + assertThat(actual.getTime()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToSqlDate(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + java.sql.Date actual = this.converter.convert(instant, java.sql.Date.class, createConvertOptions(null, zoneId)); + assertThat(actual.getTime()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToCalendar(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + Calendar actual = this.converter.convert(instant, Calendar.class, createConvertOptions(null, zoneId)); + assertThat(actual.getTime().getTime()).isEqualTo(epochMilli); + assertThat(actual.getTimeZone()).isEqualTo(TimeZone.getTimeZone(zoneId)); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToBigInteger(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + BigInteger actual = this.converter.convert(instant, BigInteger.class, createConvertOptions(null, zoneId)); + assertThat(actual.longValue()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToBigDecimal(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + BigDecimal actual = this.converter.convert(instant, BigDecimal.class, createConvertOptions(null, zoneId)); + assertThat(actual.longValue()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToLocalDate(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + LocalDate actual = this.converter.convert(instant, LocalDate.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo(expected.toLocalDate()); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToLocalTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant instant = Instant.ofEpochMilli(epochMilli); + LocalTime actual = this.converter.convert(instant, LocalTime.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo(expected.toLocalTime()); + } + + + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") void testTimestampToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) @@ -914,6 +1074,16 @@ private static Stream epochMillis_withLocalDateInformation() { } + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateInformation") + void testCalendarToDouble(long epochMilli, ZoneId zoneId, LocalDate expected) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(epochMilli); + + double d = this.converter.convert(calendar, double.class, createConvertOptions(null, zoneId)); + assertThat(d).isEqualTo((double)epochMilli); + } + @ParameterizedTest @MethodSource("epochMillis_withLocalDateInformation") void testCalendarToLocalDate(long epochMilli, ZoneId zoneId, LocalDate expected) { @@ -924,6 +1094,45 @@ void testCalendarToLocalDate(long epochMilli, ZoneId zoneId, LocalDate expected) assertThat(localDate).isEqualTo(expected); } + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testCalendarToLocalTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(epochMilli); + + LocalTime actual = this.converter.convert(calendar, LocalTime.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo(expected.toLocalTime()); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testCalendarToZonedDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(epochMilli); + + ZonedDateTime actual = this.converter.convert(calendar, ZonedDateTime.class, createConvertOptions(null, zoneId)); + assertThat(actual.toLocalDateTime()).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testCalendarToInstant(long epochMilli, ZoneId zoneId, LocalDateTime expected) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(epochMilli); + + Instant actual = this.converter.convert(calendar, Instant.class, createConvertOptions(null, zoneId)); + assertThat(actual.toEpochMilli()).isEqualTo(epochMilli); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testDateToLocalTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) { + Date date = new Date(epochMilli); + + LocalTime actual = this.converter.convert(date, LocalTime.class, createConvertOptions(null, zoneId)); + assertThat(actual).isEqualTo(expected.toLocalTime()); + } + @ParameterizedTest @MethodSource("epochMillis_withLocalDateInformation") void testCalendarToLocalDate_whenCalendarTimeZoneMatches(long epochMilli, ZoneId zoneId, LocalDate expected) { @@ -948,7 +1157,7 @@ void testCalendarToLocalDate_whenCalendarTimeZoneDoesNotMatchTarget_convertsTime } @Test - void testCalendar_testData() { + void testCalendar_testRoundTripWithLocalDate() { // Create LocalDateTime as CHICAGO TIME. GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone(CHICAGO)); @@ -1058,15 +1267,22 @@ void testTimestampToLocalDate(long epochMilli, ZoneId zoneId, LocalDate expected } - private static final LocalDateTime LDT_TOKYO_1 = LocalDateTime.of(2023, 6, 25, 0, 57, 29, 729000000); - private static final LocalDateTime LDT_PARIS_1 = LocalDateTime.of(2023, 6, 24, 17, 57, 29, 729000000); - private static final LocalDateTime LDT_NY_1 = LocalDateTime.of(2023, 6, 24, 11, 57, 29, 729000000); - private static final LocalDateTime LDT_LA_1 = LocalDateTime.of(2023, 6, 24, 8, 57, 29, 729000000); + @ParameterizedTest + @MethodSource("localDateTimeConversion_params") + void testLocalDateToLong(long epochMilli, ZoneId sourceZoneId, LocalDateTime initial, ZoneId targetZoneId, LocalDateTime expected) + { + long milli = this.converter.convert(initial, long.class, createConvertOptions(sourceZoneId, targetZoneId)); + assertThat(milli).isEqualTo(epochMilli); + + LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + assertThat(actual).isEqualTo(expected); + } + private static Stream localDateTimeConversion_params() { return Stream.of( - Arguments.of(1687622249729L, NEW_YORK, LDT_NY_1, TOKYO, LDT_TOKYO_1), - Arguments.of(1687622249729L, LOS_ANGELES, LDT_LA_1, PARIS, LDT_PARIS_1) + Arguments.of(1687622249729L, NEW_YORK, LDT_2023_NY, TOKYO, LDT_2023_TOKYO), + Arguments.of(1687622249729L, LOS_ANGELES, LDT_2023_LA, PARIS, LDT_2023_PARIS) ); } @@ -3651,5 +3867,5 @@ public ZoneId getSourceZoneIdForLocalDates() { }; } - private ConverterOptions chicagoZone() { return createConvertOptions(null, CHICAGO); } + private ConverterOptions chicagoZone() { return createConvertOptions(CHICAGO, CHICAGO); } } From f9976ef519b65734745b245767502c7d4f4fa133 Mon Sep 17 00:00:00 2001 From: Ken Partlow Date: Thu, 25 Jan 2024 22:01:51 -0500 Subject: [PATCH 4/6] Undid StringUtilities isEmpty changes --- .../cedarsoftware/util/StringUtilities.java | 26 +-- .../cedarsoftware/util/convert/Converter.java | 10 +- .../util/convert/LocalDateConversions.java | 4 + .../util/TestStringUtilities.java | 8 +- .../util/convert/ConverterTest.java | 162 +++++++++++++++++- 5 files changed, 186 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/cedarsoftware/util/StringUtilities.java b/src/main/java/com/cedarsoftware/util/StringUtilities.java index 992c1dd0..f70ef6b4 100644 --- a/src/main/java/com/cedarsoftware/util/StringUtilities.java +++ b/src/main/java/com/cedarsoftware/util/StringUtilities.java @@ -181,24 +181,25 @@ public static boolean equalsIgnoreCaseWithTrim(final String s1, final String s2) } /** - * Checks if a CharSequence is empty ("") or null. + * Checks if a CharSequence is empty (""), null, or only whitespace. * * @param cs the CharSequence to check, may be null * @return {@code true} if the CharSequence is empty or null - * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) */ - public static boolean isEmpty(final CharSequence cs) { - return cs == null || cs.length() == 0; + public static boolean isEmpty(CharSequence cs) + { + return isWhitespace(cs); } /** - * Checks if a CharSequence is not empty ("") and not null. + * Checks if a CharSequence is not empty (""), not null and not whitespace only. * * @param cs the CharSequence to check, may be null - * @return {@code true} if the CharSequence is not empty and not null + * @return {@code true} if the CharSequence is + * not empty and not null and not whitespace only */ - public static boolean isNotEmpty(final CharSequence cs) { - return !isEmpty(cs); + public static boolean isNotWhitespace(final CharSequence cs) { + return !isWhitespace(cs); } /** @@ -221,13 +222,12 @@ public static boolean isWhitespace(final CharSequence cs) { } /** - * Checks if a CharSequence is not empty (""), not null and not whitespace only. + * Checks if a CharSequence is not null, not empty (""), and not only whitespace. * * @param cs the CharSequence to check, may be null - * @return {@code true} if the CharSequence is - * not empty and not null and not whitespace only + * @return {@code true} if the CharSequence is not empty and not null */ - public static boolean hasContent(final CharSequence cs) { + public static boolean isNotEmpty(final CharSequence cs) { return !isWhitespace(cs); } @@ -238,7 +238,7 @@ public static boolean hasContent(final CharSequence cs) { * @return {@code true} if the CharSequence is * not empty and not null and not whitespace only */ - public static boolean isNotWhitespace(final CharSequence cs) { + public static boolean hasContent(final CharSequence cs) { return !isWhitespace(cs); } diff --git a/src/main/java/com/cedarsoftware/util/convert/Converter.java b/src/main/java/com/cedarsoftware/util/convert/Converter.java index 533bc69b..79d632a7 100644 --- a/src/main/java/com/cedarsoftware/util/convert/Converter.java +++ b/src/main/java/com/cedarsoftware/util/convert/Converter.java @@ -209,7 +209,7 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Boolean.class, Float.class), BooleanConversions::toFloat); DEFAULT_FACTORY.put(pair(Character.class, Float.class), CharacterConversions::toFloat); DEFAULT_FACTORY.put(pair(Instant.class, Float.class), InstantConversions::toFloat); - DEFAULT_FACTORY.put(pair(LocalDate.class, Float.class), LocalDateConversions::toLong); + DEFAULT_FACTORY.put(pair(LocalDate.class, Float.class), LocalDateConversions::toFloat); DEFAULT_FACTORY.put(pair(AtomicBoolean.class, Float.class), AtomicBooleanConversions::toFloat); DEFAULT_FACTORY.put(pair(AtomicInteger.class, Float.class), NumberConversions::toFloat); DEFAULT_FACTORY.put(pair(AtomicLong.class, Float.class), NumberConversions::toFloat); @@ -231,7 +231,7 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Boolean.class, Double.class), BooleanConversions::toDouble); DEFAULT_FACTORY.put(pair(Character.class, Double.class), CharacterConversions::toDouble); DEFAULT_FACTORY.put(pair(Instant.class, Double.class), InstantConversions::toDouble); - DEFAULT_FACTORY.put(pair(LocalDate.class, Double.class), LocalDateConversions::toLong); + DEFAULT_FACTORY.put(pair(LocalDate.class, Double.class), LocalDateConversions::toDouble); DEFAULT_FACTORY.put(pair(LocalDateTime.class, Double.class), LocalDateTimeConversions::toLong); DEFAULT_FACTORY.put(pair(ZonedDateTime.class, Double.class), ZonedDateTimeConversions::toLong); DEFAULT_FACTORY.put(pair(Date.class, Double.class), DateConversions::toLong); @@ -554,8 +554,8 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Timestamp.class, LocalDate.class), DateConversions::toLocalDate); DEFAULT_FACTORY.put(pair(Date.class, LocalDate.class), DateConversions::toLocalDate); DEFAULT_FACTORY.put(pair(Instant.class, LocalDate.class), InstantConversions::toLocalDate); - DEFAULT_FACTORY.put(pair(LocalDate.class, LocalDate.class), Converter::identity); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalDate.class), (fromInstance, converter, options) -> ((LocalDateTime) fromInstance).toLocalDate()); + DEFAULT_FACTORY.put(pair(LocalDate.class, LocalDate.class), LocalDateConversions::toLocalDate); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalDate.class), LocalDateTimeConversions::toLocalDate); DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalDate.class), ZonedDateTimeConversions::toLocalDate); DEFAULT_FACTORY.put(pair(Calendar.class, LocalDate.class), CalendarConversions::toLocalDate); DEFAULT_FACTORY.put(pair(Number.class, LocalDate.class), NumberConversions::toLocalDate); @@ -590,7 +590,7 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Timestamp.class, LocalDateTime.class), DateConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(Date.class, LocalDateTime.class), DateConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(Instant.class, LocalDateTime.class), InstantConversions::toLocalDateTime); - DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalDateTime.class), Converter::identity); + DEFAULT_FACTORY.put(pair(LocalDateTime.class, LocalDateTime.class), LocalDateTimeConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(LocalDate.class, LocalDateTime.class), LocalDateConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(ZonedDateTime.class, LocalDateTime.class), ZonedDateTimeConversions::toLocalDateTime); DEFAULT_FACTORY.put(pair(Calendar.class, LocalDateTime.class), CalendarConversions::toLocalDateTime); diff --git a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java index c5931025..8539c1f8 100644 --- a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java @@ -31,6 +31,10 @@ static LocalDateTime toLocalDateTime(Object fromInstance, Converter converter, C return toZonedDateTime(fromInstance, options).toLocalDateTime(); } + static LocalDate toLocalDate(Object fromInstance, Converter converter, ConverterOptions options) { + return toZonedDateTime(fromInstance, options).toLocalDate(); + } + static LocalTime toLocalTime(Object fromInstance, Converter converter, ConverterOptions options) { return toZonedDateTime(fromInstance, options).toLocalTime(); } diff --git a/src/test/java/com/cedarsoftware/util/TestStringUtilities.java b/src/test/java/com/cedarsoftware/util/TestStringUtilities.java index c55f97a2..7bd2c0a0 100644 --- a/src/test/java/com/cedarsoftware/util/TestStringUtilities.java +++ b/src/test/java/com/cedarsoftware/util/TestStringUtilities.java @@ -62,9 +62,9 @@ void testConstructorIsPrivate() throws Exception { @ParameterizedTest @MethodSource("stringsWithAllWhitespace") - void testIsEmpty_whenStringHasWhitespace_returnsFalse(String s) + void testIsEmpty_whenStringHasOnlyWhitespace_returnsTrue(String s) { - assertFalse(StringUtilities.isEmpty(s)); + assertTrue(StringUtilities.isEmpty(s)); } @ParameterizedTest @@ -83,9 +83,9 @@ void testIsEmpty_whenNullOrEmpty_returnsTrue(String s) @ParameterizedTest @MethodSource("stringsWithAllWhitespace") - void testIsNotEmpty_whenStringHasWhitespace_returnsTrue(String s) + void testIsNotEmpty_whenStringHasOnlyWhitespace_returnsFalse(String s) { - assertTrue(StringUtilities.isNotEmpty(s)); + assertFalse(StringUtilities.isNotEmpty(s)); } @ParameterizedTest diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java index 4b4be2a1..2484b015 100644 --- a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java +++ b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java @@ -795,15 +795,16 @@ void testCalendar_roundTrip(long epochMilli, ZoneId zoneId, LocalDateTime expect } - private static Stream roundTrip_localDates() { + private static Stream roundTrip_tokyoTime() { return Stream.of( Arguments.of(946652400000L, TOKYO, LD_MILLINNIUM_TOKYO), Arguments.of(946652400000L, NEW_YORK, LD_MILLINNIUM_NY), Arguments.of(946652400000L, CHICAGO, LD_MILLENNIUM_CHICAGO) ); } + @ParameterizedTest - @MethodSource("roundTrip_localDates") + @MethodSource("roundTrip_tokyoTime") void testCalendar_roundTrip_withLocalDate(long epochMilli, ZoneId zoneId, LocalDate expected) { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); calendar.setTimeInMillis(epochMilli); @@ -825,6 +826,154 @@ void testCalendar_roundTrip_withLocalDate(long epochMilli, ZoneId zoneId, LocalD assertThat(actual.getTimeInMillis()).isEqualTo(epochMilli); } + private static Stream localDateToLong() { + return Stream.of( + Arguments.of(946616400000L, NEW_YORK, LD_MILLINNIUM_NY, TOKYO), + Arguments.of(946616400000L, NEW_YORK, LD_MILLINNIUM_NY, CHICAGO), + Arguments.of(946620000000L, CHICAGO, LD_MILLENNIUM_CHICAGO, TOKYO) + ); + } + @ParameterizedTest + @MethodSource("localDateToLong") + void testConvertLocalDateToLongAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + long intermediate = this.converter.convert(expected, long.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateToInstantAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + Instant intermediate = this.converter.convert(expected, Instant.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.toEpochMilli()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateToDoubleAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + double intermediate = this.converter.convert(expected, double.class, createConvertOptions(zoneId, targetZone)); + + assertThat((long)intermediate).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateToAtomicLongAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + AtomicLong intermediate = this.converter.convert(expected, AtomicLong.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.get()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateToDateAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + Date intermediate = this.converter.convert(expected,Date.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.getTime()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateSqlDateAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + java.sql.Date intermediate = this.converter.convert(expected, java.sql.Date.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.getTime()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateTimestampAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + Timestamp intermediate = this.converter.convert(expected, Timestamp.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.getTime()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateZonedDateTimeAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + ZonedDateTime intermediate = this.converter.convert(expected, ZonedDateTime.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.toInstant().toEpochMilli()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateToLocalDateTimeAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + LocalDateTime intermediate = this.converter.convert(expected, LocalDateTime.class, createConvertOptions(zoneId, targetZone)); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateBigIntegerAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + BigInteger intermediate = this.converter.convert(expected, BigInteger.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.longValue()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateBigDecimalAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + BigDecimal intermediate = this.converter.convert(expected, BigDecimal.class, createConvertOptions(zoneId, targetZone)); + + assertThat(intermediate.longValue()).isEqualTo(epochMilli); + + LocalDate actual = this.converter.convert(intermediate, LocalDate.class, createConvertOptions(targetZone, zoneId)); + + assertThat(actual).isEqualTo(expected); + } + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") void testZonedDateTimeToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) @@ -915,6 +1064,15 @@ void testDateToZonedDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expec assertThat(zonedDateTime.toLocalDateTime()).isEqualTo(expected); } + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testInstantToZonedDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + Instant date = Instant.ofEpochMilli(epochMilli); + ZonedDateTime zonedDateTime = this.converter.convert(date, ZonedDateTime.class, createConvertOptions(null, zoneId)); + assertThat(zonedDateTime.toInstant()).isEqualTo(date); + } + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") void testDateToInstant(long epochMilli, ZoneId zoneId, LocalDateTime expected) From 9723bef911c79da8050e0f48d4f2aa96b172ed93 Mon Sep 17 00:00:00 2001 From: Ken Partlow Date: Thu, 25 Jan 2024 22:15:12 -0500 Subject: [PATCH 5/6] LocalDate tests added, started LocalTime --- .../util/convert/CalendarConversions.java | 4 -- .../util/convert/LocalDateConversions.java | 7 +++ .../util/convert/ConverterTest.java | 44 ++++++++++++++++++- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java b/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java index 5cc42f64..29e7c803 100644 --- a/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/CalendarConversions.java @@ -96,8 +96,4 @@ static Calendar create(long epochMilli, ConverterOptions options) { cal.setTimeInMillis(epochMilli); return cal; } - - static Calendar create(ZonedDateTime time, ConverterOptions options) { - return GregorianCalendar.from(time); - } } diff --git a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java index 8539c1f8..50e19dce 100644 --- a/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/LocalDateConversions.java @@ -52,6 +52,13 @@ static long toLong(Object fromInstance, Converter converter, ConverterOptions op return toInstant(fromInstance, options).toEpochMilli(); } + /** + * Warning: Can lose precision going from a full long down to a floating point number + * @param fromInstance instance to convert + * @param converter converter instance + * @param options converter options + * @return the floating point number cast from a lont. + */ static float toFloat(Object fromInstance, Converter converter, ConverterOptions options) { return toLong(fromInstance, converter, options); } diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java index 2484b015..4704e4dd 100644 --- a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java +++ b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java @@ -950,7 +950,7 @@ void testLocalDateToLocalDateTimeAndBack(long epochMilli, ZoneId zoneId, LocalDa @ParameterizedTest @MethodSource("localDateToLong") - void testLocalDateBigIntegerAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + void testLocalDateToBigIntegerAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { BigInteger intermediate = this.converter.convert(expected, BigInteger.class, createConvertOptions(zoneId, targetZone)); @@ -963,7 +963,7 @@ void testLocalDateBigIntegerAndBack(long epochMilli, ZoneId zoneId, LocalDate ex @ParameterizedTest @MethodSource("localDateToLong") - void testLocalDateBigDecimalAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + void testLocalDateToBigDecimalAndBack(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { BigDecimal intermediate = this.converter.convert(expected, BigDecimal.class, createConvertOptions(zoneId, targetZone)); @@ -974,6 +974,46 @@ void testLocalDateBigDecimalAndBack(long epochMilli, ZoneId zoneId, LocalDate ex assertThat(actual).isEqualTo(expected); } + @Test + void testLocalDateToFloat() { + + float intermediate = this.converter.convert(LD_MILLINNIUM_NY, float.class, createConvertOptions(NEW_YORK, TOKYO)); + + assertThat((long)intermediate).isNotEqualTo(946616400000L); + } + + @Test + void testLocalDateToLocalTime_withZoneChange_willBeZoneOffset() { + + LocalTime intermediate = this.converter.convert(LD_MILLINNIUM_NY, LocalTime.class, createConvertOptions(NEW_YORK, TOKYO)); + + assertThat(intermediate).hasHour(14) + .hasMinute(0) + .hasSecond(0) + .hasNano(0); + } + + @Test + void testLocalDateToLocalTimeWithoutZoneChange_willBeMidnight() { + + LocalTime intermediate = this.converter.convert(LD_MILLINNIUM_NY, LocalTime.class, createConvertOptions(NEW_YORK, NEW_YORK)); + + assertThat(intermediate).hasHour(0) + .hasMinute(0) + .hasSecond(0) + .hasNano(0); + } + + @ParameterizedTest + @MethodSource("localDateToLong") + void testLocalDateToLocalTime(long epochMilli, ZoneId zoneId, LocalDate expected, ZoneId targetZone) { + + float intermediate = this.converter.convert(expected, float.class, createConvertOptions(zoneId, targetZone)); + + assertThat((long)intermediate).isNotEqualTo(epochMilli); + } + + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") void testZonedDateTimeToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) From 5d2e40641e699a5374825f250fff13e18948f302 Mon Sep 17 00:00:00 2001 From: Ken Partlow Date: Thu, 25 Jan 2024 23:14:11 -0500 Subject: [PATCH 6/6] Moved over tests for ListOf...SetOf...and ClassUtilities --- .../util/ClassUtilitiesTest.java | 71 +++++++++ .../util/CollectionUtilitiesTests.java | 105 +++++++++++++ .../util/convert/ConverterTest.java | 147 ++++++++++-------- 3 files changed, 261 insertions(+), 62 deletions(-) create mode 100644 src/test/java/com/cedarsoftware/util/CollectionUtilitiesTests.java diff --git a/src/test/java/com/cedarsoftware/util/ClassUtilitiesTest.java b/src/test/java/com/cedarsoftware/util/ClassUtilitiesTest.java index 6f5bdbb2..226bee16 100644 --- a/src/test/java/com/cedarsoftware/util/ClassUtilitiesTest.java +++ b/src/test/java/com/cedarsoftware/util/ClassUtilitiesTest.java @@ -152,4 +152,75 @@ public void testPrimitives() { assert 1 == ClassUtilities.computeInheritanceDistance(java.sql.Date.class, Date.class); } + @Test + public void testClassForName() + { + Class testObjectClass = ClassUtilities.forName(SubClass.class.getName(), ClassUtilities.class.getClassLoader()); + assert testObjectClass instanceof Class; + assert SubClass.class.getName().equals(testObjectClass.getName()); + } + + @Test + public void testClassForNameWithClassloader() + { + Class testObjectClass = ClassUtilities.forName("ReallyLong", new AlternateNameClassLoader("ReallyLong", Long.class)); + assert testObjectClass instanceof Class; + assert "java.lang.Long".equals(testObjectClass.getName()); + } + + @Test + public void testClassForNameNullClassErrorHandling() + { + assert null == ClassUtilities.forName(null, ClassUtilities.class.getClassLoader()); + assert null == ClassUtilities.forName("Smith&Wesson", ClassUtilities.class.getClassLoader()); + } + + @Test + public void testClassForNameFailOnClassLoaderErrorTrue() + { + assert null == ClassUtilities.forName("foo.bar.baz.Qux", ClassUtilities.class.getClassLoader()); + } + + @Test + public void testClassForNameFailOnClassLoaderErrorFalse() + { + Class testObjectClass = ClassUtilities.forName("foo.bar.baz.Qux", ClassUtilities.class.getClassLoader()); + assert testObjectClass == null; + } + + private static class AlternateNameClassLoader extends ClassLoader + { + AlternateNameClassLoader(String alternateName, Class clazz) + { + super(AlternateNameClassLoader.class.getClassLoader()); + this.alternateName = alternateName; + this.clazz = clazz; + } + + public Class loadClass(String className) throws ClassNotFoundException + { + return findClass(className); + } + + protected Class findClass(String className) + { + try + { + return findSystemClass(className); + } + catch (Exception ignored) + { } + + if (alternateName.equals(className)) + { + return Long.class; + } + + return null; + } + + private final String alternateName; + private final Class clazz; + } + } diff --git a/src/test/java/com/cedarsoftware/util/CollectionUtilitiesTests.java b/src/test/java/com/cedarsoftware/util/CollectionUtilitiesTests.java new file mode 100644 index 00000000..79fa70b3 --- /dev/null +++ b/src/test/java/com/cedarsoftware/util/CollectionUtilitiesTests.java @@ -0,0 +1,105 @@ +package com.cedarsoftware.util; + +import com.cedarsoftware.util.io.MetaUtils; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CollectionUtilitiesTests { + static class Rec { + final String s; + final int i; + Rec(String s, int i) { + this.s = s; + this.i = i; + } + + Rec link; + List ilinks; + List mlinks; + + Map smap; + } + + @Test + void testListOf() { + final List list = CollectionUtilities.listOf(); + assertEquals(0, list.size()); + } + + @Test + void testListOf_producesImmutableList() { + final List list = CollectionUtilities.listOf(); + assertThatExceptionOfType(UnsupportedOperationException.class) + .isThrownBy(() -> list.add("One")); + } + + @Test + void testListOfOne() { + final List list = CollectionUtilities.listOf("One"); + assertEquals(1, list.size()); + assertEquals("One", list.get(0)); + } + + @Test + void testListOfTwo() { + final List list = CollectionUtilities.listOf("One", "Two"); + assertEquals(2, list.size()); + assertEquals("One", list.get(0)); + assertEquals("Two", list.get(1)); + } + + @Test + void testListOfThree() { + final List list = CollectionUtilities.listOf("One", "Two", "Three"); + assertEquals(3, list.size()); + assertEquals("One", list.get(0)); + assertEquals("Two", list.get(1)); + assertEquals("Three", list.get(2)); + } + + @Test + void testSetOf() { + final Set set = CollectionUtilities.setOf(); + assertEquals(0, set.size()); + } + + @Test + void testSetOf_producesImmutableSet() { + final Set set = CollectionUtilities.setOf(); + assertThatExceptionOfType(UnsupportedOperationException.class) + .isThrownBy(() -> set.add("One")); + } + + + @Test + void testSetOfOne() { + final Set set = CollectionUtilities.setOf("One"); + assertEquals(1, set.size()); + assertTrue(set.contains("One")); + } + + @Test + public void testSetOfTwo() { + final Set set = CollectionUtilities.setOf("One", "Two"); + assertEquals(2, set.size()); + assertTrue(set.contains("One")); + assertTrue(set.contains("Two")); + } + + @Test + public void testSetOfThree() { + final Set set = CollectionUtilities.setOf("One", "Two", "Three"); + assertEquals(3, set.size()); + assertTrue(set.contains("One")); + assertTrue(set.contains("Two")); + assertTrue(set.contains("Three")); + } +} diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java index 4704e4dd..0b305885 100644 --- a/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java +++ b/src/test/java/com/cedarsoftware/util/convert/ConverterTest.java @@ -1027,6 +1027,52 @@ void testZonedDateTimeToLocalDateTime(long epochMilli, ZoneId zoneId, LocalDateT } + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testZonedDateTimeToLocalTime(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + ZonedDateTime time = Instant.ofEpochMilli(epochMilli).atZone(zoneId); + + LocalTime actual = this.converter.convert(time, LocalTime.class, createConvertOptions(zoneId, zoneId)); + + assertThat(actual).isEqualTo(expected.toLocalTime()); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testZonedDateTimeToLocalDate(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + ZonedDateTime time = Instant.ofEpochMilli(epochMilli).atZone(zoneId); + + LocalDate actual = this.converter.convert(time, LocalDate.class, createConvertOptions(zoneId, zoneId)); + + assertThat(actual).isEqualTo(expected.toLocalDate()); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testZonedDateTimeToInstant(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + ZonedDateTime time = Instant.ofEpochMilli(epochMilli).atZone(zoneId); + + Instant actual = this.converter.convert(time, Instant.class, createConvertOptions(zoneId, zoneId)); + + assertThat(actual).isEqualTo(time.toInstant()); + } + + @ParameterizedTest + @MethodSource("epochMillis_withLocalDateTimeInformation") + void testZonedDateTimeToCalendar(long epochMilli, ZoneId zoneId, LocalDateTime expected) + { + ZonedDateTime time = Instant.ofEpochMilli(epochMilli).atZone(zoneId); + + Calendar actual = this.converter.convert(time, Calendar.class, createConvertOptions(zoneId, zoneId)); + + assertThat(actual.getTime().getTime()).isEqualTo(time.toInstant().toEpochMilli()); + assertThat(actual.getTimeZone()).isEqualTo(TimeZone.getTimeZone(zoneId)); + } + + @ParameterizedTest @MethodSource("epochMillis_withLocalDateTimeInformation") void testZonedDateTimeToLong(long epochMilli, ZoneId zoneId, LocalDateTime localDateTime) @@ -1492,7 +1538,18 @@ void testLocalDateTimeToLong(long epochMilli, ZoneId sourceZoneId, LocalDateTime long milli = this.converter.convert(initial, long.class, createConvertOptions(sourceZoneId, targetZoneId)); assertThat(milli).isEqualTo(epochMilli); - LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(null, targetZoneId)); + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateTimeConversion_params") + void testLocalDateTimeToInstant(long epochMilli, ZoneId sourceZoneId, LocalDateTime initial, ZoneId targetZoneId, LocalDateTime expected) + { + Instant intermediate = this.converter.convert(initial, Instant.class, createConvertOptions(sourceZoneId, targetZoneId)); + assertThat(intermediate.toEpochMilli()).isEqualTo(epochMilli); + + LocalDateTime actual = this.converter.convert(intermediate, LocalDateTime.class, createConvertOptions(null, targetZoneId)); assertThat(actual).isEqualTo(expected); } @@ -1503,10 +1560,30 @@ void testLocalDateTimeToAtomicLong(long epochMilli, ZoneId sourceZoneId, LocalDa AtomicLong milli = this.converter.convert(initial, AtomicLong.class, createConvertOptions(sourceZoneId, targetZoneId)); assertThat(milli.longValue()).isEqualTo(epochMilli); - LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(null, targetZoneId)); + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("localDateTimeConversion_params") + void testLocalDateTimeToZonedDateTime(long epochMilli, ZoneId sourceZoneId, LocalDateTime initial, ZoneId targetZoneId, LocalDateTime expected) + { + ZonedDateTime intermediate = this.converter.convert(initial, ZonedDateTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + assertThat(intermediate.toInstant().toEpochMilli()).isEqualTo(epochMilli); + + LocalDateTime actual = this.converter.convert(intermediate, LocalDateTime.class, createConvertOptions(null, targetZoneId)); assertThat(actual).isEqualTo(expected); } + @ParameterizedTest + @MethodSource("localDateTimeConversion_params") + void testLocalDateTimeToLocalTime(long epochMilli, ZoneId sourceZoneId, LocalDateTime initial, ZoneId targetZoneId, LocalDateTime expected) + { + LocalTime intermediate = this.converter.convert(initial, LocalTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + + assertThat(intermediate).isEqualTo(expected.toLocalTime()); + } + @ParameterizedTest @MethodSource("localDateTimeConversion_params") void testLocalDateTimeToBigInteger(long epochMilli, ZoneId sourceZoneId, LocalDateTime initial, ZoneId targetZoneId, LocalDateTime expected) @@ -1514,7 +1591,7 @@ void testLocalDateTimeToBigInteger(long epochMilli, ZoneId sourceZoneId, LocalDa BigInteger milli = this.converter.convert(initial, BigInteger.class, createConvertOptions(sourceZoneId, targetZoneId)); assertThat(milli.longValue()).isEqualTo(epochMilli); - LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(null, targetZoneId)); assertThat(actual).isEqualTo(expected); } @@ -1526,7 +1603,7 @@ void testLocalDateTimeToBigDecimal(long epochMilli, ZoneId sourceZoneId, LocalDa BigDecimal milli = this.converter.convert(initial, BigDecimal.class, createConvertOptions(sourceZoneId, targetZoneId)); assertThat(milli.longValue()).isEqualTo(epochMilli); - LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(sourceZoneId, targetZoneId)); + LocalDateTime actual = this.converter.convert(milli, LocalDateTime.class, createConvertOptions(null, targetZoneId)); assertThat(actual).isEqualTo(expected); } @@ -2379,66 +2456,12 @@ void testConversions_whenClassTypeMatchesObjectType_stillCreatesNewObject(Object } @Test - void testLocalDateTimeToOthers() - { - // String to LocalDateTime -// String strDate = this.converter.convert(now, String.class); -// localDateTime = this.converter.convert(strDate, LocalDateTime.class); -// String strDate2 = this.converter.convert(localDateTime, String.class); -// assert strDate.startsWith(strDate2); -// -// // Other direction --> LocalDateTime to other date types -// -// // LocalDateTime to Date -// localDateTime = this.converter.convert(now, LocalDateTime.class); -// Date date = this.converter.convert(localDateTime, Date.class); -// assertEquals(localDateTimeToMillis(localDateTime), date.getTime()); -// -// // LocalDateTime to SqlDate -// sqlDate = this.converter.convert(localDateTime, java.sql.Date.class); -// assertEquals(localDateTimeToMillis(localDateTime), sqlDate.getTime()); -// -// // LocalDateTime to Timestamp -// timestamp = this.converter.convert(localDateTime, Timestamp.class); -// assertEquals(localDateTimeToMillis(localDateTime), timestamp.getTime()); -// -// // LocalDateTime to Long -// long tnow = this.converter.convert(localDateTime, long.class); -// assertEquals(localDateTimeToMillis(localDateTime), tnow); -// -// // LocalDateTime to AtomicLong -// atomicLong = this.converter.convert(localDateTime, AtomicLong.class); -// assertEquals(localDateTimeToMillis(localDateTime), atomicLong.get()); -// -// // LocalDateTime to String -// strDate = this.converter.convert(localDateTime, String.class); -// strDate2 = this.converter.convert(now, String.class); -// assert strDate2.startsWith(strDate); -// -// // LocalDateTime to BigInteger -// bigInt = this.converter.convert(localDateTime, BigInteger.class); -// assertEquals(now.getTime(), bigInt.longValue()); -// -// // LocalDateTime to BigDecimal -// bigDec = this.converter.convert(localDateTime, BigDecimal.class); -// assertEquals(now.getTime(), bigDec.longValue()); -// -// // Error handling -// try -// { -// this.converter.convert("2020-12-40", LocalDateTime.class); -// fail(); -// } -// catch (IllegalArgumentException e) -// { -// TestUtil.assertContainsIgnoreCase(e.getMessage(), "day must be between 1 and 31"); -// } -// -// assert this.converter.convert(null, LocalDateTime.class) == null; + void testConvertStringToLocalDateTime_withParseError() { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.converter.convert("2020-12-40", LocalDateTime.class)) + .withMessageContaining("Day must be between 1 and 31"); } - - @Test void testDateErrorHandlingBadInput() {