001/* 002 * Copyright 2023 the original author or authors. 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.tools.lang; 017 018import static de.cuioss.tools.base.Preconditions.checkArgument; 019import static de.cuioss.tools.collect.MoreCollections.isEmpty; 020 021import java.util.function.Supplier; 022 023import lombok.experimental.UtilityClass; 024 025/** 026 * Provides some utilities in the context of {@link Object} 027 * 028 * @author Oliver Wolff 029 * 030 */ 031@UtilityClass 032public class MoreObjects { 033 034 /** 035 * Checks and returns the given Object if it is assignable to the given 036 * targetType. Otherwise, it throws an {@link IllegalArgumentException}. This 037 * will be thrown also if one of the parameters is {@code null}. 038 * 039 * @param <T> defining the type to be returned. 040 * 041 * @param underCheck KeyStoreType to be checked / cast. If it is null or is 042 * not assignable to expectedType an 043 * {@link IllegalArgumentException} will be thrown. 044 * @param expectedType checks the type . If it is null an 045 * {@link IllegalArgumentException} will be thrown 046 * @return the cast Objected of type T if applicable. 047 * @throws IllegalArgumentException if the given type is either null or not the 048 * expected type 049 */ 050 @SuppressWarnings("unchecked") // owolff: It is actually checked before. 051 public static <T> T requireType(final Object underCheck, Class<T> expectedType) { 052 checkArgument(null != underCheck, "Object to be checked must not be null"); 053 checkArgument(null != expectedType, "expectedType must not be null"); 054 checkArgument(expectedType.isAssignableFrom(underCheck.getClass()), 055 "KeyStoreType to be checked '%s' is not assignable to '%s'", underCheck.getClass(), 056 expectedType.getName()); 057 return (T) underCheck; 058 } 059 060 /** 061 * Simple helper checking whether a number of given Objects are not {@code null} 062 * 063 * @param objects 064 * @return {@code true} if there is no {@code null} value given, {@code false} 065 * if at least one null value is given. An empty varags parameter 066 * therefore results in {@code true} (no null object found) 067 */ 068 public static boolean allNonNull(Object... objects) { 069 if (isEmpty(objects)) { 070 return true; 071 } 072 for (Object object : objects) { 073 if (null == object) { 074 return false; 075 } 076 } 077 return true; 078 } 079 080 /** 081 * Simple helper checking whether a number of given Objects are {@code null} 082 * 083 * @param objects 084 * @return {@code true} if there is no non-{@code null} value given, 085 * {@code false} if at least one non-null value is given. An empty 086 * varags parameter therefore results in {@code true} (no non-null 087 * object found) 088 */ 089 public static boolean allNull(Object... objects) { 090 if (isEmpty(objects)) { 091 return true; 092 } 093 for (Object object : objects) { 094 if (null != object) { 095 return false; 096 } 097 } 098 return true; 099 } 100 101 /** 102 * <p> 103 * Returns the first value in the array which is not {@code null}. If all the 104 * values are {@code null} or the array is {@code null} or empty then 105 * {@code null} is returned. 106 * </p> 107 * 108 * <pre> 109 * MoreObjects.firstNonNull(null, null) = null 110 * MoreObjects.firstNonNull(null, "") = "" 111 * MoreObjects.firstNonNull(null, null, "") = "" 112 * MoreObjects.firstNonNull(null, "zz") = "zz" 113 * MoreObjects.firstNonNull("abc", *) = "abc" 114 * MoreObjects.firstNonNull(null, "xyz", *) = "xyz" 115 * MoreObjects.firstNonNull(Boolean.TRUE, *) = Boolean.TRUE 116 * MoreObjects.firstNonNull() = null 117 * </pre> 118 * 119 * @param <T> the component type of the array 120 * @param values the values to test, may be {@code null} or empty 121 * 122 * @return the first value from {@code values} which is not {@code null}, or 123 * {@code null} if there are no non-null values 124 */ 125 @SafeVarargs 126 public static <T> T firstNonNull(final T... values) { 127 if (values != null) { 128 for (final T val : values) { 129 if (val != null) { 130 return val; 131 } 132 } 133 } 134 return null; 135 } 136 137 /** 138 * <p> 139 * Executes the given suppliers in order and returns the first return value 140 * where a value other than {@code null} is returned. Once a non-{@code null} 141 * value is obtained, all following suppliers are not executed anymore. If all 142 * the return values are {@code null} or no suppliers are provided then 143 * {@code null} is returned. 144 * </p> 145 * 146 * <pre> 147 * MoreObjects.getFirstNonNull(null, () -> null) = null 148 * MoreObjects.getFirstNonNull(() -> null, () -> "") = "" 149 * MoreObjects.getFirstNonNull(() -> "", () -> throw new IllegalStateException()) = "" 150 * MoreObjects.getFirstNonNull(() -> null, () -> "zz) = "zz" 151 * MoreObjects.getFirstNonNull() = null 152 * </pre> 153 * 154 * @param <T> the type of the return values 155 * @param suppliers the suppliers returning the values to test. {@code null} 156 * values are ignored. Suppliers may return {@code null} or a 157 * value of type @{code T} 158 * 159 * @return the first return value from {@code suppliers} which is not 160 * {@code null}, or {@code null} if there are no non-null values 161 */ 162 @SafeVarargs 163 public static <T> T getFirstNonNull(final Supplier<T>... suppliers) { 164 if (suppliers != null) { 165 for (final Supplier<T> supplier : suppliers) { 166 if (supplier != null) { 167 final var value = supplier.get(); 168 if (value != null) { 169 return value; 170 } 171 } 172 } 173 } 174 return null; 175 } 176}