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.utils;
018
019
020import java.lang.reflect.*;
021import java.util.*;
022import java.util.function.*;
023
024import org.apache.juneau.commons.lang.*;
025import static org.apache.juneau.commons.utils.Shorts.*;
026
027/**
028 * Canonical home for object-level helpers: null/empty checks, equality, comparison,
029 * coalescing, boolean folds, identity/stringify, small numeric helpers, and optionals.
030 *
031 * <p>Terse aliases for these methods live in {@link Shorts}.
032 */
033@SuppressWarnings({
034   "java:S1118", // Utility class with static methods only.
035   "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants
036   "java:S1221", // equal(...) overloads (aliased by Shorts.eq) have 60+ callers reactor-wide; renaming would be a high-blast-radius public-API break.
037   "unchecked" // The (T) casts of boxed Number results in abs() are safe because each branch is selected by the runtime type of value.
038})
039public class ObjectUtils {
040
041   /** Constructor — this class is meant to be subclassed. */
042   protected ObjectUtils() {}
043
044   /** Returns <jk>true</jk> if the object is not <jk>null</jk>. */
045   public static boolean isNotNull(Object o) { return o != null; }
046
047   /** Returns <jk>true</jk> if the object is <jk>null</jk>. */
048   public static <T> boolean isNull(T value) { return value == null; }
049
050   /** Returns <jk>true</jk> if all specified values are <jk>null</jk> (or the array is <jk>null</jk>). */
051   public static boolean isNull(Object...values) {
052      if (values == null) return true;
053      for (var v : values) if (v != null) return false;
054      return true;
055   }
056
057   /** Returns <jk>null</jk> typed as the specified class (type-inference helper). */
058   @SuppressWarnings({
059      "java:S1172", // Parameter used for type inference only.
060      "unused" // Parameter used for type inference only.
061   })
062   public static <T> T nullObject(Class<T> type) { return null; }
063
064   /** Null/array/annotation-aware equality. */
065   public static <T> boolean equal(T o1, T o2) {
066      if (o1 instanceof java.lang.annotation.Annotation o1a && o2 instanceof java.lang.annotation.Annotation o2a)
067         return AnnotationUtils.equals(o1a, o2a);
068      if (ClassUtils.isArray(o1) && ClassUtils.isArray(o2)) {
069         var l1 = Array.getLength(o1);
070         var l2 = Array.getLength(o2);
071         if (l1 != l2) return false;
072         for (var i = 0; i < l1; i++)
073            if (notEqual(Array.get(o1, i), Array.get(o2, i))) return false;
074         return true;
075      }
076      return Objects.equals(o1, o2);
077   }
078
079   /** String equality with optional case-insensitivity (<jk>null</jk>-safe; two <jk>null</jk> values are equal). */
080   public static boolean equal(boolean caseInsensitive, String s1, String s2) {
081      return caseInsensitive ? equalIgnoreCase(s1, s2) : equal(s1, s2);
082   }
083
084   /** Null-safe equality via a custom predicate. */
085   public static <T,U> boolean equal(T o1, U o2, BiPredicate<T,U> test) {
086      if (o1 == null) return o2 == null;
087      if (o2 == null) return false;
088      if (o1 == o2) return true;
089      return test.test(o1, o2);
090   }
091
092   /** Returns <jk>true</jk> if the first argument equals any of the varargs.  <br>Returns <jk>false</jk> if the varargs array is <jk>null</jk> or empty. */
093   @SafeVarargs
094   public static <T> boolean equalsAny(T o1, T...o2) {
095      if (o2 == null || o2.length == 0) return false;
096      for (var o : o2) if (equal(o1, o)) return true;
097      return false;
098   }
099
100   /** Case-insensitive equality of two objects' string forms (<jk>null</jk>-safe; two <jk>null</jk> values are equal, one <jk>null</jk> is not). */
101   public static boolean equalIgnoreCase(Object o1, Object o2) { return StringUtils.equalsIgnoreCase(o1, o2); }
102
103   /** Inverse of {@link #equal(Object,Object)}. */
104   public static <T> boolean notEqual(T o1, T o2) { return ! equal(o1, o2); }
105
106   /** Inverse of {@link #equal(Object,Object,BiPredicate)}. */
107   public static <T,U> boolean notEqual(T o1, U o2, BiPredicate<T,U> test) {
108      if (o1 == null) return isNotNull(o2);
109      if (o2 == null) return true;
110      if (o1 == o2) return false;
111      return ! test.test(o1, o2);
112   }
113
114   /** Null-tolerant natural-order compare (0 if types differ / not Comparable). */
115   @SuppressWarnings({
116      "java:S3740" // Raw Comparable; parameterizing breaks compareTo.
117   })
118   public static int compare(Object o1, Object o2) {
119      if (o1 == null) return o2 == null ? 0 : -1;
120      if (o2 == null) return 1;
121      if (equal(o1.getClass(), o2.getClass()) && o1 instanceof Comparable o12)
122         return o12.compareTo(o2);
123      return 0;
124   }
125
126   /**
127    * Returns <jk>true</jk> if o1 is less than o2.
128    *
129    * @param <T> The comparable type.
130    * @param o1 Object 1.  Can be <jk>null</jk>.
131    * @param o2 Object 2.  Can be <jk>null</jk>.
132    * @return <jk>true</jk> if o1 is less than o2.  A <jk>null</jk> value is considered less than any non-<jk>null</jk> value.
133    */
134   public static <T extends Comparable<T>> boolean lessThan(T o1, T o2) {
135      if (o1 == null) return o2 != null;
136      if (o2 == null) return false;
137      return o1.compareTo(o2) < 0;
138   }
139
140   /**
141    * Returns <jk>true</jk> if o1 is less than or equal to o2.
142    *
143    * @param <T> The comparable type.
144    * @param o1 Object 1.  Can be <jk>null</jk>.
145    * @param o2 Object 2.  Can be <jk>null</jk>.
146    * @return <jk>true</jk> if o1 is less than or equal to o2.  A <jk>null</jk> o1 is considered less than or equal to any value.
147    */
148   public static <T extends Comparable<T>> boolean lessThanOrEqual(T o1, T o2) {
149      if (o1 == null) return true;
150      if (o2 == null) return false;
151      return o1.compareTo(o2) <= 0;
152   }
153
154   /**
155    * Returns <jk>true</jk> if o1 is greater than o2.
156    *
157    * @param <T> The comparable type.
158    * @param o1 Object 1.  Can be <jk>null</jk>.
159    * @param o2 Object 2.  Can be <jk>null</jk>.
160    * @return <jk>true</jk> if o1 is greater than o2.  A <jk>null</jk> o1 is never considered greater than o2; a non-<jk>null</jk> o1 is considered greater than a <jk>null</jk> o2.
161    */
162   public static <T extends Comparable<T>> boolean greaterThan(T o1, T o2) {
163      if (o1 == null) return false;
164      if (o2 == null) return true;
165      return o1.compareTo(o2) > 0;
166   }
167
168   /**
169    * Returns <jk>true</jk> if o1 is greater than or equal to o2.
170    *
171    * @param <T> The comparable type.
172    * @param o1 Object 1.  Can be <jk>null</jk>.
173    * @param o2 Object 2.  Can be <jk>null</jk>.
174    * @return <jk>true</jk> if o1 is greater than or equal to o2.  A non-<jk>null</jk> o1 is considered greater than or equal to a <jk>null</jk> o2; a <jk>null</jk> o1 is greater than or equal only to a <jk>null</jk> o2.
175    */
176   public static <T extends Comparable<T>> boolean greaterThanOrEqual(T o1, T o2) {
177      if (o1 == null) return o2 == null;
178      if (o2 == null) return true;
179      return o1.compareTo(o2) >= 0;
180   }
181
182   /**
183    * Returns the minimum of two comparable values.
184    *
185    * @param <T> The comparable type.
186    * @param o1 Value 1.  Can be <jk>null</jk>.
187    * @param o2 Value 2.  Can be <jk>null</jk>.
188    * @return The minimum value.  If one argument is <jk>null</jk>, the other is returned (which may itself be <jk>null</jk> if both are <jk>null</jk>).
189    */
190   public static <T extends Comparable<T>> T min(T o1, T o2) {
191      if (o1 == null) return o2;
192      if (o2 == null) return o1;
193      return o1.compareTo(o2) <= 0 ? o1 : o2;
194   }
195
196   /**
197    * Returns the maximum of two comparable values.
198    *
199    * @param <T> The comparable type.
200    * @param o1 Value 1.  Can be <jk>null</jk>.
201    * @param o2 Value 2.  Can be <jk>null</jk>.
202    * @return The maximum value.  If one argument is <jk>null</jk>, the other is returned (which may itself be <jk>null</jk> if both are <jk>null</jk>).
203    */
204   public static <T extends Comparable<T>> T max(T o1, T o2) {
205      if (o1 == null) return o2;
206      if (o2 == null) return o1;
207      return o1.compareTo(o2) >= 0 ? o1 : o2;
208   }
209
210   /** Returns the value if non-null, else the default (coalesce). */
211   public static <T> T coalesce(T value, T defaultValue) { return isNotNull(value) ? value : defaultValue; }
212
213   /** Returns the first non-null value, or <jk>null</jk>. */
214   @SafeVarargs
215   public static <T> T coalesce(T...t) {
216      if (isNotNull(t)) for (var tt : t) if (isNotNull(tt)) return tt;
217      return null;
218   }
219
220   /**
221    * Returns <jk>null</jk> when the value is <jk>null</jk>, else the mapper's result; the mapper is never called on <jk>null</jk>.
222    *
223    * @param <T> The value type.
224    * @param <R> The result type.
225    * @param value The value to map. Can be <jk>null</jk>.
226    * @param mapper The mapping function.
227    * @return The mapped value, or <jk>null</jk> if {@code value} is <jk>null</jk> or the mapper returns <jk>null</jk>.
228    */
229   public static <T,R> R mapOrNull(T value, Function<? super T,? extends R> mapper) { return value == null ? null : mapper.apply(value); }
230
231   /** Boolean AND-fold (vacuously true when empty). */
232   public static boolean allTrue(boolean...values) {
233      if (values == null || values.length == 0) return true;
234      for (var v : values) if (! v) return false;
235      return true;
236   }
237
238   /** Boolean OR-fold (false when empty). */
239   public static boolean anyTrue(boolean...values) {
240      if (values == null || values.length == 0) return false;
241      for (var v : values) if (v) return true;
242      return false;
243   }
244
245   /** Boolean negation. */
246   public static boolean negate(boolean value) { return ! value; }
247
248   /** Null-safe {@link Boolean#TRUE} check. */
249   public static boolean isTrue(Object value) { return Boolean.TRUE.equals(value); }
250
251   /** Null-safe {@link Boolean#FALSE} check. */
252   public static boolean isFalse(Object value) { return Boolean.FALSE.equals(value); }
253
254   /** Coerces an object to a boolean (false if null). */
255   public static boolean toBoolean(Object val) {
256      return optional(val).map(Object::toString).map(Boolean::valueOf).orElse(false);
257   }
258
259   /** Null-safe toString (returns <jk>null</jk> for <jk>null</jk>). */
260   public static String stringify(Object val) { return val == null ? null : val.toString(); }
261
262   /** "SimpleQualifiedName@identityHashCode" for the object (unwrapping Optionals).  <br>Returns <jk>null</jk> if the argument is <jk>null</jk> (or an empty Optional). */
263   public static String identity(Object o) {
264      if (o instanceof Optional<?> o2) o = o2.orElse(null);
265      if (o == null) return null;
266      return ClassUtils.classNameSimpleQualified(o) + "@" + System.identityHashCode(o);
267   }
268
269   /** Unwraps a Supplier/Holder/Optional to its inner value.  <br>Returns <jk>null</jk> if the argument is <jk>null</jk> or unwraps to <jk>null</jk>. */
270   public static Object unwrap(Object o) {
271      if (o instanceof Supplier<?> o2) o = unwrap(o2.get());
272      if (o instanceof Holder<?> o2) o = unwrap(o2.get());
273      if (o instanceof Optional<?> o2) o = unwrap(o2.orElse(null));
274      return o;
275   }
276
277   /** Absolute value across Number subtypes.  <br>Returns <jk>null</jk> if the argument is <jk>null</jk>. */
278   public static <T extends Number> T abs(T value) {
279      if (value == null) return null;
280      if (value instanceof Integer) return (T)Integer.valueOf(Math.abs(value.intValue()));
281      if (value instanceof Long) return (T)Long.valueOf(Math.abs(value.longValue()));
282      if (value instanceof Double) return (T)Double.valueOf(Math.abs(value.doubleValue()));
283      if (value instanceof Float) return (T)Float.valueOf(Math.abs(value.floatValue()));
284      if (value instanceof Short) return (T)Short.valueOf((short)Math.abs(value.shortValue()));
285      if (value instanceof Byte) return (T)Byte.valueOf((byte)Math.abs(value.byteValue()));
286      return (T)Double.valueOf(Math.abs(value.doubleValue()));
287   }
288
289   /** Inclusive between. */
290   public static boolean isBetween(int n, int lower, int higher) { return n >= lower && n <= higher; }
291
292   /** True if the number is non-null and not -1. */
293   public static <T extends Number> boolean isNotMinusOne(T value) { return isNotNull(value) && value.intValue() != -1; }
294
295   /** Content/annotation/array-aware hash.  <br>Throws {@link IllegalArgumentException} if the array is <jk>null</jk>. */
296   public static int hash(Object...values) {
297      reqnn("values", values);
298      return HashCode.of(values);
299   }
300
301   /** True if the object (String/Collection/Map/array/other) is null or empty. */
302   public static boolean isEmpty(Object o) {
303      if (o == null) return true;
304      if (o instanceof Collection<?> o2) return o2.isEmpty();
305      if (o instanceof Map<?,?> o2) return o2.isEmpty();
306      if (ClassUtils.isArray(o)) return Array.getLength(o) == 0;
307      return o.toString().isEmpty();
308   }
309
310   /** Inverse of {@link #isEmpty(Object)}. */
311   public static boolean isNotEmpty(Object value) {
312      if (value == null) return false;
313      if (value instanceof CharSequence value2) return ! value2.isEmpty();
314      if (value instanceof Collection<?> value2) return ! value2.isEmpty();
315      if (value instanceof Map<?,?> value2) return ! value2.isEmpty();
316      if (ClassUtils.isArray(value)) return Array.getLength(value) > 0;
317      return isNotEmpty(stringify(value));
318   }
319
320   /** {@link Optional#ofNullable(Object)} shorthand. */
321   public static <T> Optional<T> optional(T t) { return Optional.ofNullable(t); }
322
323   /** {@link Optional#empty()} shorthand. */
324   public static <T> Optional<T> emptyOptional() { return Optional.empty(); }
325
326   /** {@code optional.orElse(defaultValue)} shorthand. */
327   public static <T> T orElse(Optional<T> optional, T defaultValue) { return optional.orElse(defaultValue); }
328
329   /** Asserts non-null and returns the value. */
330   public static <T> T requireNonNull(T value) { return Objects.requireNonNull(value); }
331
332   /** Null-safe size (0 for null; length/size for String/Collection/Map/array; else 1). */
333   public static int size(Object o) {
334      if (o == null) return 0;
335      if (o instanceof CharSequence o2) return o2.length();
336      if (o instanceof Collection<?> o2) return o2.size();
337      if (o instanceof Map<?,?> o2) return o2.size();
338      if (ClassUtils.isArray(o)) return Array.getLength(o);
339      return 1;
340   }
341}