001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.internal;
014
015import java.lang.reflect.*;
016
017import org.apache.juneau.*;
018import org.apache.juneau.parser.*;
019import org.apache.juneau.transform.*;
020
021/**
022 * Utility class for efficiently converting objects between types.
023 *
024 * <p>
025 * If the value isn't an instance of the specified type, then converts the value if possible.
026 *
027 * <p>
028 * The following conversions are valid:
029 * <table class='styled'>
030 *    <tr><th>Convert to type</th><th>Valid input value types</th><th>Notes</th></tr>
031 *    <tr>
032 *       <td>
033 *          A class that is the normal type of a registered {@link PojoSwap}.
034 *       </td>
035 *       <td>
036 *          A value whose class matches the transformed type of that registered {@link PojoSwap}.
037 *       </td>
038 *       <td>&nbsp;</td>
039 *    </tr>
040 *    <tr>
041 *       <td>
042 *          A class that is the transformed type of a registered {@link PojoSwap}.
043 *       </td>
044 *       <td>
045 *          A value whose class matches the normal type of that registered {@link PojoSwap}.
046 *       </td>
047 *       <td>&nbsp;</td>
048 *    </tr>
049 *    <tr>
050 *       <td>
051 *          {@code Number} (e.g. {@code Integer}, {@code Short}, {@code Float},...)
052 *          <br><code>Number.<jsf>TYPE</jsf></code> (e.g. <code>Integer.<jsf>TYPE</jsf></code>,
053 *          <code>Short.<jsf>TYPE</jsf></code>, <code>Float.<jsf>TYPE</jsf></code>,...)
054 *       </td>
055 *       <td>
056 *          {@code Number}, {@code String}, <jk>null</jk>
057 *       </td>
058 *       <td>
059 *          For primitive {@code TYPES}, <jk>null</jk> returns the JVM default value for that type.
060 *       </td>
061 *    </tr>
062 *    <tr>
063 *       <td>
064 *          {@code Map} (e.g. {@code Map}, {@code HashMap}, {@code TreeMap}, {@code OMap})
065 *       </td>
066 *       <td>
067 *          {@code Map}
068 *       </td>
069 *       <td>
070 *          If {@code Map} is not constructible, an {@code OMap} is created.
071 *       </td>
072 *    </tr>
073 *    <tr>
074 *       <td>
075 *          <c>Collection</c> (e.g. <c>List</c>, <c>LinkedList</c>, <c>HashSet</c>, <c>OList</c>)
076 *       </td>
077 *       <td>
078 *          <c>Collection&lt;Object&gt;</c>
079 *          <br><c>Object[]</c>
080 *       </td>
081 *       <td>
082 *          If <c>Collection</c> is not constructible, a <c>OList</c> is created.
083 *       </td>
084 *    </tr>
085 *    <tr>
086 *       <td>
087 *          <c>X[]</c> (array of any type X)
088 *       </td>
089 *       <td>
090 *          <c>List&lt;X&gt;</c>
091 *       </td>
092 *       <td>&nbsp;</td>
093 *    </tr>
094 *    <tr>
095 *       <td>
096 *          <c>X[][]</c> (multi-dimensional arrays)
097 *       </td>
098 *       <td>
099 *          <c>List&lt;List&lt;X&gt;&gt;</c>
100 *          <br><c>List&lt;X[]&gt;</c>
101 *          <br><c> List[]&lt;X&gt;</c>
102 *       </td>
103 *       <td>&nbsp;</td>
104 *    </tr>
105 *    <tr>
106 *       <td>
107 *          <c>Enum</c>
108 *       </td>
109 *       <td>
110 *          <c>String</c>
111 *       </td>
112 *       <td>&nbsp;</td>
113 *    </tr>
114 *    <tr>
115 *       <td>
116 *          Bean
117 *       </td>
118 *       <td>
119 *          <c>Map</c>
120 *       </td>
121 *       <td>&nbsp;</td>
122 *    </tr>
123 *    <tr>
124 *       <td>
125 *          <c>String</c>
126 *       </td>
127 *       <td>
128 *          Anything
129 *       </td>
130 *       <td>
131 *          Arrays are converted to JSON arrays
132 *       </td>
133 *    </tr>
134 *    <tr>
135 *       <td>
136 *          Anything with one of the following methods:
137 *          <br><code><jk>public static</jk> T fromString(String)</code>
138 *          <br><code><jk>public static</jk> T valueOf(String)</code>
139 *          <br><code><jk>public</jk> T(String)</code>
140 *       </td>
141 *       <td>
142 *          <c>String</c>
143 *       </td>
144 *       <td>
145 *          <br>
146 *       </td>
147 *    </tr>
148 * </table>
149 */
150public final class ConverterUtils {
151
152   // Session objects are usually not thread safe, but we're not using any feature
153   // of bean sessions that would cause thread safety issues.
154   private static final BeanSession session = BeanContext.DEFAULT.createSession();
155
156   /**
157    * Converts the specified object to the specified type.
158    *
159    * @param <T> The class type to convert the value to.
160    * @param value The value to convert.
161    * @param type The class type to convert the value to.
162    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
163    * @return The converted value.
164    */
165   public static <T> T toType(Object value, Class<T> type) {
166      return session.convertToType(value, type);
167   }
168
169
170   /**
171    * Converts the specified object to the specified type.
172    *
173    * @param <T> The class type to convert the value to.
174    * @param value The value to convert.
175    * @param type The class type to convert the value to.
176    * @param args The type arguments.
177    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
178    * @return The converted value.
179    */
180   public static <T> T toType(Object value, Class<T> type, Type...args) {
181      return session.convertToType(value, type, args);
182   }
183
184   /**
185    * Converts an object to a Boolean.
186    *
187    * @param o The object to convert.
188    * @return The converted object.
189    */
190   public static Boolean toBoolean(Object o) {
191      return toType(o, Boolean.class);
192   }
193
194   /**
195    * Converts an object to an Integer.
196    *
197    * @param o The object to convert.
198    * @return The converted object.
199    */
200   public static Integer toInteger(Object o) {
201      return toType(o, Integer.class);
202   }
203
204   /**
205    * Converts an object to a Number.
206    *
207    * @param o The object to convert.
208    * @return The converted object.
209    */
210   public static Number toNumber(Object o) {
211      if (o == null)
212         return null;
213      if (o instanceof Number)
214         return (Number)o;
215      try {
216         return StringUtils.parseNumber(o.toString(), null);
217      } catch (ParseException e) {
218         throw new RuntimeException(e);
219      }
220   }
221}