Class Converter

java.lang.Object
com.cedarsoftware.util.convert.Converter

public final class Converter extends Object
Instance conversion utility for converting objects between various types.

Supports conversion from primitive types to their corresponding wrapper classes, Number classes, Date and Time classes (e.g., Date, Timestamp, LocalDate, LocalDateTime, ZonedDateTime, Calendar), BigInteger, BigDecimal, Atomic classes (e.g., AtomicBoolean, AtomicInteger, AtomicLong), Class, UUID, String, Collection classes (e.g., List, Set, Map), ByteBuffer, CharBuffer, and other related classes.

The Converter includes thousands of built-in conversions. Use the getSupportedConversions() API to view all source-to-target conversion mappings.

The primary API is convert(Object, Class). For example:


     Long x = convert("35", Long.class);
     Date d = convert("2015/01/01", Date.class);
     int y = convert(45.0, int.class);
     String dateStr = convert(date, String.class);
     String dateStr = convert(calendar, String.class);
     Short t = convert(true, short.class);     // returns (short) 1 or 0
     Long time = convert(calendar, long.class); // retrieves calendar's time as long
     Map<String, Object> map = Map.of("_v", "75.0");
     Double value = convert(map, double.class); // Extracts "_v" key and converts it
 

Null Handling: If a null value is passed as the source, the Converter returns:

  • null for object types
  • 0 for numeric primitive types
  • false for boolean primitives
  • '' for char primitives

Map Conversions: A Map can be converted to almost all supported JDK data classes. For example, UUID can be converted to/from a Map with keys like "mostSigBits" and "leastSigBits". Date/Time classes expect specific keys such as "time" or "nanos". For other classes, the Converter typically looks for a "value" key to source the conversion.

Extensibility: Additional conversions can be added by specifying the source class, target class, and a conversion function (e.g., a lambda). Use the addConversion(Class, Class, Convert) method to register custom converters. This allows for the inclusion of new Collection types and other custom types as needed.

Supported Collection Conversions: The Converter supports conversions involving various Collection types, including but not limited to:

These conversions facilitate seamless transformation between different Collection types and other supported classes.

Usage Example:


     ConverterOptions options = new ConverterOptions();
     Converter converter = new Converter(options);

     // Convert String to Integer
     Integer number = converter.convert("123", Integer.class);

     // Convert Enum to String
     Day day = Day.MONDAY;
     String dayStr = converter.convert(day, String.class);

     // Convert Object[], String[], Collection, and primitive Arrays to EnumSet
     Object[] array = {Day.MONDAY, Day.WEDNESDAY, "FRIDAY", 4};
     EnumSet<Day> daySet = (EnumSet<Day>)(Object)converter.convert(array, Day.class);

     Enum, String, and Number value in the source collection/array is properly converted
     to the correct Enum type and added to the returned EnumSet. Null values inside the
     source (Object[], Collection) are skipped.

     When converting arrays or collections to EnumSet, you must use a double cast due to Java's
     type system and generic type erasure. The cast is safe as the converter guarantees return of
     an EnumSet when converting arrays/collections to enum types.

     // Add a custom conversion from String to CustomType
     converter.addConversion(String.class, CustomType.class, (from, conv) -> new CustomType(from));

     // Convert using the custom converter
     CustomType custom = converter.convert("customValue", CustomType.class);
 

Module Dependencies:

  • SQL support: Conversions involving java.sql.Date and java.sql.Timestamp require the java.sql module to be present at runtime. If you're using OSGi, ensure your bundle imports the java.sql package or declare it as an optional import if SQL support is not required.
  • XML support: This library does not directly use XML classes, but IOUtilities provides XML stream support that requires the java.xml module. See IOUtilities for more details.
Author:
John DeRegnaucourt ([email protected]) Copyright (c) Cedar Software LLC

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

