blob: 731b93c18b09331d56c750e9b50ab0ee81f42ed0 [file] [log] [blame]
Jeff Sharkeyd2a45872011-05-28 20:56:34 -07001/*
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
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080019import android.annotation.IntRange;
20import android.annotation.NonNull;
Andrei Onea15884392019-03-22 17:28:11 +000021import android.annotation.UnsupportedAppUsage;
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080022import android.text.TextUtils;
23
Ruben Brunk91838de2014-07-16 17:24:17 -070024import java.util.Collection;
25
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070026/**
27 * Simple static methods to be called at the start of your own methods to verify
28 * correct arguments and state.
29 */
30public class Preconditions {
31
Andrei Onea15884392019-03-22 17:28:11 +000032 @UnsupportedAppUsage
Jeff Sharkey620b32b2015-04-23 19:36:02 -070033 public static void checkArgument(boolean expression) {
34 if (!expression) {
35 throw new IllegalArgumentException();
36 }
37 }
38
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070039 /**
Philip P. Moltmannd74d1e52016-03-17 16:37:47 -070040 * Ensures that an expression checking an argument is true.
41 *
42 * @param expression the expression to check
43 * @param errorMessage the exception message to use if the check fails; will
44 * be converted to a string using {@link String#valueOf(Object)}
45 * @throws IllegalArgumentException if {@code expression} is false
46 */
Andrei Onea15884392019-03-22 17:28:11 +000047 @UnsupportedAppUsage
Philip P. Moltmannd74d1e52016-03-17 16:37:47 -070048 public static void checkArgument(boolean expression, final Object errorMessage) {
49 if (!expression) {
50 throw new IllegalArgumentException(String.valueOf(errorMessage));
51 }
52 }
53
54 /**
Eugene Suslacf00ade2017-04-10 11:51:58 -070055 * Ensures that an expression checking an argument is true.
56 *
57 * @param expression the expression to check
58 * @param messageTemplate a printf-style message template to use if the check fails; will
59 * be converted to a string using {@link String#format(String, Object...)}
60 * @param messageArgs arguments for {@code messageTemplate}
61 * @throws IllegalArgumentException if {@code expression} is false
62 */
63 public static void checkArgument(boolean expression,
64 final String messageTemplate,
65 final Object... messageArgs) {
66 if (!expression) {
67 throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
68 }
69 }
70
71 /**
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080072 * Ensures that an string reference passed as a parameter to the calling
73 * method is not empty.
74 *
75 * @param string an string reference
76 * @return the string reference that was validated
77 * @throws IllegalArgumentException if {@code string} is empty
78 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -070079 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -080080 if (TextUtils.isEmpty(string)) {
81 throw new IllegalArgumentException();
82 }
83 return string;
84 }
85
86 /**
87 * Ensures that an string reference passed as a parameter to the calling
88 * method is not empty.
89 *
90 * @param string an string reference
91 * @param errorMessage the exception message to use if the check fails; will
92 * be converted to a string using {@link String#valueOf(Object)}
93 * @return the string reference that was validated
94 * @throws IllegalArgumentException if {@code string} is empty
95 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -070096 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080097 final Object errorMessage) {
98 if (TextUtils.isEmpty(string)) {
99 throw new IllegalArgumentException(String.valueOf(errorMessage));
100 }
101 return string;
102 }
103
104 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700105 * Ensures that an object reference passed as a parameter to the calling
106 * method is not null.
107 *
108 * @param reference an object reference
109 * @return the non-null reference that was validated
110 * @throws NullPointerException if {@code reference} is null
111 */
Andrei Onea15884392019-03-22 17:28:11 +0000112 @UnsupportedAppUsage
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800113 public static @NonNull <T> T checkNotNull(final T reference) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700114 if (reference == null) {
115 throw new NullPointerException();
116 }
117 return reference;
118 }
119
120 /**
121 * Ensures that an object reference passed as a parameter to the calling
122 * method is not null.
123 *
124 * @param reference an object reference
125 * @param errorMessage the exception message to use if the check fails; will
126 * be converted to a string using {@link String#valueOf(Object)}
127 * @return the non-null reference that was validated
128 * @throws NullPointerException if {@code reference} is null
129 */
Andrei Onea15884392019-03-22 17:28:11 +0000130 @UnsupportedAppUsage
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800131 public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700132 if (reference == null) {
133 throw new NullPointerException(String.valueOf(errorMessage));
134 }
135 return reference;
136 }
137
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700138 /**
Eugene Suslaadce09b2017-03-29 13:15:32 -0700139 * Ensures that an object reference passed as a parameter to the calling
140 * method is not null.
141 *
142 * @param reference an object reference
143 * @param messageTemplate a printf-style message template to use if the check fails; will
144 * be converted to a string using {@link String#format(String, Object...)}
145 * @param messageArgs arguments for {@code messageTemplate}
146 * @return the non-null reference that was validated
147 * @throws NullPointerException if {@code reference} is null
148 */
149 public static @NonNull <T> T checkNotNull(final T reference,
150 final String messageTemplate,
151 final Object... messageArgs) {
152 if (reference == null) {
153 throw new NullPointerException(String.format(messageTemplate, messageArgs));
154 }
155 return reference;
156 }
157
158 /**
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700159 * Ensures the truth of an expression involving the state of the calling
160 * instance, but not involving any parameters to the calling method.
161 *
162 * @param expression a boolean expression
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800163 * @param message exception message
164 * @throws IllegalStateException if {@code expression} is false
165 */
Andrei Onea15884392019-03-22 17:28:11 +0000166 @UnsupportedAppUsage
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800167 public static void checkState(final boolean expression, String message) {
168 if (!expression) {
169 throw new IllegalStateException(message);
170 }
171 }
172
173 /**
174 * Ensures the truth of an expression involving the state of the calling
175 * instance, but not involving any parameters to the calling method.
176 *
177 * @param expression a boolean expression
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700178 * @throws IllegalStateException if {@code expression} is false
179 */
Andrei Onea15884392019-03-22 17:28:11 +0000180 @UnsupportedAppUsage
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700181 public static void checkState(final boolean expression) {
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800182 checkState(expression, null);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700183 }
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700184
185 /**
186 * Check the requested flags, throwing if any requested flags are outside
187 * the allowed set.
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700188 *
189 * @return the validated requested flags.
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700190 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700191 public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700192 if ((requestedFlags & allowedFlags) != requestedFlags) {
193 throw new IllegalArgumentException("Requested flags 0x"
194 + Integer.toHexString(requestedFlags) + ", but only 0x"
195 + Integer.toHexString(allowedFlags) + " are allowed");
196 }
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700197
198 return requestedFlags;
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700199 }
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700200
201 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100202 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700203 *
204 * @param value a numeric int value
205 * @param errorMessage the exception message to use if the check fails
206 * @return the validated numeric value
207 * @throws IllegalArgumentException if {@code value} was negative
208 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800209 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
210 final String errorMessage) {
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700211 if (value < 0) {
212 throw new IllegalArgumentException(errorMessage);
213 }
214
215 return value;
216 }
217
218 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100219 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700220 *
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700221 * @param value a numeric int value
222 *
223 * @return the validated numeric value
224 * @throws IllegalArgumentException if {@code value} was negative
225 */
226 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
227 if (value < 0) {
228 throw new IllegalArgumentException();
229 }
230
231 return value;
232 }
233
234 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100235 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700236 *
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700237 * @param value a numeric long value
Philip P. Moltmann4723f362016-03-30 13:48:38 -0700238 * @return the validated numeric value
239 * @throws IllegalArgumentException if {@code value} was negative
240 */
241 public static long checkArgumentNonnegative(final long value) {
242 if (value < 0) {
243 throw new IllegalArgumentException();
244 }
245
246 return value;
247 }
248
249 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100250 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Philip P. Moltmann4723f362016-03-30 13:48:38 -0700251 *
252 * @param value a numeric long value
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700253 * @param errorMessage the exception message to use if the check fails
254 * @return the validated numeric value
255 * @throws IllegalArgumentException if {@code value} was negative
256 */
257 public static long checkArgumentNonnegative(final long value, final String errorMessage) {
258 if (value < 0) {
259 throw new IllegalArgumentException(errorMessage);
260 }
261
262 return value;
263 }
264
265 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100266 * Ensures that that the argument numeric value is positive (greater than 0).
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700267 *
268 * @param value a numeric int value
269 * @param errorMessage the exception message to use if the check fails
270 * @return the validated numeric value
271 * @throws IllegalArgumentException if {@code value} was not positive
272 */
273 public static int checkArgumentPositive(final int value, final String errorMessage) {
274 if (value <= 0) {
275 throw new IllegalArgumentException(errorMessage);
276 }
277
278 return value;
279 }
280
281 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100282 * Ensures that the argument floating point value is non-negative (greater than or equal to 0).
283 * @param value a floating point value
284 * @param errorMessage the exteption message to use if the check fails
285 * @return the validated numeric value
286 * @throws IllegalArgumentException if {@code value} was negative
287 */
288 public static float checkArgumentNonNegative(final float value, final String errorMessage) {
289 if (value < 0) {
290 throw new IllegalArgumentException(errorMessage);
291 }
292
293 return value;
294 }
295
296 /**
297 * Ensures that the argument floating point value is positive (greater than 0).
298 * @param value a floating point value
299 * @param errorMessage the exteption message to use if the check fails
300 * @return the validated numeric value
301 * @throws IllegalArgumentException if {@code value} was not positive
302 */
303 public static float checkArgumentPositive(final float value, final String errorMessage) {
304 if (value <= 0) {
305 throw new IllegalArgumentException(errorMessage);
306 }
307
308 return value;
309 }
310
311 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700312 * Ensures that the argument floating point value is a finite number.
313 *
314 * <p>A finite number is defined to be both representable (that is, not NaN) and
315 * not infinite (that is neither positive or negative infinity).</p>
316 *
317 * @param value a floating point value
318 * @param valueName the name of the argument to use if the check fails
319 *
320 * @return the validated floating point value
321 *
322 * @throws IllegalArgumentException if {@code value} was not finite
323 */
324 public static float checkArgumentFinite(final float value, final String valueName) {
325 if (Float.isNaN(value)) {
326 throw new IllegalArgumentException(valueName + " must not be NaN");
327 } else if (Float.isInfinite(value)) {
328 throw new IllegalArgumentException(valueName + " must not be infinite");
329 }
330
331 return value;
332 }
333
334 /**
335 * Ensures that the argument floating point value is within the inclusive range.
336 *
337 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
338 * will always be out of range.</p>
339 *
340 * @param value a floating point value
341 * @param lower the lower endpoint of the inclusive range
342 * @param upper the upper endpoint of the inclusive range
343 * @param valueName the name of the argument to use if the check fails
344 *
345 * @return the validated floating point value
346 *
347 * @throws IllegalArgumentException if {@code value} was not within the range
348 */
349 public static float checkArgumentInRange(float value, float lower, float upper,
350 String valueName) {
351 if (Float.isNaN(value)) {
352 throw new IllegalArgumentException(valueName + " must not be NaN");
353 } else if (value < lower) {
354 throw new IllegalArgumentException(
355 String.format(
356 "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
357 } else if (value > upper) {
358 throw new IllegalArgumentException(
359 String.format(
360 "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
361 }
362
363 return value;
364 }
365
366 /**
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700367 * Ensures that the argument int value is within the inclusive range.
368 *
369 * @param value a int value
370 * @param lower the lower endpoint of the inclusive range
371 * @param upper the upper endpoint of the inclusive range
372 * @param valueName the name of the argument to use if the check fails
373 *
374 * @return the validated int value
375 *
376 * @throws IllegalArgumentException if {@code value} was not within the range
377 */
Andrei Onea15884392019-03-22 17:28:11 +0000378 @UnsupportedAppUsage
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700379 public static int checkArgumentInRange(int value, int lower, int upper,
380 String valueName) {
381 if (value < lower) {
382 throw new IllegalArgumentException(
383 String.format(
384 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
385 } else if (value > upper) {
386 throw new IllegalArgumentException(
387 String.format(
388 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
389 }
390
391 return value;
392 }
393
394 /**
Daichi Hirono2dd48252016-01-12 15:46:41 +0900395 * Ensures that the argument long value is within the inclusive range.
396 *
397 * @param value a long value
398 * @param lower the lower endpoint of the inclusive range
399 * @param upper the upper endpoint of the inclusive range
400 * @param valueName the name of the argument to use if the check fails
401 *
402 * @return the validated long value
403 *
404 * @throws IllegalArgumentException if {@code value} was not within the range
405 */
406 public static long checkArgumentInRange(long value, long lower, long upper,
407 String valueName) {
408 if (value < lower) {
409 throw new IllegalArgumentException(
410 String.format(
411 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
412 } else if (value > upper) {
413 throw new IllegalArgumentException(
414 String.format(
415 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
416 }
417
418 return value;
419 }
420
421 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700422 * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700423 *
424 * @param value an array of boxed objects
425 * @param valueName the name of the argument to use if the check fails
426 *
427 * @return the validated array
428 *
429 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
430 */
431 public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
432 if (value == null) {
433 throw new NullPointerException(valueName + " must not be null");
434 }
435
436 for (int i = 0; i < value.length; ++i) {
437 if (value[i] == null) {
438 throw new NullPointerException(
439 String.format("%s[%d] must not be null", valueName, i));
440 }
441 }
442
443 return value;
444 }
445
446 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700447 * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
448 * {@code null}.
449 *
450 * @param value a {@link Collection} of boxed objects
451 * @param valueName the name of the argument to use if the check fails
452 *
453 * @return the validated {@link Collection}
454 *
455 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
456 */
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -0800457 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
458 final C value, final String valueName) {
Ruben Brunk91838de2014-07-16 17:24:17 -0700459 if (value == null) {
460 throw new NullPointerException(valueName + " must not be null");
461 }
462
463 long ctr = 0;
464 for (T elem : value) {
465 if (elem == null) {
466 throw new NullPointerException(
467 String.format("%s[%d] must not be null", valueName, ctr));
468 }
469 ++ctr;
470 }
471
472 return value;
473 }
474
475 /**
476 * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
477 *
478 * @param value a {@link Collection} of boxed elements.
479 * @param valueName the name of the argument to use if the check fails.
480
481 * @return the validated {@link Collection}
482 *
483 * @throws NullPointerException if the {@code value} was {@code null}
484 * @throws IllegalArgumentException if the {@code value} was empty
485 */
486 public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
487 final String valueName) {
488 if (value == null) {
489 throw new NullPointerException(valueName + " must not be null");
490 }
491 if (value.isEmpty()) {
492 throw new IllegalArgumentException(valueName + " is empty");
493 }
494 return value;
495 }
496
497 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700498 * Ensures that all elements in the argument floating point array are within the inclusive range
499 *
500 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
501 * will always be out of range.</p>
502 *
503 * @param value a floating point array of values
504 * @param lower the lower endpoint of the inclusive range
505 * @param upper the upper endpoint of the inclusive range
506 * @param valueName the name of the argument to use if the check fails
507 *
508 * @return the validated floating point value
509 *
510 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
511 * @throws NullPointerException if the {@code value} was {@code null}
512 */
513 public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
514 String valueName) {
515 checkNotNull(value, valueName + " must not be null");
516
517 for (int i = 0; i < value.length; ++i) {
518 float v = value[i];
519
520 if (Float.isNaN(v)) {
521 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
522 } else if (v < lower) {
523 throw new IllegalArgumentException(
524 String.format("%s[%d] is out of range of [%f, %f] (too low)",
525 valueName, i, lower, upper));
526 } else if (v > upper) {
527 throw new IllegalArgumentException(
528 String.format("%s[%d] is out of range of [%f, %f] (too high)",
529 valueName, i, lower, upper));
530 }
531 }
532
533 return value;
534 }
Michael Wrighteef0e132017-11-21 17:57:52 +0000535
536 /**
537 * Ensures that all elements in the argument integer array are within the inclusive range
538 *
539 * @param value an integer array of values
540 * @param lower the lower endpoint of the inclusive range
541 * @param upper the upper endpoint of the inclusive range
542 * @param valueName the name of the argument to use if the check fails
543 *
544 * @return the validated integer array
545 *
546 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
547 * @throws NullPointerException if the {@code value} was {@code null}
548 */
549 public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
550 String valueName) {
551 checkNotNull(value, valueName + " must not be null");
552
553 for (int i = 0; i < value.length; ++i) {
554 int v = value[i];
555
556 if (v < lower) {
557 throw new IllegalArgumentException(
558 String.format("%s[%d] is out of range of [%d, %d] (too low)",
559 valueName, i, lower, upper));
560 } else if (v > upper) {
561 throw new IllegalArgumentException(
562 String.format("%s[%d] is out of range of [%d, %d] (too high)",
563 valueName, i, lower, upper));
564 }
565 }
566
567 return value;
568 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700569}