Preconditions.java revision adce09b9a48b1d25c97fe7d3c731de1862f0487b
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 that an object reference passed as a parameter to the calling 118 * method is not null. 119 * 120 * @param reference an object reference 121 * @param messageTemplate a printf-style message template to use if the check fails; will 122 * be converted to a string using {@link String#format(String, Object...)} 123 * @param messageArgs arguments for {@code messageTemplate} 124 * @return the non-null reference that was validated 125 * @throws NullPointerException if {@code reference} is null 126 */ 127 public static @NonNull <T> T checkNotNull(final T reference, 128 final String messageTemplate, 129 final Object... messageArgs) { 130 if (reference == null) { 131 throw new NullPointerException(String.format(messageTemplate, messageArgs)); 132 } 133 return reference; 134 } 135 136 /** 137 * Ensures the truth of an expression involving the state of the calling 138 * instance, but not involving any parameters to the calling method. 139 * 140 * @param expression a boolean expression 141 * @param message exception message 142 * @throws IllegalStateException if {@code expression} is false 143 */ 144 public static void checkState(final boolean expression, String message) { 145 if (!expression) { 146 throw new IllegalStateException(message); 147 } 148 } 149 150 /** 151 * Ensures the truth of an expression involving the state of the calling 152 * instance, but not involving any parameters to the calling method. 153 * 154 * @param expression a boolean expression 155 * @throws IllegalStateException if {@code expression} is false 156 */ 157 public static void checkState(final boolean expression) { 158 checkState(expression, null); 159 } 160 161 /** 162 * Check the requested flags, throwing if any requested flags are outside 163 * the allowed set. 164 * 165 * @return the validated requested flags. 166 */ 167 public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) { 168 if ((requestedFlags & allowedFlags) != requestedFlags) { 169 throw new IllegalArgumentException("Requested flags 0x" 170 + Integer.toHexString(requestedFlags) + ", but only 0x" 171 + Integer.toHexString(allowedFlags) + " are allowed"); 172 } 173 174 return requestedFlags; 175 } 176 177 /** 178 * Ensures that that the argument numeric value is non-negative. 179 * 180 * @param value a numeric int value 181 * @param errorMessage the exception message to use if the check fails 182 * @return the validated numeric value 183 * @throws IllegalArgumentException if {@code value} was negative 184 */ 185 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value, 186 final String errorMessage) { 187 if (value < 0) { 188 throw new IllegalArgumentException(errorMessage); 189 } 190 191 return value; 192 } 193 194 /** 195 * Ensures that that the argument numeric value is non-negative. 196 * 197 * @param value a numeric int value 198 * 199 * @return the validated numeric value 200 * @throws IllegalArgumentException if {@code value} was negative 201 */ 202 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) { 203 if (value < 0) { 204 throw new IllegalArgumentException(); 205 } 206 207 return value; 208 } 209 210 /** 211 * Ensures that that the argument numeric value is non-negative. 212 * 213 * @param value a numeric long value 214 * @return the validated numeric value 215 * @throws IllegalArgumentException if {@code value} was negative 216 */ 217 public static long checkArgumentNonnegative(final long value) { 218 if (value < 0) { 219 throw new IllegalArgumentException(); 220 } 221 222 return value; 223 } 224 225 /** 226 * Ensures that that the argument numeric value is non-negative. 227 * 228 * @param value a numeric long value 229 * @param errorMessage the exception message to use if the check fails 230 * @return the validated numeric value 231 * @throws IllegalArgumentException if {@code value} was negative 232 */ 233 public static long checkArgumentNonnegative(final long value, final String errorMessage) { 234 if (value < 0) { 235 throw new IllegalArgumentException(errorMessage); 236 } 237 238 return value; 239 } 240 241 /** 242 * Ensures that that the argument numeric value is positive. 243 * 244 * @param value a numeric int value 245 * @param errorMessage the exception message to use if the check fails 246 * @return the validated numeric value 247 * @throws IllegalArgumentException if {@code value} was not positive 248 */ 249 public static int checkArgumentPositive(final int value, final String errorMessage) { 250 if (value <= 0) { 251 throw new IllegalArgumentException(errorMessage); 252 } 253 254 return value; 255 } 256 257 /** 258 * Ensures that the argument floating point value is a finite number. 259 * 260 * <p>A finite number is defined to be both representable (that is, not NaN) and 261 * not infinite (that is neither positive or negative infinity).</p> 262 * 263 * @param value a floating point value 264 * @param valueName the name of the argument to use if the check fails 265 * 266 * @return the validated floating point value 267 * 268 * @throws IllegalArgumentException if {@code value} was not finite 269 */ 270 public static float checkArgumentFinite(final float value, final String valueName) { 271 if (Float.isNaN(value)) { 272 throw new IllegalArgumentException(valueName + " must not be NaN"); 273 } else if (Float.isInfinite(value)) { 274 throw new IllegalArgumentException(valueName + " must not be infinite"); 275 } 276 277 return value; 278 } 279 280 /** 281 * Ensures that the argument floating point value is within the inclusive range. 282 * 283 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers 284 * will always be out of range.</p> 285 * 286 * @param value a floating point value 287 * @param lower the lower endpoint of the inclusive range 288 * @param upper the upper endpoint of the inclusive range 289 * @param valueName the name of the argument to use if the check fails 290 * 291 * @return the validated floating point value 292 * 293 * @throws IllegalArgumentException if {@code value} was not within the range 294 */ 295 public static float checkArgumentInRange(float value, float lower, float upper, 296 String valueName) { 297 if (Float.isNaN(value)) { 298 throw new IllegalArgumentException(valueName + " must not be NaN"); 299 } else if (value < lower) { 300 throw new IllegalArgumentException( 301 String.format( 302 "%s is out of range of [%f, %f] (too low)", valueName, lower, upper)); 303 } else if (value > upper) { 304 throw new IllegalArgumentException( 305 String.format( 306 "%s is out of range of [%f, %f] (too high)", valueName, lower, upper)); 307 } 308 309 return value; 310 } 311 312 /** 313 * Ensures that the argument int value is within the inclusive range. 314 * 315 * @param value a int value 316 * @param lower the lower endpoint of the inclusive range 317 * @param upper the upper endpoint of the inclusive range 318 * @param valueName the name of the argument to use if the check fails 319 * 320 * @return the validated int value 321 * 322 * @throws IllegalArgumentException if {@code value} was not within the range 323 */ 324 public static int checkArgumentInRange(int value, int lower, int upper, 325 String valueName) { 326 if (value < lower) { 327 throw new IllegalArgumentException( 328 String.format( 329 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper)); 330 } else if (value > upper) { 331 throw new IllegalArgumentException( 332 String.format( 333 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper)); 334 } 335 336 return value; 337 } 338 339 /** 340 * Ensures that the argument long value is within the inclusive range. 341 * 342 * @param value a long value 343 * @param lower the lower endpoint of the inclusive range 344 * @param upper the upper endpoint of the inclusive range 345 * @param valueName the name of the argument to use if the check fails 346 * 347 * @return the validated long value 348 * 349 * @throws IllegalArgumentException if {@code value} was not within the range 350 */ 351 public static long checkArgumentInRange(long value, long lower, long upper, 352 String valueName) { 353 if (value < lower) { 354 throw new IllegalArgumentException( 355 String.format( 356 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper)); 357 } else if (value > upper) { 358 throw new IllegalArgumentException( 359 String.format( 360 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper)); 361 } 362 363 return value; 364 } 365 366 /** 367 * Ensures that the array is not {@code null}, and none of its elements are {@code null}. 368 * 369 * @param value an array of boxed objects 370 * @param valueName the name of the argument to use if the check fails 371 * 372 * @return the validated array 373 * 374 * @throws NullPointerException if the {@code value} or any of its elements were {@code null} 375 */ 376 public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) { 377 if (value == null) { 378 throw new NullPointerException(valueName + " must not be null"); 379 } 380 381 for (int i = 0; i < value.length; ++i) { 382 if (value[i] == null) { 383 throw new NullPointerException( 384 String.format("%s[%d] must not be null", valueName, i)); 385 } 386 } 387 388 return value; 389 } 390 391 /** 392 * Ensures that the {@link Collection} is not {@code null}, and none of its elements are 393 * {@code null}. 394 * 395 * @param value a {@link Collection} of boxed objects 396 * @param valueName the name of the argument to use if the check fails 397 * 398 * @return the validated {@link Collection} 399 * 400 * @throws NullPointerException if the {@code value} or any of its elements were {@code null} 401 */ 402 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull( 403 final C value, final String valueName) { 404 if (value == null) { 405 throw new NullPointerException(valueName + " must not be null"); 406 } 407 408 long ctr = 0; 409 for (T elem : value) { 410 if (elem == null) { 411 throw new NullPointerException( 412 String.format("%s[%d] must not be null", valueName, ctr)); 413 } 414 ++ctr; 415 } 416 417 return value; 418 } 419 420 /** 421 * Ensures that the {@link Collection} is not {@code null}, and contains at least one element. 422 * 423 * @param value a {@link Collection} of boxed elements. 424 * @param valueName the name of the argument to use if the check fails. 425 426 * @return the validated {@link Collection} 427 * 428 * @throws NullPointerException if the {@code value} was {@code null} 429 * @throws IllegalArgumentException if the {@code value} was empty 430 */ 431 public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value, 432 final String valueName) { 433 if (value == null) { 434 throw new NullPointerException(valueName + " must not be null"); 435 } 436 if (value.isEmpty()) { 437 throw new IllegalArgumentException(valueName + " is empty"); 438 } 439 return value; 440 } 441 442 /** 443 * Ensures that all elements in the argument floating point array are within the inclusive range 444 * 445 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers 446 * will always be out of range.</p> 447 * 448 * @param value a floating point array of values 449 * @param lower the lower endpoint of the inclusive range 450 * @param upper the upper endpoint of the inclusive range 451 * @param valueName the name of the argument to use if the check fails 452 * 453 * @return the validated floating point value 454 * 455 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range 456 * @throws NullPointerException if the {@code value} was {@code null} 457 */ 458 public static float[] checkArrayElementsInRange(float[] value, float lower, float upper, 459 String valueName) { 460 checkNotNull(value, valueName + " must not be null"); 461 462 for (int i = 0; i < value.length; ++i) { 463 float v = value[i]; 464 465 if (Float.isNaN(v)) { 466 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN"); 467 } else if (v < lower) { 468 throw new IllegalArgumentException( 469 String.format("%s[%d] is out of range of [%f, %f] (too low)", 470 valueName, i, lower, upper)); 471 } else if (v > upper) { 472 throw new IllegalArgumentException( 473 String.format("%s[%d] is out of range of [%f, %f] (too high)", 474 valueName, i, lower, upper)); 475 } 476 } 477 478 return value; 479 } 480} 481