blob: 5bc96d8ee1d314b64d2a0f7c58972603aa6e3db0 [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;
Artur Satayev2a9f3b82019-12-10 17:47:55 +000021import android.compat.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 /**
Benedict Wong5501fca2019-10-28 19:03:05 -0700105 * Ensures that an string reference passed as a parameter to the calling method is not empty.
106 *
107 * @param string an string reference
108 * @param messageTemplate a printf-style message template to use if the check fails; will be
109 * converted to a string using {@link String#format(String, Object...)}
110 * @param messageArgs arguments for {@code messageTemplate}
111 * @return the string reference that was validated
112 * @throws IllegalArgumentException if {@code string} is empty
113 */
114 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(
115 final T string, final String messageTemplate, final Object... messageArgs) {
116 if (TextUtils.isEmpty(string)) {
117 throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
118 }
119 return string;
120 }
121
122 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700123 * Ensures that an object reference passed as a parameter to the calling
124 * method is not null.
125 *
126 * @param reference an object reference
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) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700132 if (reference == null) {
133 throw new NullPointerException();
134 }
135 return reference;
136 }
137
138 /**
139 * 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 errorMessage the exception message to use if the check fails; will
144 * be converted to a string using {@link String#valueOf(Object)}
145 * @return the non-null reference that was validated
146 * @throws NullPointerException if {@code reference} is null
147 */
Andrei Onea15884392019-03-22 17:28:11 +0000148 @UnsupportedAppUsage
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800149 public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700150 if (reference == null) {
151 throw new NullPointerException(String.valueOf(errorMessage));
152 }
153 return reference;
154 }
155
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700156 /**
Eugene Suslaadce09b2017-03-29 13:15:32 -0700157 * Ensures that an object reference passed as a parameter to the calling
158 * method is not null.
159 *
160 * @param reference an object reference
161 * @param messageTemplate a printf-style message template to use if the check fails; will
162 * be converted to a string using {@link String#format(String, Object...)}
163 * @param messageArgs arguments for {@code messageTemplate}
164 * @return the non-null reference that was validated
165 * @throws NullPointerException if {@code reference} is null
166 */
167 public static @NonNull <T> T checkNotNull(final T reference,
168 final String messageTemplate,
169 final Object... messageArgs) {
170 if (reference == null) {
171 throw new NullPointerException(String.format(messageTemplate, messageArgs));
172 }
173 return reference;
174 }
175
176 /**
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700177 * Ensures the truth of an expression involving the state of the calling
178 * instance, but not involving any parameters to the calling method.
179 *
180 * @param expression a boolean expression
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800181 * @param message exception message
182 * @throws IllegalStateException if {@code expression} is false
183 */
Andrei Onea15884392019-03-22 17:28:11 +0000184 @UnsupportedAppUsage
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800185 public static void checkState(final boolean expression, String message) {
186 if (!expression) {
187 throw new IllegalStateException(message);
188 }
189 }
190
191 /**
192 * Ensures the truth of an expression involving the state of the calling
193 * instance, but not involving any parameters to the calling method.
194 *
195 * @param expression a boolean expression
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700196 * @throws IllegalStateException if {@code expression} is false
197 */
Andrei Onea15884392019-03-22 17:28:11 +0000198 @UnsupportedAppUsage
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700199 public static void checkState(final boolean expression) {
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800200 checkState(expression, null);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700201 }
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700202
203 /**
204 * Check the requested flags, throwing if any requested flags are outside
205 * the allowed set.
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700206 *
207 * @return the validated requested flags.
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700208 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700209 public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700210 if ((requestedFlags & allowedFlags) != requestedFlags) {
211 throw new IllegalArgumentException("Requested flags 0x"
212 + Integer.toHexString(requestedFlags) + ", but only 0x"
213 + Integer.toHexString(allowedFlags) + " are allowed");
214 }
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700215
216 return requestedFlags;
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700217 }
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700218
219 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100220 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700221 *
222 * @param value a numeric int value
223 * @param errorMessage the exception message to use if the check fails
224 * @return the validated numeric value
225 * @throws IllegalArgumentException if {@code value} was negative
226 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800227 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
228 final String errorMessage) {
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700229 if (value < 0) {
230 throw new IllegalArgumentException(errorMessage);
231 }
232
233 return value;
234 }
235
236 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100237 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700238 *
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700239 * @param value a numeric int value
240 *
241 * @return the validated numeric value
242 * @throws IllegalArgumentException if {@code value} was negative
243 */
244 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
245 if (value < 0) {
246 throw new IllegalArgumentException();
247 }
248
249 return value;
250 }
251
252 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100253 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700254 *
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700255 * @param value a numeric long value
Philip P. Moltmann4723f362016-03-30 13:48:38 -0700256 * @return the validated numeric value
257 * @throws IllegalArgumentException if {@code value} was negative
258 */
259 public static long checkArgumentNonnegative(final long value) {
260 if (value < 0) {
261 throw new IllegalArgumentException();
262 }
263
264 return value;
265 }
266
267 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100268 * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
Philip P. Moltmann4723f362016-03-30 13:48:38 -0700269 *
270 * @param value a numeric long value
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700271 * @param errorMessage the exception message to use if the check fails
272 * @return the validated numeric value
273 * @throws IllegalArgumentException if {@code value} was negative
274 */
275 public static long checkArgumentNonnegative(final long value, final String errorMessage) {
276 if (value < 0) {
277 throw new IllegalArgumentException(errorMessage);
278 }
279
280 return value;
281 }
282
283 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100284 * Ensures that that the argument numeric value is positive (greater than 0).
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700285 *
286 * @param value a numeric int value
287 * @param errorMessage the exception message to use if the check fails
288 * @return the validated numeric value
289 * @throws IllegalArgumentException if {@code value} was not positive
290 */
291 public static int checkArgumentPositive(final int value, final String errorMessage) {
292 if (value <= 0) {
293 throw new IllegalArgumentException(errorMessage);
294 }
295
296 return value;
297 }
298
299 /**
Mihai Popa469aba82018-07-18 14:52:26 +0100300 * Ensures that the argument floating point value is non-negative (greater than or equal to 0).
301 * @param value a floating point value
302 * @param errorMessage the exteption message to use if the check fails
303 * @return the validated numeric value
304 * @throws IllegalArgumentException if {@code value} was negative
305 */
306 public static float checkArgumentNonNegative(final float value, final String errorMessage) {
307 if (value < 0) {
308 throw new IllegalArgumentException(errorMessage);
309 }
310
311 return value;
312 }
313
314 /**
315 * Ensures that the argument floating point value is positive (greater than 0).
316 * @param value a floating point value
317 * @param errorMessage the exteption message to use if the check fails
318 * @return the validated numeric value
319 * @throws IllegalArgumentException if {@code value} was not positive
320 */
321 public static float checkArgumentPositive(final float value, final String errorMessage) {
322 if (value <= 0) {
323 throw new IllegalArgumentException(errorMessage);
324 }
325
326 return value;
327 }
328
329 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700330 * Ensures that the argument floating point value is a finite number.
331 *
332 * <p>A finite number is defined to be both representable (that is, not NaN) and
333 * not infinite (that is neither positive or negative infinity).</p>
334 *
335 * @param value a floating point value
336 * @param valueName the name of the argument to use if the check fails
337 *
338 * @return the validated floating point value
339 *
340 * @throws IllegalArgumentException if {@code value} was not finite
341 */
342 public static float checkArgumentFinite(final float value, final String valueName) {
343 if (Float.isNaN(value)) {
344 throw new IllegalArgumentException(valueName + " must not be NaN");
345 } else if (Float.isInfinite(value)) {
346 throw new IllegalArgumentException(valueName + " must not be infinite");
347 }
348
349 return value;
350 }
351
352 /**
353 * Ensures that the argument floating point value is within the inclusive range.
354 *
355 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
356 * will always be out of range.</p>
357 *
358 * @param value a floating point value
359 * @param lower the lower endpoint of the inclusive range
360 * @param upper the upper endpoint of the inclusive range
361 * @param valueName the name of the argument to use if the check fails
362 *
363 * @return the validated floating point value
364 *
365 * @throws IllegalArgumentException if {@code value} was not within the range
366 */
367 public static float checkArgumentInRange(float value, float lower, float upper,
368 String valueName) {
369 if (Float.isNaN(value)) {
370 throw new IllegalArgumentException(valueName + " must not be NaN");
371 } else if (value < lower) {
372 throw new IllegalArgumentException(
373 String.format(
374 "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
375 } else if (value > upper) {
376 throw new IllegalArgumentException(
377 String.format(
378 "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
379 }
380
381 return value;
382 }
383
384 /**
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700385 * Ensures that the argument int value is within the inclusive range.
386 *
387 * @param value a int value
388 * @param lower the lower endpoint of the inclusive range
389 * @param upper the upper endpoint of the inclusive range
390 * @param valueName the name of the argument to use if the check fails
391 *
392 * @return the validated int value
393 *
394 * @throws IllegalArgumentException if {@code value} was not within the range
395 */
Andrei Onea15884392019-03-22 17:28:11 +0000396 @UnsupportedAppUsage
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700397 public static int checkArgumentInRange(int value, int lower, int upper,
398 String valueName) {
399 if (value < lower) {
400 throw new IllegalArgumentException(
401 String.format(
402 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
403 } else if (value > upper) {
404 throw new IllegalArgumentException(
405 String.format(
406 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
407 }
408
409 return value;
410 }
411
412 /**
Daichi Hirono2dd48252016-01-12 15:46:41 +0900413 * Ensures that the argument long value is within the inclusive range.
414 *
415 * @param value a long value
416 * @param lower the lower endpoint of the inclusive range
417 * @param upper the upper endpoint of the inclusive range
418 * @param valueName the name of the argument to use if the check fails
419 *
420 * @return the validated long value
421 *
422 * @throws IllegalArgumentException if {@code value} was not within the range
423 */
424 public static long checkArgumentInRange(long value, long lower, long upper,
425 String valueName) {
426 if (value < lower) {
427 throw new IllegalArgumentException(
428 String.format(
429 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
430 } else if (value > upper) {
431 throw new IllegalArgumentException(
432 String.format(
433 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
434 }
435
436 return value;
437 }
438
439 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700440 * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700441 *
442 * @param value an array of boxed objects
443 * @param valueName the name of the argument to use if the check fails
444 *
445 * @return the validated array
446 *
447 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
448 */
449 public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
450 if (value == null) {
451 throw new NullPointerException(valueName + " must not be null");
452 }
453
454 for (int i = 0; i < value.length; ++i) {
455 if (value[i] == null) {
456 throw new NullPointerException(
457 String.format("%s[%d] must not be null", valueName, i));
458 }
459 }
460
461 return value;
462 }
463
464 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700465 * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
466 * {@code null}.
467 *
468 * @param value a {@link Collection} of boxed objects
469 * @param valueName the name of the argument to use if the check fails
470 *
471 * @return the validated {@link Collection}
472 *
473 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
474 */
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -0800475 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
476 final C value, final String valueName) {
Ruben Brunk91838de2014-07-16 17:24:17 -0700477 if (value == null) {
478 throw new NullPointerException(valueName + " must not be null");
479 }
480
481 long ctr = 0;
482 for (T elem : value) {
483 if (elem == null) {
484 throw new NullPointerException(
485 String.format("%s[%d] must not be null", valueName, ctr));
486 }
487 ++ctr;
488 }
489
490 return value;
491 }
492
493 /**
494 * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
495 *
496 * @param value a {@link Collection} of boxed elements.
497 * @param valueName the name of the argument to use if the check fails.
498
499 * @return the validated {@link Collection}
500 *
501 * @throws NullPointerException if the {@code value} was {@code null}
502 * @throws IllegalArgumentException if the {@code value} was empty
503 */
504 public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
505 final String valueName) {
506 if (value == null) {
507 throw new NullPointerException(valueName + " must not be null");
508 }
509 if (value.isEmpty()) {
510 throw new IllegalArgumentException(valueName + " is empty");
511 }
512 return value;
513 }
514
515 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700516 * Ensures that all elements in the argument floating point array are within the inclusive range
517 *
518 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
519 * will always be out of range.</p>
520 *
521 * @param value a floating point array of values
522 * @param lower the lower endpoint of the inclusive range
523 * @param upper the upper endpoint of the inclusive range
524 * @param valueName the name of the argument to use if the check fails
525 *
526 * @return the validated floating point value
527 *
528 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
529 * @throws NullPointerException if the {@code value} was {@code null}
530 */
531 public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
532 String valueName) {
533 checkNotNull(value, valueName + " must not be null");
534
535 for (int i = 0; i < value.length; ++i) {
536 float v = value[i];
537
538 if (Float.isNaN(v)) {
539 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
540 } else if (v < lower) {
541 throw new IllegalArgumentException(
542 String.format("%s[%d] is out of range of [%f, %f] (too low)",
543 valueName, i, lower, upper));
544 } else if (v > upper) {
545 throw new IllegalArgumentException(
546 String.format("%s[%d] is out of range of [%f, %f] (too high)",
547 valueName, i, lower, upper));
548 }
549 }
550
551 return value;
552 }
Michael Wrighteef0e132017-11-21 17:57:52 +0000553
554 /**
555 * Ensures that all elements in the argument integer array are within the inclusive range
556 *
557 * @param value an integer array of values
558 * @param lower the lower endpoint of the inclusive range
559 * @param upper the upper endpoint of the inclusive range
560 * @param valueName the name of the argument to use if the check fails
561 *
562 * @return the validated integer array
563 *
564 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
565 * @throws NullPointerException if the {@code value} was {@code null}
566 */
567 public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
568 String valueName) {
569 checkNotNull(value, valueName + " must not be null");
570
571 for (int i = 0; i < value.length; ++i) {
572 int v = value[i];
573
574 if (v < lower) {
575 throw new IllegalArgumentException(
576 String.format("%s[%d] is out of range of [%d, %d] (too low)",
577 valueName, i, lower, upper));
578 } else if (v > upper) {
579 throw new IllegalArgumentException(
580 String.format("%s[%d] is out of range of [%d, %d] (too high)",
581 valueName, i, lower, upper));
582 }
583 }
584
585 return value;
586 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700587}