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}