ConvertUtilsBean.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.beanutils2;

  18. import java.awt.Color;
  19. import java.awt.Dimension;
  20. import java.awt.Point;
  21. import java.io.File;
  22. import java.lang.reflect.Array;
  23. import java.math.BigDecimal;
  24. import java.math.BigInteger;
  25. import java.net.InetAddress;
  26. import java.net.URI;
  27. import java.net.URL;
  28. import java.nio.file.Path;
  29. import java.sql.Timestamp;
  30. import java.time.Duration;
  31. import java.time.LocalDate;
  32. import java.time.LocalDateTime;
  33. import java.time.LocalTime;
  34. import java.time.MonthDay;
  35. import java.time.OffsetDateTime;
  36. import java.time.OffsetTime;
  37. import java.time.Period;
  38. import java.time.Year;
  39. import java.time.YearMonth;
  40. import java.time.ZoneId;
  41. import java.time.ZoneOffset;
  42. import java.time.ZonedDateTime;
  43. import java.util.Calendar;
  44. import java.util.Collection;
  45. import java.util.Locale;
  46. import java.util.Map;
  47. import java.util.Objects;
  48. import java.util.UUID;
  49. import java.util.regex.Pattern;

  50. import org.apache.commons.beanutils2.converters.ArrayConverter;
  51. import org.apache.commons.beanutils2.converters.BigDecimalConverter;
  52. import org.apache.commons.beanutils2.converters.BigIntegerConverter;
  53. import org.apache.commons.beanutils2.converters.BooleanConverter;
  54. import org.apache.commons.beanutils2.converters.ByteConverter;
  55. import org.apache.commons.beanutils2.converters.CalendarConverter;
  56. import org.apache.commons.beanutils2.converters.CharacterConverter;
  57. import org.apache.commons.beanutils2.converters.ClassConverter;
  58. import org.apache.commons.beanutils2.converters.ColorConverter;
  59. import org.apache.commons.beanutils2.converters.ConverterFacade;
  60. import org.apache.commons.beanutils2.converters.DateConverter;
  61. import org.apache.commons.beanutils2.converters.DimensionConverter;
  62. import org.apache.commons.beanutils2.converters.DoubleConverter;
  63. import org.apache.commons.beanutils2.converters.DurationConverter;
  64. import org.apache.commons.beanutils2.converters.EnumConverter;
  65. import org.apache.commons.beanutils2.converters.FileConverter;
  66. import org.apache.commons.beanutils2.converters.FloatConverter;
  67. import org.apache.commons.beanutils2.converters.InetAddressConverter;
  68. import org.apache.commons.beanutils2.converters.IntegerConverter;
  69. import org.apache.commons.beanutils2.converters.LocalDateConverter;
  70. import org.apache.commons.beanutils2.converters.LocalDateTimeConverter;
  71. import org.apache.commons.beanutils2.converters.LocalTimeConverter;
  72. import org.apache.commons.beanutils2.converters.LocaleConverter;
  73. import org.apache.commons.beanutils2.converters.LongConverter;
  74. import org.apache.commons.beanutils2.converters.MonthDayConverter;
  75. import org.apache.commons.beanutils2.converters.OffsetDateTimeConverter;
  76. import org.apache.commons.beanutils2.converters.OffsetTimeConverter;
  77. import org.apache.commons.beanutils2.converters.PathConverter;
  78. import org.apache.commons.beanutils2.converters.PatternConverter;
  79. import org.apache.commons.beanutils2.converters.PeriodConverter;
  80. import org.apache.commons.beanutils2.converters.PointConverter;
  81. import org.apache.commons.beanutils2.converters.ShortConverter;
  82. import org.apache.commons.beanutils2.converters.StringConverter;
  83. import org.apache.commons.beanutils2.converters.URIConverter;
  84. import org.apache.commons.beanutils2.converters.URLConverter;
  85. import org.apache.commons.beanutils2.converters.UUIDConverter;
  86. import org.apache.commons.beanutils2.converters.YearConverter;
  87. import org.apache.commons.beanutils2.converters.YearMonthConverter;
  88. import org.apache.commons.beanutils2.converters.ZoneIdConverter;
  89. import org.apache.commons.beanutils2.converters.ZoneOffsetConverter;
  90. import org.apache.commons.beanutils2.converters.ZonedDateTimeConverter;
  91. import org.apache.commons.beanutils2.sql.converters.SqlDateConverter;
  92. import org.apache.commons.beanutils2.sql.converters.SqlTimeConverter;
  93. import org.apache.commons.beanutils2.sql.converters.SqlTimestampConverter;
  94. import org.apache.commons.logging.Log;
  95. import org.apache.commons.logging.LogFactory;

  96. /**
  97.  * TODO DOCS
  98.  * <p>
  99.  * 2.0
  100.  * </p>
  101.  *
  102.  * {@link ConvertUtilsBean} implementation that delegates {@code convert()} methods to the new {@link ConvertUtilsBean#convert(Object, Class)} method.
  103.  *
  104.  * <p>
  105.  * To configure this implementation for the current context ClassLoader invoke {@code BeanUtilsBean.setInstance(new BeanUtilsBean2());}
  106.  * </p>
  107.  *
  108.  * <p>
  109.  * Pre-2.0
  110.  * </p>
  111.  *
  112.  * <p>
  113.  * Utility methods for converting String scalar values to objects of the specified Class, String arrays to arrays of the specified Class. The actual
  114.  * {@link Converter} instance to be used can be registered for each possible destination Class. Unless you override them, standard {@link Converter} instances
  115.  * are provided for all of the following destination Classes:
  116.  * </p>
  117.  * <ul>
  118.  * <li>java.lang.BigDecimal (no default value)</li>
  119.  * <li>java.lang.BigInteger (no default value)</li>
  120.  * <li>boolean and java.lang.Boolean (default to false)</li>
  121.  * <li>byte and java.lang.Byte (default to zero)</li>
  122.  * <li>char and java.lang.Character (default to a space)</li>
  123.  * <li>java.lang.Class (no default value)</li>
  124.  * <li>java.awt.Color (no default value)</li>
  125.  * <li>java.awt.Dimension (no default value)</li>
  126.  * <li>double and java.lang.Double (default to zero)</li>
  127.  * <li>float and java.lang.Float (default to zero)</li>
  128.  * <li>int and java.lang.Integer (default to zero)</li>
  129.  * <li>long and java.lang.Long (default to zero)</li>
  130.  * <li>short and java.lang.Short (default to zero)</li>
  131.  * <li>java.lang.String (default to null)</li>
  132.  * <li>java.lang.Enum (default to null)</li>
  133.  * <li>java.io.File (no default value)</li>
  134.  * <li>java.net.InetAddress (no default value)</li>
  135.  * <li>java.util.Locale (no default value)</li>
  136.  * <li>java.nio.file.Path (no default value)</li>
  137.  * <li>java.net.URL (no default value)</li>
  138.  * <li>java.net.URI (no default value)</li>
  139.  * <li>java.util.UUID (no default value)</li>
  140.  * <li>java.sql.Date (no default value)</li>
  141.  * <li>java.sql.Time (no default value)</li>
  142.  * <li>java.sql.Timestamp (no default value)</li>
  143.  * <li>java.time.LocalDate (no default value)</li>
  144.  * <li>java.time.LocalDateTime (no default value)</li>
  145.  * <li>java.time.LocalTime (no default value)</li>
  146.  * <li>java.time.OffsetDateTime (no default value)</li>
  147.  * <li>java.time.OffsetTime (no default value)</li>
  148.  * <li>java.time.ZonedDateTime (no default value)</li>
  149.  * <li>java.time.Duration (no default value)</li>
  150.  * <li>java.time.MonthDay (no default value)</li>
  151.  * <li>java.util.regex.Pattern (no default value)</li>
  152.  * <li>java.time.Period (no default value)</li>
  153.  * <li>java.awt.Point (no default value)</li>
  154.  * <li>java.time.Year (no default value)</li>
  155.  * <li>java.time.YearMonth (no default value)</li>
  156.  * <li>java.time.ZoneId (no default value)</li>
  157.  * <li>java.time.ZoneOffset (no default value)</li>
  158.  * </ul>
  159.  *
  160.  * <p>
  161.  * For backwards compatibility, the standard Converters for primitive types (and the corresponding wrapper classes) return a defined default value when a
  162.  * conversion error occurs. If you prefer to have a {@link ConversionException} thrown instead, replace the standard Converter instances with instances created
  163.  * with the zero-arguments constructor. For example, to cause the Converters for integers to throw an exception on conversion errors, you could do this:
  164.  * </p>
  165.  *
  166.  * <pre>
  167.  * // No-args constructor gets the version that throws exceptions
  168.  * Converter myConverter = new org.apache.commons.beanutils2.converter.IntegerConverter();
  169.  * ConvertUtils.register(myConverter, Integer.TYPE); // Native type
  170.  * ConvertUtils.register(myConverter, Integer.class); // Wrapper class
  171.  * </pre>
  172.  *
  173.  * <p>
  174.  * Converters generally treat null input as if it were invalid input, that is, they return their default value if one was specified when the converter was
  175.  * constructed, and throw an exception otherwise. If you prefer nulls to be preserved for converters that are converting to objects (not primitives) then
  176.  * register a converter as above, passing a default value of null to the converter constructor (and of course registering that converter only for the .class
  177.  * target).
  178.  * </p>
  179.  *
  180.  * <p>
  181.  * When a converter is listed above as having no default value, then that converter will throw an exception when passed null or an invalid value as its input.
  182.  * In particular, by default the BigInteger and BigDecimal converters have no default (and are therefore somewhat inconsistent with the other numerical
  183.  * converters which all have zero as their default).
  184.  * </p>
  185.  *
  186.  * <p>
  187.  * Converters that generate <em>arrays</em> of each of the primitive types are also automatically configured (including String[]). When passed null or invalid
  188.  * input, these return an empty array (not null). See class AbstractArrayConverter for the supported input formats for these converters.
  189.  * </p>
  190.  *
  191.  * @since 1.7
  192.  */
  193. public class ConvertUtilsBean {

  194.     private static final Integer ZERO = Integer.valueOf(0);
  195.     private static final Character SPACE = Character.valueOf(' ');

  196.     /**
  197.      * The {@code Log} instance for this class.
  198.      */
  199.     private static final Log LOG = LogFactory.getLog(ConvertUtilsBean.class);

  200.     /**
  201.      * Gets singleton instance
  202.      *
  203.      * @return The singleton instance
  204.      */
  205.     protected static ConvertUtilsBean getInstance() {
  206.         return BeanUtilsBean.getInstance().getConvertUtils();
  207.     }

  208.     /**
  209.      * The set of {@link Converter}s that can be used to convert Strings into objects of a specified Class, keyed by the destination Class.
  210.      */
  211.     private final Map<Class<?>, Converter<?>> converters = BeanUtils.createCache();

  212.     /** Constructs a bean with standard converters registered */
  213.     public ConvertUtilsBean() {
  214.         deregister();
  215.     }

  216.     /**
  217.      * Delegates to the new {@link ConvertUtilsBean#convert(Object, Class)} method.
  218.      *
  219.      * @param value Value to be converted (may be null)
  220.      * @return The converted String value or null if value is null
  221.      * @see ConvertUtilsBean#convert(String[], Class)
  222.      */
  223.     public String convert(final Object value) {
  224.         return (String) convert(value, String.class);
  225.     }

  226.     /**
  227.      * Converts the value to an object of the specified class (if possible). If no converter for the desired target type is registered, the passed in object is
  228.      * returned unchanged.
  229.      *
  230.      * @param <T>        The Class type.
  231.      * @param value      Value to be converted (may be null)
  232.      * @param targetType Class of the value to be converted to (must not be null)
  233.      * @return The converted value
  234.      * @throws ConversionException if thrown by an underlying Converter
  235.      */
  236.     public <T> Object convert(final Object value, final Class<T> targetType) {
  237.         final boolean nullValue = value == null;
  238.         final Class<?> sourceType = nullValue ? null : value.getClass();

  239.         if (LOG.isDebugEnabled()) {
  240.             if (nullValue) {
  241.                 LOG.debug("Convert null value to type '" + targetType.getName() + "'");
  242.             } else {
  243.                 LOG.debug("Convert type '" + sourceType.getName() + "' value '" + value + "' to type '" + targetType.getName() + "'");
  244.             }
  245.         }

  246.         Object converted = value;
  247.         final Converter<T> converter = lookup(sourceType, targetType);
  248.         if (converter != null) {
  249.             if (LOG.isTraceEnabled()) {
  250.                 LOG.trace("  Using converter " + converter);
  251.             }
  252.             converted = converter.convert(targetType, value);
  253.         }
  254.         if (String.class.equals(targetType) && converted != null && !(converted instanceof String)) {

  255.             // NOTE: For backwards compatibility, if the Converter
  256.             // doesn't handle conversion-->String then
  257.             // use the registered String Converter
  258.             final Converter<String> strConverter = lookup(String.class);
  259.             if (strConverter != null) {
  260.                 if (LOG.isTraceEnabled()) {
  261.                     LOG.trace("  Using converter " + converter);
  262.                 }
  263.                 converted = strConverter.convert(String.class, converted);
  264.             }

  265.             // If the object still isn't a String, use toString() method
  266.             if (converted != null && !(converted instanceof String)) {
  267.                 converted = converted.toString();
  268.             }

  269.         }
  270.         return converted;
  271.     }

  272.     /**
  273.      * Delegates to the new {@link ConvertUtilsBean#convert(Object, Class)} method.
  274.      *
  275.      * @param <R> the type of the class for the return value.
  276.      * @param value Value to be converted (may be null)
  277.      * @param clazz Java class to be converted to (must not be null)
  278.      * @return The converted value or null if value is null
  279.      * @see ConvertUtilsBean#convert(String[], Class)
  280.      */
  281.     public <R> Object convert(final String value, final Class<R> clazz) {
  282.         return convert((Object) value, clazz);
  283.     }

  284.     /**
  285.      * Delegates to the new {@link ConvertUtilsBean#convert(Object, Class)} method.
  286.      *
  287.      * @param <T> the type of the class for the return value.
  288.      * @param value Array of values to be converted
  289.      * @param clazz Java array or element class to be converted to (must not be null)
  290.      * @return The converted value
  291.      * @see ConvertUtilsBean#convert(String[], Class)
  292.      */
  293.     public <T> Object convert(final String[] value, final Class<T> clazz) {
  294.         return convert((Object) value, clazz);
  295.     }

  296.     private <T> Object convert(final String[] values, final Class<T> type, final Converter<T> converter) {
  297.         if (LOG.isTraceEnabled()) {
  298.             LOG.trace("  Using converter " + converter);
  299.         }
  300.         final Object array = Array.newInstance(type, values.length);
  301.         for (int i = 0; i < values.length; i++) {
  302.             Array.set(array, i, converter.convert(type, values[i]));
  303.         }
  304.         return array;
  305.     }

  306.     /**
  307.      * Deregisters all registered {@link Converter}s, and re-establish the standard Converters.
  308.      */
  309.     public void deregister() {

  310.         converters.clear();

  311.         registerPrimitives(false);
  312.         registerStandard(false, false);
  313.         registerOther(true);
  314.         registerArrays(false, 0);
  315.         register(BigDecimal.class, new BigDecimalConverter());
  316.         register(BigInteger.class, new BigIntegerConverter());
  317.     }

  318.     /**
  319.      * Remove any registered {@link Converter} for the specified destination {@code Class}.
  320.      *
  321.      * @param clazz Class for which to remove a registered Converter
  322.      */
  323.     public void deregister(final Class<?> clazz) {
  324.         converters.remove(clazz);
  325.     }

  326.     /**
  327.      * Looks up and return any registered {@link Converter} for the specified source and destination class; if there is no registered Converter, return
  328.      * {@code null}.
  329.      *
  330.      * @param <T>        The converter type.
  331.      * @param sourceType Class of the value being converted
  332.      * @param targetType Class of the value to be converted to
  333.      * @return The registered {@link Converter} or {@code null} if not found
  334.      */
  335.     public <T> Converter<T> lookup(final Class<?> sourceType, final Class<T> targetType) {
  336.         Objects.requireNonNull(targetType, "targetType");
  337.         if (sourceType == null) {
  338.             return lookup(targetType);
  339.         }
  340.         Converter converter = null;
  341.         // Convert --> String
  342.         if (targetType == String.class) {
  343.             converter = lookup(sourceType);
  344.             if (converter == null && (sourceType.isArray() || Collection.class.isAssignableFrom(sourceType))) {
  345.                 converter = lookup(String[].class);
  346.             }
  347.             if (converter == null) {
  348.                 converter = lookup(String.class);
  349.             }
  350.             return converter;
  351.         }

  352.         // Convert --> String array
  353.         if (targetType == String[].class) {
  354.             if (sourceType.isArray() || Collection.class.isAssignableFrom(sourceType)) {
  355.                 converter = lookup(sourceType);
  356.             }
  357.             if (converter == null) {
  358.                 converter = lookup(String[].class);
  359.             }
  360.             return converter;
  361.         }

  362.         return lookup(targetType);

  363.     }

  364.     /**
  365.      * Looks up and return any registered {@link Converter} for the specified destination class; if there is no registered Converter, return {@code null}.
  366.      *
  367.      * @param <T>   The converter type.
  368.      * @param clazz Class for which to return a registered Converter
  369.      * @return The registered {@link Converter} or {@code null} if not found
  370.      */
  371.     @SuppressWarnings("unchecked")
  372.     public <T> Converter<T> lookup(final Class<T> clazz) {
  373.         return (Converter<T>) converters.get(clazz);
  374.     }

  375.     /**
  376.      * Registers the provided converters with the specified defaults.
  377.      *
  378.      * @param throwException   {@code true} if the converters should throw an exception when a conversion error occurs, otherwise {@code false} if a default
  379.      *                         value should be used.
  380.      * @param defaultNull      {@code true}if the <em>standard</em> converters (see {@link ConvertUtilsBean#registerStandard(boolean, boolean)}) should use a
  381.      *                         default value of {@code null</code>, otherwise <code>false}.
  382.      * N.B. This values is ignored if {@code throwException</code> is <code>true}
  383.      * @param defaultArraySize The size of the default array value for array converters
  384.      * (N.B. This values is ignored if {@code throwException</code> is <code>true}). Specifying a value less than zero causes a {@code null} value to be used
  385.      * for the default.
  386.      */
  387.     public void register(final boolean throwException, final boolean defaultNull, final int defaultArraySize) {
  388.         registerPrimitives(throwException);
  389.         registerStandard(throwException, defaultNull);
  390.         registerOther(throwException);
  391.         registerArrays(throwException, defaultArraySize);
  392.     }

  393.     /** Strictly for convenience since it has same parameter order as Map.put */
  394.     private <T> void register(final Class<?> clazz, final Converter<T> converter) {
  395.         register(new ConverterFacade<>(converter), clazz);
  396.     }

  397.     /**
  398.      * Registers a custom {@link Converter} for the specified destination {@code Class}, replacing any previously registered Converter.
  399.      *
  400.      * @param converter Converter to be registered
  401.      * @param clazz     Destination class for conversions performed by this Converter
  402.      */
  403.     public void register(final Converter converter, final Class<?> clazz) {
  404.         converters.put(clazz, converter);
  405.     }

  406.     /**
  407.      * Registers a new ArrayConverter with the specified element delegate converter that returns a default array of the specified size in the event of
  408.      * conversion errors.
  409.      *
  410.      * @param componentType      The component type of the array
  411.      * @param componentConverter The converter to delegate to for the array elements
  412.      * @param throwException     Whether a conversion exception should be thrown or a default value used in the event of a conversion error
  413.      * @param defaultArraySize   The size of the default array
  414.      */
  415.     private <T> void registerArrayConverter(final Class<T> componentType, final Converter<T> componentConverter, final boolean throwException,
  416.             final int defaultArraySize) {
  417.         final Class<T[]> arrayType = (Class<T[]>) Array.newInstance(componentType, 0).getClass();
  418.         final Converter<T[]> arrayConverter;
  419.         if (throwException) {
  420.             arrayConverter = new ArrayConverter<>(arrayType, componentConverter);
  421.         } else {
  422.             arrayConverter = new ArrayConverter<>(arrayType, componentConverter, defaultArraySize);
  423.         }
  424.         register(arrayType, arrayConverter);
  425.     }

  426.     /**
  427.      * Registers array converters.
  428.      *
  429.      * @param throwException   {@code true} if the converters should throw an exception when a conversion error occurs, otherwise {@code false} if a default
  430.      *                         value should be used.
  431.      * @param defaultArraySize The size of the default array value for array converters (N.B. This values is ignored if
  432.      *                         {@code throwException</code> is <code>true}). Specifying a value less than zero causes a {@code null} value to be used for the
  433.      *                         default.
  434.      */
  435.     private void registerArrays(final boolean throwException, final int defaultArraySize) {
  436.         // @formatter:off

  437.         // Primitives
  438.         registerArrayConverter(Boolean.TYPE,   new BooleanConverter(),   throwException, defaultArraySize);
  439.         registerArrayConverter(Byte.TYPE,      new ByteConverter(),      throwException, defaultArraySize);
  440.         registerArrayConverter(Character.TYPE, new CharacterConverter(), throwException, defaultArraySize);
  441.         registerArrayConverter(Double.TYPE,    new DoubleConverter(),    throwException, defaultArraySize);
  442.         registerArrayConverter(Float.TYPE,     new FloatConverter(),     throwException, defaultArraySize);
  443.         registerArrayConverter(Integer.TYPE,   new IntegerConverter(),   throwException, defaultArraySize);
  444.         registerArrayConverter(Long.TYPE,      new LongConverter(),      throwException, defaultArraySize);
  445.         registerArrayConverter(Short.TYPE,     new ShortConverter(),     throwException, defaultArraySize);

  446.         // Standard
  447.         registerArrayConverter(BigDecimal.class, new BigDecimalConverter(), throwException, defaultArraySize);
  448.         registerArrayConverter(BigInteger.class, new BigIntegerConverter(), throwException, defaultArraySize);
  449.         registerArrayConverter(Boolean.class,    new BooleanConverter(),    throwException, defaultArraySize);
  450.         registerArrayConverter(Byte.class,       new ByteConverter(),       throwException, defaultArraySize);
  451.         registerArrayConverter(Character.class,  new CharacterConverter(),  throwException, defaultArraySize);
  452.         registerArrayConverter(Double.class,     new DoubleConverter(),     throwException, defaultArraySize);
  453.         registerArrayConverter(Float.class,      new FloatConverter(),      throwException, defaultArraySize);
  454.         registerArrayConverter(Integer.class,    new IntegerConverter(),    throwException, defaultArraySize);
  455.         registerArrayConverter(Long.class,       new LongConverter(),       throwException, defaultArraySize);
  456.         registerArrayConverter(Short.class,      new ShortConverter(),      throwException, defaultArraySize);
  457.         registerArrayConverter(String.class,     new StringConverter(),     throwException, defaultArraySize);

  458.         // Other
  459.         registerArrayConverter(Class.class,          new ClassConverter(),         throwException, defaultArraySize);
  460.         registerArrayConverter(Color.class,          new ColorConverter(),         throwException, defaultArraySize);
  461.         registerArrayConverter(Enum.class,           new EnumConverter(),          throwException, defaultArraySize);
  462.         registerArrayConverter(java.util.Date.class, new DateConverter(),          throwException, defaultArraySize);
  463.         registerArrayConverter(Calendar.class,       new CalendarConverter(),      throwException, defaultArraySize);
  464.         registerArrayConverter(Dimension.class,      new DimensionConverter(),     throwException, defaultArraySize);
  465.         registerArrayConverter(File.class,           new FileConverter(),          throwException, defaultArraySize);
  466.         registerArrayConverter(InetAddress.class,    new InetAddressConverter(),   throwException, defaultArraySize);
  467.         registerArrayConverter(Path.class,           new PathConverter(),          throwException, defaultArraySize);
  468.         registerArrayConverter(java.sql.Date.class,  new SqlDateConverter(),       throwException, defaultArraySize);
  469.         registerArrayConverter(java.sql.Time.class,  new SqlTimeConverter(),       throwException, defaultArraySize);
  470.         registerArrayConverter(Timestamp.class,      new SqlTimestampConverter(),  throwException, defaultArraySize);
  471.         registerArrayConverter(URL.class,            new URLConverter(),           throwException, defaultArraySize);
  472.         registerArrayConverter(URI.class,            new URIConverter(),           throwException, defaultArraySize);
  473.         registerArrayConverter(UUID.class,           new UUIDConverter(),          throwException, defaultArraySize);
  474.         registerArrayConverter(LocalDate.class,      new LocalDateConverter(),     throwException, defaultArraySize);
  475.         registerArrayConverter(LocalDateTime.class,  new LocalDateTimeConverter(), throwException, defaultArraySize);
  476.         registerArrayConverter(LocalTime.class,      new LocalTimeConverter(),     throwException, defaultArraySize);
  477.         registerArrayConverter(Locale.class,         new LocaleConverter(),        throwException, defaultArraySize);
  478.         registerArrayConverter(OffsetDateTime.class, new OffsetDateTimeConverter(),throwException, defaultArraySize);
  479.         registerArrayConverter(OffsetTime.class,     new OffsetTimeConverter(),    throwException, defaultArraySize);
  480.         registerArrayConverter(ZonedDateTime.class,  new ZonedDateTimeConverter(), throwException, defaultArraySize);
  481.         registerArrayConverter(Duration.class,       new DurationConverter(),      throwException, defaultArraySize);
  482.         registerArrayConverter(MonthDay.class,       new MonthDayConverter(),      throwException, defaultArraySize);
  483.         registerArrayConverter(Pattern.class,        new PatternConverter(),       throwException, defaultArraySize);
  484.         registerArrayConverter(Period.class,         new PeriodConverter(),        throwException, defaultArraySize);
  485.         registerArrayConverter(Point.class,          new PointConverter(),         throwException, defaultArraySize);
  486.         registerArrayConverter(Year.class,           new YearConverter(),          throwException, defaultArraySize);
  487.         registerArrayConverter(YearMonth.class,      new YearMonthConverter(),     throwException, defaultArraySize);
  488.         registerArrayConverter(ZoneId.class,         new ZoneIdConverter(),        throwException, defaultArraySize);
  489.         registerArrayConverter(ZoneOffset.class,     new ZoneOffsetConverter(),    throwException, defaultArraySize);
  490.         // @formatter:on
  491.     }

  492.     /**
  493.      * Registers the converters for other types.
  494.      * </p>
  495.      * This method registers the following converters:
  496.      * <ul>
  497.      * <li>{@code Class.class} - {@link ClassConverter}</li>
  498.      * <li>{@code Enum.class} - {@link EnumConverter}</li>
  499.      * <li>{@code java.util.Date.class} - {@link DateConverter}</li>
  500.      * <li>{@code java.util.Calendar.class} - {@link CalendarConverter}</li>
  501.      * <li>{@code File.class} - {@link FileConverter}</li>
  502.      * <li>{@code Path.class} - {@link PathConverter}</li>
  503.      * <li>{@code java.sql.Date.class} - {@link SqlDateConverter}</li>
  504.      * <li>{@code java.sql.Time.class} - {@link SqlTimeConverter}</li>
  505.      * <li>{@code java.sql.Timestamp.class} - {@link SqlTimestampConverter}</li>
  506.      * <li>{@code URL.class} - {@link URLConverter}</li>
  507.      * <li>{@code URI.class} - {@link URIConverter}</li>
  508.      * <li>{@code UUID.class} - {@link UUIDConverter}</li>
  509.      * <li>{@code LocalDate.class} - {@link LocalDateConverter}</li>
  510.      * <li>{@code LocalDateTime.class} - {@link LocalDateTimeConverter}</li>
  511.      * <li>{@code LocalTime.class} - {@link LocalTimeConverter}</li>
  512.      * <li>{@code OffsetDateTime.class} - {@link OffsetDateTimeConverter}</li>
  513.      * <li>{@code OffsetTime.class} - {@link OffsetTimeConverter}</li>
  514.      * <li>{@code ZonedDateTime.class} - {@link ZonedDateTimeConverter}</li>
  515.      * <li>{@code Duration.class} - {@link DurationConverter}</li>
  516.      * <li>{@code MonthDay.class} - {@link MonthDayConverter}</li>
  517.      * <li>{@code Period.class} - {@link PeriodConverter}</li>
  518.      * <li>{@code Year.class} - {@link YearConverter}</li>
  519.      * <li>{@code YearMonth.class} - {@link YearMonthConverter}</li>
  520.      * <li>{@code ZoneId.class} - {@link ZoneIdConverter}</li>
  521.      * <li>{@code ZoneOffset.class} - {@link ZoneOffsetConverter}</li>
  522.      * </ul>
  523.      *
  524.      * @param throwException {@code true} if the converters should throw an exception when a conversion error occurs, otherwise <code> {@code false} if a
  525.      *                       default value should be used.
  526.      */
  527.     private void registerOther(final boolean throwException) {
  528.         // @formatter:off
  529.         register(Class.class,          throwException ? new ClassConverter<>()        : new ClassConverter<>(null));
  530.         register(Color.class,          throwException ? new ColorConverter()          : new ColorConverter(null));
  531.         register(Enum.class,           throwException ? new EnumConverter()           : new EnumConverter(null));
  532.         register(java.util.Date.class, throwException ? new DateConverter()           : new DateConverter(null));
  533.         register(Dimension.class,      throwException ? new DimensionConverter()      : new DimensionConverter(null));
  534.         register(Calendar.class,       throwException ? new CalendarConverter()       : new CalendarConverter(null));
  535.         register(File.class,           throwException ? new FileConverter()           : new FileConverter(null));
  536.         register(InetAddress.class,    throwException ? new InetAddressConverter()    : new InetAddressConverter(null));
  537.         register(Path.class,           throwException ? new PathConverter()           : new PathConverter(null));
  538.         register(java.sql.Date.class,  throwException ? new SqlDateConverter()        : new SqlDateConverter(null));
  539.         register(java.sql.Time.class,  throwException ? new SqlTimeConverter()        : new SqlTimeConverter(null));
  540.         register(Timestamp.class,      throwException ? new SqlTimestampConverter()   : new SqlTimestampConverter(null));
  541.         register(URL.class,            throwException ? new URLConverter()            : new URLConverter(null));
  542.         register(URI.class,            throwException ? new URIConverter()            : new URIConverter(null));
  543.         register(UUID.class,           throwException ? new UUIDConverter()           : new UUIDConverter(null));
  544.         register(LocalDate.class,      throwException ? new LocalDateConverter()      : new LocalDateConverter(null));
  545.         register(LocalDateTime.class,  throwException ? new LocalDateTimeConverter()  : new LocalDateTimeConverter(null));
  546.         register(LocalTime.class,      throwException ? new LocalTimeConverter()      : new LocalTimeConverter(null));
  547.         register(Locale.class,         throwException ? new LocaleConverter()         : new LocaleConverter(null));
  548.         register(OffsetDateTime.class, throwException ? new OffsetDateTimeConverter() : new OffsetDateTimeConverter(null));
  549.         register(OffsetTime.class,     throwException ? new OffsetTimeConverter()     : new OffsetTimeConverter(null));
  550.         register(ZonedDateTime.class,  throwException ? new ZonedDateTimeConverter()  : new ZonedDateTimeConverter(null));
  551.         register(Duration.class,       throwException ? new DurationConverter()       : new DurationConverter(null));
  552.         register(MonthDay.class,       throwException ? new MonthDayConverter()       : new MonthDayConverter(null));
  553.         register(Pattern.class,        throwException ? new PatternConverter()        : new PatternConverter(null));
  554.         register(Period.class,         throwException ? new PeriodConverter()         : new PeriodConverter(null));
  555.         register(Point.class,          throwException ? new PointConverter()          : new PointConverter(null));
  556.         register(Year.class,           throwException ? new YearConverter()           : new YearConverter(null));
  557.         register(YearMonth.class,      throwException ? new YearMonthConverter()      : new YearMonthConverter(null));
  558.         register(ZoneId.class,         throwException ? new ZoneIdConverter()         : new ZoneIdConverter(null));
  559.         register(ZoneOffset.class,     throwException ? new ZoneOffsetConverter()     : new ZoneOffsetConverter(null));
  560.         // @formatter:on
  561.     }

  562.     /**
  563.      * Registers the converters for primitive types.
  564.      * </p>
  565.      * This method registers the following converters:
  566.      * <ul>
  567.      * <li>{@code Boolean.TYPE} - {@link BooleanConverter}</li>
  568.      * <li>{@code Byte.TYPE} - {@link ByteConverter}</li>
  569.      * <li>{@code Character.TYPE} - {@link CharacterConverter}</li>
  570.      * <li>{@code Double.TYPE} - {@link DoubleConverter}</li>
  571.      * <li>{@code Float.TYPE} - {@link FloatConverter}</li>
  572.      * <li>{@code Integer.TYPE} - {@link IntegerConverter}</li>
  573.      * <li>{@code Long.TYPE} - {@link LongConverter}</li>
  574.      * <li>{@code Short.TYPE} - {@link ShortConverter}</li>
  575.      * </ul>
  576.      *
  577.      * @param throwException {@code true} if the converters should throw an exception when a conversion error occurs, otherwise <code> {@code false} if a
  578.      *                       default value should be used.
  579.      */
  580.     private void registerPrimitives(final boolean throwException) {
  581.         register(Boolean.TYPE, throwException ? new BooleanConverter() : new BooleanConverter(Boolean.FALSE));
  582.         register(Byte.TYPE, throwException ? new ByteConverter() : new ByteConverter(ZERO));
  583.         register(Character.TYPE, throwException ? new CharacterConverter() : new CharacterConverter(SPACE));
  584.         register(Double.TYPE, throwException ? new DoubleConverter() : new DoubleConverter(ZERO));
  585.         register(Float.TYPE, throwException ? new FloatConverter() : new FloatConverter(ZERO));
  586.         register(Integer.TYPE, throwException ? new IntegerConverter() : new IntegerConverter(ZERO));
  587.         register(Long.TYPE, throwException ? new LongConverter() : new LongConverter(ZERO));
  588.         register(Short.TYPE, throwException ? new ShortConverter() : new ShortConverter(ZERO));
  589.     }

  590.     /**
  591.      * Registers the converters for standard types.
  592.      * </p>
  593.      * This method registers the following converters:
  594.      * <ul>
  595.      * <li>{@code BigDecimal.class} - {@link BigDecimalConverter}</li>
  596.      * <li>{@code BigInteger.class} - {@link BigIntegerConverter}</li>
  597.      * <li>{@code Boolean.class} - {@link BooleanConverter}</li>
  598.      * <li>{@code Byte.class} - {@link ByteConverter}</li>
  599.      * <li>{@code Character.class} - {@link CharacterConverter}</li>
  600.      * <li>{@code Double.class} - {@link DoubleConverter}</li>
  601.      * <li>{@code Float.class} - {@link FloatConverter}</li>
  602.      * <li>{@code Integer.class} - {@link IntegerConverter}</li>
  603.      * <li>{@code Long.class} - {@link LongConverter}</li>
  604.      * <li>{@code Short.class} - {@link ShortConverter}</li>
  605.      * <li>{@code String.class} - {@link StringConverter}</li>
  606.      * </ul>
  607.      *
  608.      * @param throwException {@code true} if the converters should throw an exception when a conversion error occurs, otherwise <code>
  609.      *                       {@code false} if a default value should be used.
  610.      * @param defaultNull {@code true}if the <em>standard</em> converters
  611.      * (see {@link ConvertUtilsBean#registerStandard(boolean, boolean)})
  612.      * should use a default value of {@code null</code>, otherwise <code>false}.
  613.      * N.B. This values is ignored if {@code throwException</code> is <code>true}
  614.      */
  615.     private void registerStandard(final boolean throwException, final boolean defaultNull) {

  616.         final Number defaultNumber = defaultNull ? null : ZERO;
  617.         final BigDecimal bigDecDeflt = defaultNull ? null : new BigDecimal("0.0");
  618.         final BigInteger bigIntDeflt = defaultNull ? null : new BigInteger("0");
  619.         final Boolean booleanDefault = defaultNull ? null : Boolean.FALSE;
  620.         final Character charDefault = defaultNull ? null : SPACE;
  621.         final String stringDefault = defaultNull ? null : "";

  622.         register(BigDecimal.class, throwException ? new BigDecimalConverter() : new BigDecimalConverter(bigDecDeflt));
  623.         register(BigInteger.class, throwException ? new BigIntegerConverter() : new BigIntegerConverter(bigIntDeflt));
  624.         register(Boolean.class, throwException ? new BooleanConverter() : new BooleanConverter(booleanDefault));
  625.         register(Byte.class, throwException ? new ByteConverter() : new ByteConverter(defaultNumber));
  626.         register(Character.class, throwException ? new CharacterConverter() : new CharacterConverter(charDefault));
  627.         register(Double.class, throwException ? new DoubleConverter() : new DoubleConverter(defaultNumber));
  628.         register(Float.class, throwException ? new FloatConverter() : new FloatConverter(defaultNumber));
  629.         register(Integer.class, throwException ? new IntegerConverter() : new IntegerConverter(defaultNumber));
  630.         register(Long.class, throwException ? new LongConverter() : new LongConverter(defaultNumber));
  631.         register(Short.class, throwException ? new ShortConverter() : new ShortConverter(defaultNumber));
  632.         register(String.class, throwException ? new StringConverter() : new StringConverter(stringDefault));

  633.     }
  634. }