1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.util; 18 19import android.annotation.IntRange; 20import android.annotation.NonNull; 21import android.text.TextUtils; 22 23import java.util.Collection; 24 25/** 26 * Simple static methods to be called at the start of your own methods to verify 27 * correct arguments and state. 28 */ 29public class Preconditions { 30 31 public static void checkArgument(boolean expression) { 32 if (!expression) { 33 throw new IllegalArgumentException(); 34 } 35 } 36 37 /** 38 * Ensures that an expression checking an argument is true. 39 * 40 * @param expression the expression to check 41 * @param errorMessage the exception message to use if the check fails; will 42 * be converted to a string using {@link String#valueOf(Object)} 43 * @throws IllegalArgumentException if {@code expression} is false 44 */ 45 public static void checkArgument(boolean expression, final Object errorMessage) { 46 if (!expression) { 47 throw new IllegalArgumentException(String.valueOf(errorMessage)); 48 } 49 } 50 51 /** 52 * Ensures that an string reference passed as a parameter to the calling 53 * method is not empty. 54 * 55 * @param string an string reference 56 * @return the string reference that was validated 57 * @throws IllegalArgumentException if {@code string} is empty 58 */ 59 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) { 60 if (TextUtils.isEmpty(string)) { 61 throw new IllegalArgumentException(); 62 } 63 return string; 64 } 65 66 /** 67 * Ensures that an string reference passed as a parameter to the calling 68 * method is not empty. 69 * 70 * @param string an string reference 71 * @param errorMessage the exception message to use if the check fails; will 72 * be converted to a string using {@link String#valueOf(Object)} 73 * @return the string reference that was validated 74 * @throws IllegalArgumentException if {@code string} is empty 75 */ 76 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string, 77 final Object errorMessage) { 78 if (TextUtils.isEmpty(string)) { 79 throw new IllegalArgumentException(String.valueOf(errorMessage)); 80 } 81 return string; 82 } 83 84 /** 85 * Ensures that an object reference passed as a parameter to the calling 86 * method is not null. 87 * 88 * @param reference an object reference 89 * @return the non-null reference that was validated 90 * @throws NullPointerException if {@code reference} is null 91 */ 92 public static @NonNull <T> T checkNotNull(final T reference) { 93 if (reference == null) { 94 throw new NullPointerException(); 95 } 96 return reference; 97 } 98 99 /** 100 * Ensures that an object reference passed as a parameter to the calling 101 * method is not null. 102 * 103 * @param reference an object reference 104 * @param errorMessage the exception message to use if the check fails; will 105 * be converted to a string using {@link String#valueOf(Object)} 106 * @return the non-null reference that was validated 107 * @throws NullPointerException if {@code reference} is null 108 */ 109 public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) { 110 if (reference == null) { 111 throw new NullPointerException(String.valueOf(errorMessage)); 112 } 113 return reference; 114 } 115 116 /** 117 * Ensures the truth of an expression involving the state of the calling 118 * instance, but not involving any parameters to the calling method. 119 * 120 * @param expression a boolean expression 121 * @param message exception message 122 * @throws IllegalStateException if {@code expression} is false 123 */ 124 public static void checkState(final boolean expression, String message) { 125 if (!expression) { 126 throw new IllegalStateException(message); 127 } 128 } 129 130 /** 131 * Ensures the truth of an expression involving the state of the calling 132 * instance, but not involving any parameters to the calling method. 133 * 134 * @param expression a boolean expression 135 * @throws IllegalStateException if {@code expression} is false 136 */ 137 public static void checkState(final boolean expression) { 138 checkState(expression, null); 139 } 140 141 /** 142 * Check the requested flags, throwing if any requested flags are outside 143 * the allowed set. 144 * 145 * @return the validated requested flags. 146 */ 147 public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) { 148 if ((requestedFlags & allowedFlags) != requestedFlags) { 149 throw new IllegalArgumentException("Requested flags 0x" 150 + Integer.toHexString(requestedFlags) + ", but only 0x" 151 + Integer.toHexString(allowedFlags) + " are allowed"); 152 } 153 154 return requestedFlags; 155 } 156 157 /** 158 * Ensures that that the argument numeric value is non-negative. 159 * 160 * @param value a numeric int value 161 * @param errorMessage the exception message to use if the check fails 162 * @return the validated numeric value 163 * @throws IllegalArgumentException if {@code value} was negative 164 */ 165 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value, 166 final String errorMessage) { 167 if (value < 0) { 168 throw new IllegalArgumentException(errorMessage); 169 } 170 171 return value; 172 } 173 174 /** 175 * Ensures that that the argument numeric value is non-negative. 176 * 177 * @param value a numeric int value 178 * 179 * @return the validated numeric value 180 * @throws IllegalArgumentException if {@code value} was negative 181 */ 182 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) { 183 if (value < 0) { 184 throw new IllegalArgumentException(); 185 } 186 187 return value; 188 } 189 190 /** 191 * Ensures that that the argument numeric value is non-negative. 192 * 193 * @param value a numeric long value 194 * @return the validated numeric value 195 * @throws IllegalArgumentException if {@code value} was negative 196 */ 197 public static long checkArgumentNonnegative(final long value) { 198 if (value < 0) { 199 throw new IllegalArgumentException(); 200 } 201 202 return value; 203 } 204 205 /** 206 * Ensures that that the argument numeric value is non-negative. 207 * 208 * @param value a numeric long value 209 * @param errorMessage the exception message to use if the check fails 210 * @return the validated numeric value 211 * @throws IllegalArgumentException if {@code value} was negative 212 */ 213 public static long checkArgumentNonnegative(final long value, final String errorMessage) { 214 if (value < 0) { 215 throw new IllegalArgumentException(errorMessage); 216 } 217 218 return value; 219 } 220 221 /** 222 * Ensures that that the argument numeric value is positive. 223 * 224 * @param value a numeric int value 225 * @param errorMessage the exception message to use if the check fails 226 * @return the validated numeric value 227 * @throws IllegalArgumentException if {@code value} was not positive 228 */ 229 public static int checkArgumentPositive(final int value, final String errorMessage) { 230 if (value <= 0) { 231 throw new IllegalArgumentException(errorMessage); 232 } 233 234 return value; 235 } 236 237 /** 238 * Ensures that the argument floating point value is a finite number. 239 * 240 * <p>A finite number is defined to be both representable (that is, not NaN) and 241 * not infinite (that is neither positive or negative infinity).</p> 242 * 243 * @param value a floating point value 244 * @param valueName the name of the argument to use if the check fails 245 * 246 * @return the validated floating point value 247 * 248 * @throws IllegalArgumentException if {@code value} was not finite 249 */ 250 public static float checkArgumentFinite(final float value, final String valueName) { 251 if (Float.isNaN(value)) { 252 throw new IllegalArgumentException(valueName + " must not be NaN"); 253 } else if (Float.isInfinite(value)) { 254 throw new IllegalArgumentException(valueName + " must not be infinite"); 255 } 256 257 return value; 258 } 259 260 /** 261 * Ensures that the argument floating point value is within the inclusive range. 262 * 263 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers 264 * will always be out of range.</p> 265 * 266 * @param value a floating point value 267 * @param lower the lower endpoint of the inclusive range 268 * @param upper the upper endpoint of the inclusive range 269 * @param valueName the name of the argument to use if the check fails 270 * 271 * @return the validated floating point value 272 * 273 * @throws IllegalArgumentException if {@code value} was not within the range 274 */ 275 public static float checkArgumentInRange(float value, float lower, float upper, 276 String valueName) { 277 if (Float.isNaN(value)) { 278 throw new IllegalArgumentException(valueName + " must not be NaN"); 279 } else if (value < lower) { 280 throw new IllegalArgumentException( 281 String.format( 282 "%s is out of range of [%f, %f] (too low)", valueName, lower, upper)); 283 } else if (value > upper) { 284 throw new IllegalArgumentException( 285 String.format( 286 "%s is out of range of [%f, %f] (too high)", valueName, lower, upper)); 287 } 288 289 return value; 290 } 291 292 /** 293 * Ensures that the argument int value is within the inclusive range. 294 * 295 * @param value a int value 296 * @param lower the lower endpoint of the inclusive range 297 * @param upper the upper endpoint of the inclusive range 298 * @param valueName the name of the argument to use if the check fails 299 * 300 * @return the validated int value 301 * 302 * @throws IllegalArgumentException if {@code value} was not within the range 303 */ 304 public static int checkArgumentInRange(int value, int lower, int upper, 305 String valueName) { 306 if (value < lower) { 307 throw new IllegalArgumentException( 308 String.format( 309 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper)); 310 } else if (value > upper) { 311 throw new IllegalArgumentException( 312 String.format( 313 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper)); 314 } 315 316 return value; 317 } 318 319 /** 320 * Ensures that the argument long value is within the inclusive range. 321 * 322 * @param value a long value 323 * @param lower the lower endpoint of the inclusive range 324 * @param upper the upper endpoint of the inclusive range 325 * @param valueName the name of the argument to use if the check fails 326 * 327 * @return the validated long value 328 * 329 * @throws IllegalArgumentException if {@code value} was not within the range 330 */ 331 public static long checkArgumentInRange(long value, long lower, long upper, 332 String valueName) { 333 if (value < lower) { 334 throw new IllegalArgumentException( 335 String.format( 336 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper)); 337 } else if (value > upper) { 338 throw new IllegalArgumentException( 339 String.format( 340 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper)); 341 } 342 343 return value; 344 } 345 346 /** 347 * Ensures that the array is not {@code null}, and none of its elements are {@code null}. 348 * 349 * @param value an array of boxed objects 350 * @param valueName the name of the argument to use if the check fails 351 * 352 * @return the validated array 353 * 354 * @throws NullPointerException if the {@code value} or any of its elements were {@code null} 355 */ 356 public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) { 357 if (value == null) { 358 throw new NullPointerException(valueName + " must not be null"); 359 } 360 361 for (int i = 0; i < value.length; ++i) { 362 if (value[i] == null) { 363 throw new NullPointerException( 364 String.format("%s[%d] must not be null", valueName, i)); 365 } 366 } 367 368 return value; 369 } 370 371 /** 372 * Ensures that the {@link Collection} is not {@code null}, and none of its elements are 373 * {@code null}. 374 * 375 * @param value a {@link Collection} of boxed objects 376 * @param valueName the name of the argument to use if the check fails 377 * 378 * @return the validated {@link Collection} 379 * 380 * @throws NullPointerException if the {@code value} or any of its elements were {@code null} 381 */ 382 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull( 383 final C value, final String valueName) { 384 if (value == null) { 385 throw new NullPointerException(valueName + " must not be null"); 386 } 387 388 long ctr = 0; 389 for (T elem : value) { 390 if (elem == null) { 391 throw new NullPointerException( 392 String.format("%s[%d] must not be null", valueName, ctr)); 393 } 394 ++ctr; 395 } 396 397 return value; 398 } 399 400 /** 401 * Ensures that the {@link Collection} is not {@code null}, and contains at least one element. 402 * 403 * @param value a {@link Collection} of boxed elements. 404 * @param valueName the name of the argument to use if the check fails. 405 406 * @return the validated {@link Collection} 407 * 408 * @throws NullPointerException if the {@code value} was {@code null} 409 * @throws IllegalArgumentException if the {@code value} was empty 410 */ 411 public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value, 412 final String valueName) { 413 if (value == null) { 414 throw new NullPointerException(valueName + " must not be null"); 415 } 416 if (value.isEmpty()) { 417 throw new IllegalArgumentException(valueName + " is empty"); 418 } 419 return value; 420 } 421 422 /** 423 * Ensures that all elements in the argument floating point array are within the inclusive range 424 * 425 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers 426 * will always be out of range.</p> 427 * 428 * @param value a floating point array of values 429 * @param lower the lower endpoint of the inclusive range 430 * @param upper the upper endpoint of the inclusive range 431 * @param valueName the name of the argument to use if the check fails 432 * 433 * @return the validated floating point value 434 * 435 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range 436 * @throws NullPointerException if the {@code value} was {@code null} 437 */ 438 public static float[] checkArrayElementsInRange(float[] value, float lower, float upper, 439 String valueName) { 440 checkNotNull(value, valueName + " must not be null"); 441 442 for (int i = 0; i < value.length; ++i) { 443 float v = value[i]; 444 445 if (Float.isNaN(v)) { 446 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN"); 447 } else if (v < lower) { 448 throw new IllegalArgumentException( 449 String.format("%s[%d] is out of range of [%f, %f] (too low)", 450 valueName, i, lower, upper)); 451 } else if (v > upper) { 452 throw new IllegalArgumentException( 453 String.format("%s[%d] is out of range of [%f, %f] (too high)", 454 valueName, i, lower, upper)); 455 } 456 } 457 458 return value; 459 } 460} 461