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> </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> </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 * <c>Collection</c> (e.g. <c>List</c>, <c>LinkedList</c>, <c>HashSet</c>, <c>ObjectList</c>) 077 * </td> 078 * <td> 079 * <c>Collection<Object></c> 080 * <br><c>Object[]</c> 081 * </td> 082 * <td> 083 * If <c>Collection</c> is not constructible, a <c>ObjectList</c> is created. 084 * </td> 085 * </tr> 086 * <tr> 087 * <td> 088 * <c>X[]</c> (array of any type X) 089 * </td> 090 * <td> 091 * <c>List<X></c> 092 * </td> 093 * <td> </td> 094 * </tr> 095 * <tr> 096 * <td> 097 * <c>X[][]</c> (multi-dimensional arrays) 098 * </td> 099 * <td> 100 * <c>List<List<X>></c> 101 * <br><c>List<X[]></c> 102 * <br><c> List[]<X></c> 103 * </td> 104 * <td> </td> 105 * </tr> 106 * <tr> 107 * <td> 108 * <c>Enum</c> 109 * </td> 110 * <td> 111 * <c>String</c> 112 * </td> 113 * <td> </td> 114 * </tr> 115 * <tr> 116 * <td> 117 * Bean 118 * </td> 119 * <td> 120 * <c>Map</c> 121 * </td> 122 * <td> </td> 123 * </tr> 124 * <tr> 125 * <td> 126 * <c>String</c> 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 * <c>String</c> 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 * Returns <jk>true</jk> if the specified objects are equal. 187 * 188 * <p> 189 * Gracefully handles <jk>null</jk>s. 190 * 191 * @param o1 Object #1 192 * @param o2 Object #2 193 * @return <jk>true</jk> if the objects are equal or both <jk>null</jk>. 194 */ 195 public static boolean equals(Object o1, Object o2) { 196 if (o1 == null && o2 == null) 197 return true; 198 if (o1 == null || o2 == null) 199 return false; 200 return o1.equals(o2); 201 } 202 203 /** 204 * Returns <jk>true</jk> if the specified object is empty. 205 * 206 * <p> 207 * Return <jk>true</jk> if the value is any of the following: 208 * <ul> 209 * <li><jk>null</jk> 210 * <li>An empty Collection 211 * <li>An empty Map 212 * <li>An empty array 213 * <li>An empty CharSequence 214 * <li>An empty String when serialized to a string using {@link Object#toString()}. 215 * </ul> 216 * 217 * @param o The object to test. 218 * @return <jk>true</jk> if the specified object is empty. 219 */ 220 @SuppressWarnings("rawtypes") 221 public static boolean isEmpty(Object o) { 222 if (o == null) 223 return true; 224 if (o instanceof Collection) 225 return ((Collection)o).isEmpty(); 226 if (o instanceof Map) 227 return ((Map)o).isEmpty(); 228 if (o.getClass().isArray()) 229 return (Array.getLength(o) == 0); 230 return o.toString().isEmpty(); 231 } 232 233 /** 234 * Returns the first non-null value in the specified array 235 * 236 * @param t The values to check. 237 * @return The first non-null value, or <jk>null</jk> if the array is null or empty or contains only <jk>null</jk> values. 238 */ 239 @SafeVarargs 240 public static <T> T firstNonNull(T... t) { 241 if (t != null) 242 for (T tt : t) 243 if (tt != null) 244 return tt; 245 return null; 246 } 247 248 /** 249 * Converts an object to a Boolean. 250 * 251 * @param o The object to convert. 252 * @return The converted object. 253 */ 254 public static Boolean toBoolean(Object o) { 255 return toType(o, Boolean.class); 256 } 257 258 /** 259 * Converts an object to an Integer. 260 * 261 * @param o The object to convert. 262 * @return The converted object. 263 */ 264 public static Integer toInteger(Object o) { 265 return toType(o, Integer.class); 266 } 267 268 /** 269 * Converts an object to a Number. 270 * 271 * @param o The object to convert. 272 * @return The converted object. 273 */ 274 public static Number toNumber(Object o) { 275 if (o == null) 276 return null; 277 if (o instanceof Number) 278 return (Number)o; 279 try { 280 return StringUtils.parseNumber(o.toString(), null); 281 } catch (ParseException e) { 282 throw new RuntimeException(e); 283 } 284 } 285 286 /** 287 * Returns the enum names for the specified enum class. 288 * 289 * @param c The enum class. 290 * @return A modifiable list of all names for that class. 291 */ 292 @SuppressWarnings("unchecked") 293 public static Enum<?>[] getEnumConstants(Class<?> c) { 294 return ((Class<Enum<?>>)c).getEnumConstants(); 295 } 296 297 /** 298 * If the specified object is an instance of the specified class, casts it to that type. 299 * 300 * @param o The object to cast. 301 * @param c The class to cast to. 302 * @return The cast object, or <jk>null</jk> if the object wasn't an instance of the specified class. 303 */ 304 @SuppressWarnings("unchecked") 305 public static <T> T castOrNull(Object o, Class<T> c) { 306 if (c.isInstance(o)) 307 return (T)o; 308 return null; 309 } 310 311 /** 312 * Returns the first non-zero value in the list of ints. 313 * 314 * @param ints The ints to check. 315 * @return The first non-zero value, or <c>0</c> if they were all zero. 316 */ 317 public static int firstNonZero(int...ints) { 318 for (int i : ints) 319 if (i != 0) 320 return i; 321 return 0; 322 } 323 324 /** 325 * Returns the first non-empty value in the list of objects. 326 * 327 * @param o The objects to check. 328 * @return The first object whose call to {@link #isEmpty(Object)} returns <jk>false</jk>, otherwise <jk>null</jk>. 329 */ 330 @SafeVarargs 331 public static <T> T firstNonEmpty(T...o) { 332 for (T oo : o) 333 if (! isEmpty(oo)) 334 return oo; 335 return null; 336 } 337 338 /** 339 * Compares two objects for equality. 340 * 341 * <p> 342 * Nulls are always considered less-than unless both are null. 343 * 344 * @param o1 Object 1. 345 * @param o2 Object 2. 346 * @return 347 * <c>-1</c>, <c>0</c>, or <c>1</c> if <c>o1</c> is less-than, equal, or greater-than <c>o2</c>. 348 * <br><c>0</c> if objects are not of the same type or do not implement the {@link Comparable} interface. 349 */ 350 @SuppressWarnings({ "rawtypes", "unchecked" }) 351 public static int compare(Object o1, Object o2) { 352 if (o1 == null) { 353 if (o2 == null) 354 return 0; 355 return -1; 356 } else if (o2 == null) { 357 return 1; 358 } 359 360 if (o1.getClass() == o2.getClass() && o1 instanceof Comparable) 361 return ((Comparable)o1).compareTo(o2); 362 363 return 0; 364 } 365 366 /** 367 * Compare two integers numerically. 368 * 369 * @param i1 Integer #1 370 * @param i2 Integer #2 371 * @return 372 * The value <c>0</c> if Integer #1 is equal to Integer #2; a value less than <c>0</c> if 373 * Integer #1 numerically less than Integer #2; and a value greater than <c>0</c> if Integer #1 is 374 * numerically greater than Integer #2 (signed comparison). 375 */ 376 public static final int compare(int i1, int i2) { 377 return (i1<i2 ? -1 : (i1==i2 ? 0 : 1)); 378 } 379}