001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.conversion;
018
019import java.lang.reflect.*;
020
021/**
022 * Interface for converting objects between types.
023 *
024 * <p>
025 * Use {@link BasicConverter#INSTANCE} for a default singleton implementation that supports
026 * a wide range of common type conversions without requiring a {@code MarshallingContext} or {@code MarshallingSession}.
027 */
028public interface Converter {
029
030   /**
031    * Returns <jk>true</jk> if this converter can convert from the specified input type to the specified output type.
032    *
033    * @param inType The input type.
034    * @param outType The output type.
035    * @return <jk>true</jk> if a conversion path exists.
036    */
037   default boolean canConvert(Class<?> inType, Class<?> outType) {
038      return true;
039   }
040
041   /**
042    * Converts the specified object to the specified type.
043    *
044    * <p>
045    * When the input is <jk>null</jk>, returns the JVM default for primitive types (e.g. {@code 0} for
046    * {@code int.class}, {@code false} for {@code boolean.class}), or <jk>null</jk> for all other types.
047    * Throws {@link InvalidConversionException} when no conversion path exists.
048    * Use {@link #canConvert(Class, Class)} to pre-check if uncertain.
049    *
050    * @param o The object to convert. Can be <jk>null</jk>.
051    * @param type The type to convert to.
052    * @param <T> The type to convert to.
053    * @return The converted object, the primitive zero-value if input is <jk>null</jk> and type is primitive,
054    *    or <jk>null</jk> if the input is <jk>null</jk> and type is non-primitive.
055    * @throws InvalidConversionException If no conversion path exists from the input type to the target type.
056    */
057   <T> T to(Object o, Class<T> type);
058
059   /**
060    * Converts the specified object to the specified parameterized type.
061    *
062    * <p>
063    * This method allows conversion to complex parameterized types such as collections and maps.
064    * The <c>args</c> parameter specifies the type parameters of the main type.
065    *
066    * <p>
067    * Returns <jk>null</jk> only when the input object is <jk>null</jk>.
068    * Throws {@link InvalidConversionException} when no conversion path exists.
069    *
070    * <h5 class='section'>Example:</h5>
071    * <p class='bjava'>
072    *    <jc>// Convert to List&lt;String&gt;</jc>
073    *    List&lt;String&gt; <jv>list</jv> = <jv>converter</jv>.to(<jv>o</jv>, List.<jk>class</jk>, String.<jk>class</jk>);
074    *
075    *    <jc>// Convert to Map&lt;String,Integer&gt;</jc>
076    *    Map&lt;String,Integer&gt; <jv>map</jv> = <jv>converter</jv>.to(<jv>o</jv>, Map.<jk>class</jk>, String.<jk>class</jk>, Integer.<jk>class</jk>);
077    * </p>
078    *
079    * @param o The object to convert. Can be <jk>null</jk>.
080    * @param mainType The main type to convert to.
081    * @param args The type parameters of the main type.
082    * @param <T> The type to convert to.
083    * @return The converted object, or <jk>null</jk> if the input is <jk>null</jk>.
084    * @throws InvalidConversionException If no conversion path exists from the input type to the target type.
085    */
086   <T> T to(Object o, Type mainType, Type...args);
087
088   /**
089    * Converts the specified object to the specified type, using the given outer instance and converter session.
090    *
091    * <p>
092    * The default implementation ignores both {@code memberOf} and {@code session} and delegates to
093    * {@link #to(Object, Class)}.
094    * Override in subclasses that wish to thread these into {@link Conversion#to(Object, Object, ConverterSession, Class[])}.
095    *
096    * @param o The object to convert. Can be <jk>null</jk>.
097    * @param memberOf The outer instance for non-static inner class construction, or <jk>null</jk>.
098    * @param session The converter session providing contextual objects, or <jk>null</jk>.
099    * @param type The type to convert to.
100    * @param <T> The type to convert to.
101    * @return The converted object, or <jk>null</jk> if the input is <jk>null</jk>.
102    * @throws InvalidConversionException If no conversion path exists from the input type to the target type.
103    */
104   default <T> T to(Object o, Object memberOf, ConverterSession session, Class<T> type) {
105      return to(o, type);
106   }
107
108   /**
109    * Converts the specified object to the specified parameterized type, using the given outer instance and converter session.
110    *
111    * <p>
112    * The default implementation ignores both {@code memberOf} and {@code session} and delegates to
113    * {@link #to(Object, Type, Type[])}.
114    * Override in subclasses that wish to thread these into {@link Conversion#to(Object, Object, ConverterSession, Class[])}.
115    *
116    * @param o The object to convert. Can be <jk>null</jk>.
117    * @param memberOf The outer instance for non-static inner class construction, or <jk>null</jk>.
118    * @param session The converter session providing contextual objects, or <jk>null</jk>.
119    * @param mainType The main type to convert to.
120    * @param args The type parameters of the main type.
121    * @param <T> The type to convert to.
122    * @return The converted object, or <jk>null</jk> if the input is <jk>null</jk>.
123    * @throws InvalidConversionException If no conversion path exists from the input type to the target type.
124    */
125   default <T> T to(Object o, Object memberOf, ConverterSession session, Type mainType, Type...args) {
126      return to(o, mainType, args);
127   }
128}