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.*;
016import java.util.*;
017
018import org.apache.juneau.*;
019import org.apache.juneau.parser.*;
020import org.apache.juneau.transform.*;
021
022/**
023 * Utility class for efficiently converting objects between types.
024 *
025 * <p>
026 * If the value isn't an instance of the specified type, then converts the value if possible.
027 *
028 * <p>
029 * The following conversions are valid:
030 * <table class='styled'>
031 *    <tr><th>Convert to type</th><th>Valid input value types</th><th>Notes</th></tr>
032 *    <tr>
033 *       <td>
034 *          A class that is the normal type of a registered {@link PojoSwap}.
035 *       </td>
036 *       <td>
037 *          A value whose class matches the transformed type of that registered {@link PojoSwap}.
038 *       </td>
039 *       <td>&nbsp;</td>
040 *    </tr>
041 *    <tr>
042 *       <td>
043 *          A class that is the transformed type of a registered {@link PojoSwap}.
044 *       </td>
045 *       <td>
046 *          A value whose class matches the normal type of that registered {@link PojoSwap}.
047 *       </td>
048 *       <td>&nbsp;</td>
049 *    </tr>
050 *    <tr>
051 *       <td>
052 *          {@code Number} (e.g. {@code Integer}, {@code Short}, {@code Float},...)
053 *          <br><code>Number.<jsf>TYPE</jsf></code> (e.g. <code>Integer.<jsf>TYPE</jsf></code>,
054 *          <code>Short.<jsf>TYPE</jsf></code>, <code>Float.<jsf>TYPE</jsf></code>,...)
055 *       </td>
056 *       <td>
057 *          {@code Number}, {@code String}, <jk>null</jk>
058 *       </td>
059 *       <td>
060 *          For primitive {@code TYPES}, <jk>null</jk> returns the JVM default value for that type.
061 *       </td>
062 *    </tr>
063 *    <tr>
064 *       <td>
065 *          {@code Map} (e.g. {@code Map}, {@code HashMap}, {@code TreeMap}, {@code ObjectMap})
066 *       </td>
067 *       <td>
068 *          {@code Map}
069 *       </td>
070 *       <td>
071 *          If {@code Map} is not constructible, a {@code ObjectMap} is created.
072 *       </td>
073 *    </tr>
074 *    <tr>
075 *       <td>
076 *          <code>Collection</code> (e.g. <code>List</code>, <code>LinkedList</code>, <code>HashSet</code>, <code>ObjectList</code>)
077 *       </td>
078 *       <td>
079 *          <code>Collection&lt;Object&gt;</code>
080 *          <br><code>Object[]</code>
081 *       </td>
082 *       <td>
083 *          If <code>Collection</code> is not constructible, a <code>ObjectList</code> is created.
084 *       </td>
085 *    </tr>
086 *    <tr>
087 *       <td>
088 *          <code>X[]</code> (array of any type X)
089 *       </td>
090 *       <td>
091 *          <code>List&lt;X&gt;</code>
092 *       </td>
093 *       <td>&nbsp;</td>
094 *    </tr>
095 *    <tr>
096 *       <td>
097 *          <code>X[][]</code> (multi-dimensional arrays)
098 *       </td>
099 *       <td>
100 *          <code>List&lt;List&lt;X&gt;&gt;</code>
101 *          <br><code>List&lt;X[]&gt;</code>
102 *          <br><code> List[]&lt;X&gt;</code>
103 *       </td>
104 *       <td>&nbsp;</td>
105 *    </tr>
106 *    <tr>
107 *       <td>
108 *          <code>Enum</code>
109 *       </td>
110 *       <td>
111 *          <code>String</code>
112 *       </td>
113 *       <td>&nbsp;</td>
114 *    </tr>
115 *    <tr>
116 *       <td>
117 *          Bean
118 *       </td>
119 *       <td>
120 *          <code>Map</code>
121 *       </td>
122 *       <td>&nbsp;</td>
123 *    </tr>
124 *    <tr>
125 *       <td>
126 *          <code>String</code>
127 *       </td>
128 *       <td>
129 *          Anything
130 *       </td>
131 *       <td>
132 *          Arrays are converted to JSON arrays
133 *       </td>
134 *    </tr>
135 *    <tr>
136 *       <td>
137 *          Anything with one of the following methods:
138 *          <br><code><jk>public static</jk> T fromString(String)</code>
139 *          <br><code><jk>public static</jk> T valueOf(String)</code>
140 *          <br><code><jk>public</jk> T(String)</code>
141 *       </td>
142 *       <td>
143 *          <code>String</code>
144 *       </td>
145 *       <td>
146 *          <br>
147 *       </td>
148 *    </tr>
149 * </table>
150 */
151public final class ObjectUtils {
152
153   // Session objects are usually not thread safe, but we're not using any feature
154   // of bean sessions that would cause thread safety issues.
155   private static final BeanSession session = BeanContext.DEFAULT.createSession();
156
157   /**
158    * Converts the specified object to the specified type.
159    *
160    * @param <T> The class type to convert the value to.
161    * @param value The value to convert.
162    * @param type The class type to convert the value to.
163    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
164    * @return The converted value.
165    */
166   public static <T> T toType(Object value, Class<T> type) {
167      return session.convertToType(value, type);
168   }
169
170
171   /**
172    * Converts the specified object to the specified type.
173    *
174    * @param <T> The class type to convert the value to.
175    * @param value The value to convert.
176    * @param type The class type to convert the value to.
177    * @param args The type arguments.
178    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
179    * @return The converted value.
180    */
181   public static <T> T toType(Object value, Class<T> type, Type...args) {
182      return session.convertToType(value, type, args);
183   }
184
185   /**
186    * Converts the specified object to the specified type.
187    *
188    * @param <T> The class type to convert the value to.
189    * @param outer
190    *    If class is a member class, this is the instance of the containing class.
191    *    Should be <jk>null</jk> if not a member class.
192    * @param value The value to convert.
193    * @param type The class type to convert the value to.
194    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
195    * @return The converted value.
196    */
197   public static <T> T toMemberType(Object outer, Object value, Class<T> type) {
198      return session.convertToMemberType(outer, value, type);
199   }
200
201   /**
202    * Returns <jk>true</jk> if the specified objects are equal.
203    *
204    * <p>
205    * Gracefully handles <jk>null</jk>s.
206    *
207    * @param o1 Object #1
208    * @param o2 Object #2
209    * @return <jk>true</jk> if the objects are equal or both <jk>null</jk>.
210    */
211   public static boolean equals(Object o1, Object o2) {
212      if (o1 == null && o2 == null)
213         return true;
214      if (o1 == null || o2 == null)
215         return false;
216      return o1.equals(o2);
217   }
218
219   /**
220    * Returns <jk>true</jk> if the specified object is empty.
221    *
222    * <p>
223    * Return <jk>true</jk> if the value is any of the following:
224    * <ul>
225    *    <li><jk>null</jk>
226    *    <li>An empty Collection
227    *    <li>An empty Map
228    *    <li>An empty array
229    *    <li>An empty CharSequence
230    *    <li>An empty String when serialized to a string using {@link Object#toString()}.
231    * </ul>
232    *
233    * @param o The object to test.
234    * @return <jk>true</jk> if the specified object is empty.
235    */
236   @SuppressWarnings("rawtypes")
237   public static boolean isEmpty(Object o) {
238      if (o == null)
239         return true;
240      if (o instanceof Collection)
241         return ((Collection)o).isEmpty();
242      if (o instanceof Map)
243         return ((Map)o).isEmpty();
244      if (o.getClass().isArray())
245         return (Array.getLength(o) == 0);
246      return o.toString().isEmpty();
247   }
248
249   /**
250    * Returns the first non-null value in the specified array
251    *
252    * @param t
253    * @return The first non-null value, or <jk>null</jk> if the array is null or empty or contains only <jk>null</jk> values.
254    */
255   @SafeVarargs
256   public static <T> T firstNonNull(T... t) {
257      if (t != null)
258         for (T tt : t)
259            if (tt != null)
260               return tt;
261      return null;
262   }
263
264   /**
265    * Converts an object to a Boolean.
266    *
267    * @param o The object to convert.
268    * @return The converted object.
269    */
270   public static Boolean toBoolean(Object o) {
271      return toType(o, Boolean.class);
272   }
273
274   /**
275    * Converts an object to an Integer.
276    *
277    * @param o The object to convert.
278    * @return The converted object.
279    */
280   public static Integer toInteger(Object o) {
281      return toType(o, Integer.class);
282   }
283
284   /**
285    * Converts an object to a Number.
286    *
287    * @param o The object to convert.
288    * @return The converted object.
289    */
290   public static Number toNumber(Object o) {
291      if (o == null)
292         return null;
293      if (o instanceof Number)
294         return (Number)o;
295      try {
296         return StringUtils.parseNumber(o.toString(), null);
297      } catch (ParseException e) {
298         throw new RuntimeException(e);
299      }
300   }
301
302   /**
303    * Returns the enum names for the specified enum class.
304    *
305    * @param c The enum class.
306    * @return A modifiable list of all names for that class.
307    */
308   @SuppressWarnings("unchecked")
309   public static Enum<?>[] getEnumConstants(Class<?> c) {
310      return ((Class<Enum<?>>)c).getEnumConstants();
311   }
312
313   /**
314    * If the specified object is an instance of the specified class, casts it to that type.
315    *
316    * @param o The object to cast.
317    * @param c The class to cast to.
318    * @return The cast object, or <jk>null</jk> if the object wasn't an instance of the specified class.
319    */
320   @SuppressWarnings("unchecked")
321   public static <T> T castOrNull(Object o, Class<T> c) {
322      if (c.isInstance(o))
323         return (T)o;
324      return null;
325   }
326
327   /**
328    * Returns the first non-zero value in the list of ints.
329    *
330    * @param ints The ints to check.
331    * @return The first non-zero value, or <code>0</code> if they were all zero.
332    */
333   public static int firstNonZero(int...ints) {
334      for (int i : ints)
335         if (i != 0)
336            return i;
337      return 0;
338   }
339
340   /**
341    * Returns the first non-empty value in the list of objects.
342    *
343    * @param o The objects to check.
344    * @return The first object whose call to {@link #isEmpty(Object)} returns <jk>false</jk>, otherwise <jk>null</jk>.
345    */
346   @SafeVarargs
347   public static <T> T firstNonEmpty(T...o) {
348      for (T oo : o)
349         if (! isEmpty(oo))
350            return oo;
351      return null;
352   }
353}