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.*;
017import java.util.function.*;
018
019import org.apache.juneau.utils.*;
020
021/**
022 * Various generic object utility methods.
023 */
024public class ObjectUtils {
025
026   /**
027    * Returns the enum names for the specified enum class.
028    *
029    * @param c The enum class.
030    * @return A modifiable list of all names for that class.
031    */
032   @SuppressWarnings("unchecked")
033   public static Enum<?>[] getEnumConstants(Class<?> c) {
034      return ((Class<Enum<?>>)c).getEnumConstants();
035   }
036
037   /**
038    * If the specified object is an instance of the specified class, casts it to that type.
039    *
040    * @param o The object to cast.
041    * @param c The class to cast to.
042    * @return The cast object, or <jk>null</jk> if the object wasn't an instance of the specified class.
043    */
044   @SuppressWarnings("unchecked")
045   public static <T> T castOrNull(Object o, Class<T> c) {
046      if (c.isInstance(o))
047         return (T)o;
048      return null;
049   }
050
051   /**
052    * Returns the first non-zero value in the list of ints.
053    *
054    * @param ints The ints to check.
055    * @return The first non-zero value, or <c>0</c> if they were all zero.
056    */
057   public static int firstNonZero(int...ints) {
058      for (int i : ints)
059         if (i != 0)
060            return i;
061      return 0;
062   }
063
064   /**
065    * Returns the first non-empty value in the list of objects.
066    *
067    * @param o The objects to check.
068    * @return The first object whose call to {@link ObjectUtils#isEmpty(Object)} returns <jk>false</jk>, otherwise <jk>null</jk>.
069    */
070   @SafeVarargs
071   public static <T> T firstNonEmpty(T...o) {
072      for (T oo : o)
073         if (! ObjectUtils.isEmpty(oo))
074            return oo;
075      return null;
076   }
077
078   /**
079    * Compares two objects for equality.
080    *
081    * <p>
082    * Nulls are always considered less-than unless both are null.
083    *
084    * @param o1 Object 1.
085    * @param o2 Object 2.
086    * @return
087    *    <c>-1</c>, <c>0</c>, or <c>1</c> if <c>o1</c> is less-than, equal, or greater-than <c>o2</c>.
088    * <br><c>0</c> if objects are not of the same type or do not implement the {@link Comparable} interface.
089    */
090   @SuppressWarnings({ "rawtypes", "unchecked" })
091   public static int compare(Object o1, Object o2) {
092      if (o1 == null) {
093         if (o2 == null)
094            return 0;
095         return -1;
096      } else if (o2 == null) {
097         return 1;
098      }
099
100      if (o1.getClass() == o2.getClass() && o1 instanceof Comparable)
101         return ((Comparable)o1).compareTo(o2);
102
103      return 0;
104   }
105
106   /**
107    * Compare two integers numerically.
108    *
109    * @param i1 Integer #1
110    * @param i2 Integer #2
111    * @return
112    *    The value <c>0</c> if Integer #1 is equal to Integer #2; a value less than <c>0</c> if
113    *    Integer #1 numerically less than Integer #2; and a value greater than <c>0</c> if Integer #1 is
114    *    numerically greater than Integer #2 (signed comparison).
115    */
116   public static final int compare(int i1, int i2) {
117      return (i1<i2 ? -1 : (i1==i2 ? 0 : 1));
118   }
119
120   /**
121    * Tests two objects for equality, gracefully handling nulls.
122    *
123    * @param <T> Object 1 type.
124    * @param <U> Object 2 type.
125    * @param o1 Object 1.
126    * @param o2 Object 2.
127    * @param test The test to use for equality.
128    * @return <jk>true</jk> if both objects are equal based on the test.
129    */
130   public static <T,U> boolean eq(T o1, U o2, BiPredicate<T,U> test) {
131      if (o1 == null)
132         return o2 == null;
133      if (o2 == null)
134         return false;
135      if (o1 == o2)
136         return true;
137      return test.test(o1, o2);
138   }
139
140   /**
141    * Tests two objects for equality, gracefully handling nulls.
142    *
143    * @param o1 Object 1.
144    * @param o2 Object 2.
145    * @return <jk>true</jk> if both objects are equal based on the {@link Object#equals(Object)} method.
146    */
147   public static boolean eq(Object o1, Object o2) {
148      return Objects.equals(o1, o2);
149   }
150
151   /**
152    * Tests two objects for inequality, gracefully handling nulls.
153    *
154    * @param <T> Object 1 type.
155    * @param <U> Object 2 type.
156    * @param o1 Object 1.
157    * @param o2 Object 2.
158    * @param test The test to use for equality.
159    * @return <jk>false</jk> if both objects are equal based on the test.
160    */
161   public static <T,U> boolean ne(T o1, U o2, BiPredicate<T,U> test) {
162      if (o1 == null)
163         return o2 != null;
164      if (o2 == null)
165         return true;
166      if (o1 == o2)
167         return false;
168      return ! test.test(o1, o2);
169   }
170
171   /**
172    * Tests two objects for equality, gracefully handling nulls.
173    *
174    * @param o1 Object 1.
175    * @param o2 Object 2.
176    * @return <jk>false</jk> if both objects are equal based on the {@link Object#equals(Object)} method.
177    */
178   public static boolean ne(Object o1, Object o2) {
179      return ! Objects.equals(o1, o2);
180   }
181
182   /**
183    * If the specified object is a {@link Supplier} or {@link Mutable}, returns the inner value, otherwise the same value.
184    *
185    * @param o The object to unwrap.
186    * @return The unwrapped object.
187    */
188   public static Object unwrap(Object o) {
189      while (o instanceof Supplier)
190         o = ((Supplier<?>)o).get();
191      while (o instanceof Mutable)
192         o = ((Mutable<?>)o).get();
193      return o;
194   }
195
196   /**
197    * Returns <jk>true</jk> if the specified object is empty.
198    *
199    * <p>
200    * Return <jk>true</jk> if the value is any of the following:
201    * <ul>
202    *    <li><jk>null</jk>
203    *    <li>An empty Collection
204    *    <li>An empty Map
205    *    <li>An empty array
206    *    <li>An empty CharSequence
207    *    <li>An empty String when serialized to a string using {@link Object#toString()}.
208    * </ul>
209    *
210    * @param o The object to test.
211    * @return <jk>true</jk> if the specified object is empty.
212    */
213   @SuppressWarnings("rawtypes")
214   public static boolean isEmpty(Object o) {
215      if (o == null)
216         return true;
217      if (o instanceof Collection)
218         return ((Collection)o).isEmpty();
219      if (o instanceof Map)
220         return ((Map)o).isEmpty();
221      if (o.getClass().isArray())
222         return (Array.getLength(o) == 0);
223      return o.toString().isEmpty();
224   }
225
226   /**
227    * Returns <jk>true</jk> if the specified object is not empty.
228    *
229    * <p>
230    * Return <jk>false</jk> if the value is any of the following:
231    * <ul>
232    *    <li><jk>null</jk>
233    *    <li>An empty Collection
234    *    <li>An empty Map
235    *    <li>An empty array
236    *    <li>An empty CharSequence
237    *    <li>An empty String when serialized to a string using {@link Object#toString()}.
238    * </ul>
239    *
240    * @param o The object to test.
241    * @return <jk>true</jk> if the specified object is empty.
242    */
243   public static boolean isNotEmpty(Object o) {
244      return ! isEmpty(o);
245   }
246
247   /**
248    * Returns the first non-null value in the specified array
249    *
250    * @param t The values to check.
251    * @return The first non-null value, or <jk>null</jk> if the array is null or empty or contains only <jk>null</jk> values.
252    */
253   @SafeVarargs
254   public static <T> T firstNonNull(T... t) {
255      if (t != null)
256         for (T tt : t)
257            if (tt != null)
258               return tt;
259      return null;
260   }
261}