License

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  • Field Details

  • Constructor Details

    • Converter

      public Converter(ConverterOptions options)
      Constructs a new Converter instance with the specified options.

      The Converter initializes its internal conversion databases by merging the predefined CONVERSION_DB with any user-specified overrides provided in options.

      Parameters:
      options - The ConverterOptions that configure this Converter's behavior and conversions.
      Throws:
      NullPointerException - if options is null.
  • Method Details

    • pair

      public static Converter.ConversionPair pair(Class<?> source, Class<?> target, long instanceId)
    • pair

      public static Converter.ConversionPair pair(Class<?> source, Class<?> target)
    • getOptions

      public ConverterOptions getOptions()
      Retrieves the converter options associated with this Converter instance.
      Returns:
      The ConverterOptions used by this Converter.
    • convert

      public <T> T convert(Object from, Class<T> toType)
      Converts the given source object to the specified target type.

      The convert method serves as the primary API for transforming objects between various types. It supports a wide range of conversions, including primitive types, wrapper classes, numeric types, date and time classes, collections, and custom objects. Additionally, it allows for extensibility by enabling the registration of custom converters.

      Key Features:

      • Wide Range of Supported Types: Supports conversion between Java primitives, their corresponding wrapper classes, Number subclasses, date and time classes (e.g., Date, LocalDateTime), collections (e.g., List, Set, Map), UUID, and more.
      • Null Handling: Gracefully handles null inputs by returning null for object types, default primitive values (e.g., 0 for numeric types, false for boolean), and default characters.
      • Inheritance-Based Conversions: Automatically considers superclass and interface hierarchies to find the most suitable converter when a direct conversion is not available.
      • Custom Converters: Allows users to register custom conversion logic for specific source-target type pairs using the addConversion(Class, Class, Convert) method.
      • Thread-Safe: Designed to be thread-safe, allowing concurrent conversions without compromising data integrity.

      Usage Examples:

      
           ConverterOptions options = new ConverterOptions();
           Converter converter = new Converter(options);
      
           // Example 1: Convert String to Integer
           String numberStr = "123";
           Integer number = converter.convert(numberStr, Integer.class);
           LOG.info("Converted Integer: " + number); // Output: Converted Integer: 123
      
           // Example 2: Convert String to Date
           String dateStr = "2024-04-27";
           LocalDate date = converter.convert(dateStr, LocalDate.class);
           LOG.info("Converted Date: " + date); // Output: Converted Date: 2024-04-27
      
           // Example 3: Convert Enum to String
           Day day = Day.MONDAY;
           String dayStr = converter.convert(day, String.class);
           LOG.info("Converted Day: " + dayStr); // Output: Converted Day: MONDAY
      
           // Example 4: Convert Array to List
           String[] stringArray = {"apple", "banana", "cherry"};
           List<String> stringList = converter.convert(stringArray, List.class);
           LOG.info("Converted List: " + stringList); // Output: Converted List: [apple, banana, cherry]
      
           // Example 5: Convert Map to UUID
           Map<String, Object> uuidMap = Map.of("mostSigBits", 123456789L, "leastSigBits", 987654321L);
           UUID uuid = converter.convert(uuidMap, UUID.class);
           LOG.info("Converted UUID: " + uuid); // Output: Converted UUID: 00000000-075b-cd15-0000-0000003ade68
      
           // Example 6: Convert Object[], String[], Collection, and primitive Arrays to EnumSet
           Object[] array = {Day.MONDAY, Day.WEDNESDAY, "FRIDAY", 4};
           EnumSet<Day> daySet = (EnumSet<Day>)(Object)converter.convert(array, Day.class);
      
           Enum, String, and Number value in the source collection/array is properly converted
           to the correct Enum type and added to the returned EnumSet. Null values inside the
           source (Object[], Collection) are skipped.
      
           When converting arrays or collections to EnumSet, you must use a double cast due to Java's
           type system and generic type erasure. The cast is safe as the converter guarantees return of
           an EnumSet when converting arrays/collections to enum types.
      
           // Example 7: Register and Use a Custom Converter
           // Custom converter to convert String to CustomType
           converter.addConversion(String.class, CustomType.class, (from, conv) -> new CustomType(from));
      
           String customStr = "customValue";
           CustomType custom = converter.convert(customStr, CustomType.class);
           LOG.info("Converted CustomType: " + custom); // Output: Converted CustomType: CustomType{value='customValue'}
       
       

      Parameter Descriptions:

      • from: The source object to be converted. This can be any object, including null. The actual type of from does not need to match the target type; the Converter will attempt to perform the necessary transformation.
      • toType: The target class to which the source object should be converted. This parameter specifies the desired output type. It can be a primitive type (e.g., int.class), a wrapper class (e.g., Integer.class), or any other supported class.

      Return Value:

      Returns an instance of the specified target type toType, representing the converted value of the source object from. If from is null, the method returns:

      • null for non-primitive target types.
      • Default primitive values for primitive target types (e.g., 0 for numeric types, false for boolean, '' for char).

      Exceptions:

      • IllegalArgumentException: Thrown if the conversion from the source type to the target type is not supported, or if the target type toType is null.
      • RuntimeException: Any underlying exception thrown during the conversion process is propagated as a RuntimeException.

      Supported Conversions:

      The Converter supports a vast array of conversions, including but not limited to:

      Extensibility:

      Users can extend the Converter's capabilities by registering custom converters for specific type pairs. This is achieved using the addConversion(Class, Class, Convert) method, which accepts the source type, target type, and a Convert functional interface implementation that defines the conversion logic.

      Performance Considerations:

      The Converter utilizes caching mechanisms to store and retrieve converters, ensuring efficient performance even with a large number of conversion operations. However, registering an excessive number of custom converters may impact memory usage. It is recommended to register only the necessary converters to maintain optimal performance.

      Type Parameters:
      T - The type of the target object.
      Parameters:
      from - The source object to be converted. Can be any object, including null.
      toType - The target class to which the source object should be converted. Must not be null.
      Returns:
      An instance of toType representing the converted value of from.
      Throws:
      IllegalArgumentException - if toType is null or if the conversion is not supported.
      See Also:
    • isContainerConversionSupported

      public static boolean isContainerConversionSupported(Class<?> sourceType, Class<?> target)
      Determines if a container-based conversion is supported between the specified source and target types. This method checks for valid conversions between arrays, collections, Maps, and EnumSets without actually performing the conversion.

      Supported conversions include:

      • Array to Collection
      • Collection to Array
      • Array to Array (when component types differ)
      • Array, Collection, or Map to EnumSet (when target is an Enum type)
      • EnumSet to Array or Collection

      Parameters:
      sourceType - The source type to convert from
      target - The target type to convert to
      Returns:
      true if a container-based conversion is supported between the types, false otherwise
      Throws:
      IllegalArgumentException - if target is EnumSet.class (caller should specify specific Enum type instead)
    • isCollectionConversionSupported

      @Deprecated public static boolean isCollectionConversionSupported(Class<?> sourceType, Class<?> target)
      Deprecated.
      Use isContainerConversionSupported(Class, Class) instead. This method will be removed in a future version.
    • isSimpleTypeConversionSupported

      public boolean isSimpleTypeConversionSupported(Class<?> source, Class<?> target)
      Determines whether a conversion from the specified source type to the target type is supported, excluding any conversions involving arrays or collections.

      The method is particularly useful when you need to verify that a conversion is possible between simple types without considering array or collection conversions. This can be helpful in scenarios where you need to validate component type conversions separately from their container types.

      Example usage:

      
       Converter converter = new Converter(options);
      
       // Check if String can be converted to Integer
       boolean canConvert = converter.isNonCollectionConversionSupportedFor(
           String.class, Integer.class);  // returns true
      
       // Check array conversion (always returns false)
       boolean arrayConvert = converter.isNonCollectionConversionSupportedFor(
           String[].class, Integer[].class);  // returns false
      
       // Check collection conversion (always returns false)
       boolean listConvert = converter.isNonCollectionConversionSupportedFor(
           List.class, Set.class);  // returns false
       
      Parameters:
      source - The source class type to check
      target - The target class type to check
      Returns:
      true if a non-collection conversion exists between the types, false if either type is an array/collection or no conversion exists
      See Also:
    • isSimpleTypeConversionSupported

      public boolean isSimpleTypeConversionSupported(Class<?> type)
      Overload of isSimpleTypeConversionSupported(Class, Class) that checks if the specified class is considered a simple type. Results are cached for fast subsequent lookups when no custom overrides exist.

      If custom converter overrides exist for the specified type, this method returns false, regardless of inheritance-based conversion support. This ensures that user-defined custom converters take precedence over automatic simple type conversions.

      Parameters:
      type - the class to check
      Returns:
      true if a simple type conversion exists for the class and no custom overrides are registered
    • isConversionSupportedFor

      public boolean isConversionSupportedFor(Class<?> source, Class<?> target)
      Determines whether a conversion from the specified source type to the target type is supported. For array-to-array conversions, this method verifies that both array conversion and component type conversions are supported.

      The method checks three paths for conversion support:

      1. Direct conversions as defined in the conversion maps
      2. Collection/Array/EnumSet conversions - for array-to-array conversions, also verifies that component type conversions are supported
      3. Inherited conversions (via superclasses and implemented interfaces)

      For array conversions, this method performs a deep check to ensure both the array types and their component types can be converted. For example, when checking if a String[] can be converted to Integer[], it verifies both:

      • That array-to-array conversion is supported
      • That String-to-Integer conversion is supported for the components
      Parameters:
      source - The source class type
      target - The target class type
      Returns:
      true if the conversion is fully supported (including component type conversions for arrays), false otherwise
    • isConversionSupportedFor

      public boolean isConversionSupportedFor(Class<?> type)
      Overload of isConversionSupportedFor(Class, Class) that checks whether the specified class can be converted to itself. The result is cached for fast repeat access.
      Parameters:
      type - the class to query
      Returns:
      true if a conversion exists for the class
    • allSupportedConversions

      public static Map<Class<?>,Set<Class<?>>> allSupportedConversions()
      Retrieves a map of all supported conversions, categorized by source and target classes.

      The returned map's keys are source classes, and each key maps to a Set of target classes that the source can be converted to.

      Returns:
      A Map<Class<?>, Set<Class<?>>> representing all supported (built-in) conversions.
    • getSupportedConversions

      public static Map<String,Set<String>> getSupportedConversions()
      Retrieves a map of all supported conversions with class names instead of class objects.

      The returned map's keys are source class names, and each key maps to a Set of target class names that the source can be converted to.

      Returns:
      A Map<String, Set<String>> representing all supported (built-int) conversions by class names.
    • addConversion

      @Deprecated public Convert<?> addConversion(Class<?> source, Class<?> target, Convert<?> conversionMethod)
      Deprecated.
      Use addConversion(Convert, Class, Class) instead. This method will be removed in a future version as it is less safe and does not handle all type variations correctly.
      Parameters:
      conversionMethod - A method that converts an instance of the source type to an instance of the target type.
      Returns:
      The previous conversion method associated with the source and target types, or null if no conversion existed.
    • addConversion

      public Convert<?> addConversion(Convert<?> conversionMethod, Class<?> source, Class<?> target)
      Adds a new conversion function for converting from one type to another for this specific Converter instance.

      When convert(source, target) is called on this instance, the conversion function is located by:

      1. Checking instance-specific conversions first (added via this method)
      2. Checking factory conversions (built-in conversions)
      3. Attempting inheritance-based conversion lookup

      This method automatically handles primitive types by converting them to their corresponding wrapper types and stores conversions for all primitive/wrapper combinations, just like the static version.

      Parameters:
      conversionMethod - A method that converts an instance of the source type to an instance of the target type.
      source - The source class (type) to convert from.
      target - The target class (type) to convert to.
      Returns:
      The previous conversion method associated with the source and target types for this instance, or null if no conversion existed.
    • identity

      public static <T> T identity(T from, Converter converter)
      Performs an identity conversion, returning the source object as-is.
      Type Parameters:
      T - The type of the source and target object.
      Parameters:
      from - The source object.
      converter - The Converter instance performing the conversion.
      Returns:
      The source object unchanged.