blob: e5d571672ce2e17e6cc8c7a79ce323d289b22d79 [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;
21import android.text.TextUtils;
22
Ruben Brunk91838de2014-07-16 17:24:17 -070023import java.util.Collection;
24
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070025/**
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
Jeff Sharkey620b32b2015-04-23 19:36:02 -070031 public static void checkArgument(boolean expression) {
32 if (!expression) {
33 throw new IllegalArgumentException();
34 }
35 }
36
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070037 /**
Philip P. Moltmannd74d1e52016-03-17 16:37:47 -070038 * 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 /**
Eugene Suslacf00ade2017-04-10 11:51:58 -070052 * Ensures that an expression checking an argument is true.
53 *
54 * @param expression the expression to check
55 * @param messageTemplate a printf-style message template to use if the check fails; will
56 * be converted to a string using {@link String#format(String, Object...)}
57 * @param messageArgs arguments for {@code messageTemplate}
58 * @throws IllegalArgumentException if {@code expression} is false
59 */
60 public static void checkArgument(boolean expression,
61 final String messageTemplate,
62 final Object... messageArgs) {
63 if (!expression) {
64 throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
65 }
66 }
67
68 /**
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080069 * Ensures that an string reference passed as a parameter to the calling
70 * method is not empty.
71 *
72 * @param string an string reference
73 * @return the string reference that was validated
74 * @throws IllegalArgumentException if {@code string} is empty
75 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -070076 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -080077 if (TextUtils.isEmpty(string)) {
78 throw new IllegalArgumentException();
79 }
80 return string;
81 }
82
83 /**
84 * Ensures that an string reference passed as a parameter to the calling
85 * method is not empty.
86 *
87 * @param string an string reference
88 * @param errorMessage the exception message to use if the check fails; will
89 * be converted to a string using {@link String#valueOf(Object)}
90 * @return the string reference that was validated
91 * @throws IllegalArgumentException if {@code string} is empty
92 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -070093 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080094 final Object errorMessage) {
95 if (TextUtils.isEmpty(string)) {
96 throw new IllegalArgumentException(String.valueOf(errorMessage));
97 }
98 return string;
99 }
100
101 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700102 * Ensures that an object reference passed as a parameter to the calling
103 * method is not null.
104 *
105 * @param reference an object reference
106 * @return the non-null reference that was validated
107 * @throws NullPointerException if {@code reference} is null
108 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800109 public static @NonNull <T> T checkNotNull(final T reference) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700110 if (reference == null) {
111 throw new NullPointerException();
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 errorMessage the exception message to use if the check fails; will
122 * be converted to a string using {@link String#valueOf(Object)}
123 * @return the non-null reference that was validated
124 * @throws NullPointerException if {@code reference} is null
125 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800126 public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700127 if (reference == null) {
128 throw new NullPointerException(String.valueOf(errorMessage));
129 }
130 return reference;
131 }
132
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700133 /**
Eugene Suslaadce09b2017-03-29 13:15:32 -0700134 * Ensures that an object reference passed as a parameter to the calling
135 * method is not null.
136 *
137 * @param reference an object reference
138 * @param messageTemplate a printf-style message template to use if the check fails; will
139 * be converted to a string using {@link String#format(String, Object...)}
140 * @param messageArgs arguments for {@code messageTemplate}
141 * @return the non-null reference that was validated
142 * @throws NullPointerException if {@code reference} is null
143 */
144 public static @NonNull <T> T checkNotNull(final T reference,
145 final String messageTemplate,
146 final Object... messageArgs) {
147 if (reference == null) {
148 throw new NullPointerException(String.format(messageTemplate, messageArgs));
149 }
150 return reference;
151 }
152
153 /**
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700154 * Ensures the truth of an expression involving the state of the calling
155 * instance, but not involving any parameters to the calling method.
156 *
157 * @param expression a boolean expression
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800158 * @param message exception message
159 * @throws IllegalStateException if {@code expression} is false
160 */
161 public static void checkState(final boolean expression, String message) {
162 if (!expression) {
163 throw new IllegalStateException(message);
164 }
165 }
166
167 /**
168 * Ensures the truth of an expression involving the state of the calling
169 * instance, but not involving any parameters to the calling method.
170 *
171 * @param expression a boolean expression
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700172 * @throws IllegalStateException if {@code expression} is false
173 */
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700174 public static void checkState(final boolean expression) {
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800175 checkState(expression, null);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700176 }
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700177
178 /**
179 * Check the requested flags, throwing if any requested flags are outside
180 * the allowed set.
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700181 *
182 * @return the validated requested flags.
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700183 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700184 public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700185 if ((requestedFlags & allowedFlags) != requestedFlags) {
186 throw new IllegalArgumentException("Requested flags 0x"
187 + Integer.toHexString(requestedFlags) + ", but only 0x"
188 + Integer.toHexString(allowedFlags) + " are allowed");
189 }
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700190
191 return requestedFlags;
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700192 }
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700193
194 /**
195 * Ensures that that the argument numeric value is non-negative.
196 *
197 * @param value a numeric int value
198 * @param errorMessage the exception message to use if the check fails
199 * @return the validated numeric value
200 * @throws IllegalArgumentException if {@code value} was negative
201 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800202 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
203 final String errorMessage) {
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700204 if (value < 0) {
205 throw new IllegalArgumentException(errorMessage);
206 }
207
208 return value;
209 }
210
211 /**
212 * Ensures that that the argument numeric value is non-negative.
213 *
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700214 * @param value a numeric int value
215 *
216 * @return the validated numeric value
217 * @throws IllegalArgumentException if {@code value} was negative
218 */
219 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
220 if (value < 0) {
221 throw new IllegalArgumentException();
222 }
223
224 return value;
225 }
226
227 /**
228 * Ensures that that the argument numeric value is non-negative.
229 *
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700230 * @param value a numeric long value
Philip P. Moltmann4723f362016-03-30 13:48:38 -0700231 * @return the validated numeric value
232 * @throws IllegalArgumentException if {@code value} was negative
233 */
234 public static long checkArgumentNonnegative(final long value) {
235 if (value < 0) {
236 throw new IllegalArgumentException();
237 }
238
239 return value;
240 }
241
242 /**
243 * Ensures that that the argument numeric value is non-negative.
244 *
245 * @param value a numeric long value
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700246 * @param errorMessage the exception message to use if the check fails
247 * @return the validated numeric value
248 * @throws IllegalArgumentException if {@code value} was negative
249 */
250 public static long checkArgumentNonnegative(final long value, final String errorMessage) {
251 if (value < 0) {
252 throw new IllegalArgumentException(errorMessage);
253 }
254
255 return value;
256 }
257
258 /**
259 * Ensures that that the argument numeric value is positive.
260 *
261 * @param value a numeric int value
262 * @param errorMessage the exception message to use if the check fails
263 * @return the validated numeric value
264 * @throws IllegalArgumentException if {@code value} was not positive
265 */
266 public static int checkArgumentPositive(final int value, final String errorMessage) {
267 if (value <= 0) {
268 throw new IllegalArgumentException(errorMessage);
269 }
270
271 return value;
272 }
273
274 /**
275 * Ensures that the argument floating point value is a finite number.
276 *
277 * <p>A finite number is defined to be both representable (that is, not NaN) and
278 * not infinite (that is neither positive or negative infinity).</p>
279 *
280 * @param value a floating point value
281 * @param valueName the name of the argument to use if the check fails
282 *
283 * @return the validated floating point value
284 *
285 * @throws IllegalArgumentException if {@code value} was not finite
286 */
287 public static float checkArgumentFinite(final float value, final String valueName) {
288 if (Float.isNaN(value)) {
289 throw new IllegalArgumentException(valueName + " must not be NaN");
290 } else if (Float.isInfinite(value)) {
291 throw new IllegalArgumentException(valueName + " must not be infinite");
292 }
293
294 return value;
295 }
296
297 /**
298 * Ensures that the argument floating point value is within the inclusive range.
299 *
300 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
301 * will always be out of range.</p>
302 *
303 * @param value a floating point value
304 * @param lower the lower endpoint of the inclusive range
305 * @param upper the upper endpoint of the inclusive range
306 * @param valueName the name of the argument to use if the check fails
307 *
308 * @return the validated floating point value
309 *
310 * @throws IllegalArgumentException if {@code value} was not within the range
311 */
312 public static float checkArgumentInRange(float value, float lower, float upper,
313 String valueName) {
314 if (Float.isNaN(value)) {
315 throw new IllegalArgumentException(valueName + " must not be NaN");
316 } else if (value < lower) {
317 throw new IllegalArgumentException(
318 String.format(
319 "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
320 } else if (value > upper) {
321 throw new IllegalArgumentException(
322 String.format(
323 "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
324 }
325
326 return value;
327 }
328
329 /**
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700330 * Ensures that the argument int value is within the inclusive range.
331 *
332 * @param value a int value
333 * @param lower the lower endpoint of the inclusive range
334 * @param upper the upper endpoint of the inclusive range
335 * @param valueName the name of the argument to use if the check fails
336 *
337 * @return the validated int value
338 *
339 * @throws IllegalArgumentException if {@code value} was not within the range
340 */
341 public static int checkArgumentInRange(int value, int lower, int upper,
342 String valueName) {
343 if (value < lower) {
344 throw new IllegalArgumentException(
345 String.format(
346 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
347 } else if (value > upper) {
348 throw new IllegalArgumentException(
349 String.format(
350 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
351 }
352
353 return value;
354 }
355
356 /**
Daichi Hirono2dd48252016-01-12 15:46:41 +0900357 * Ensures that the argument long value is within the inclusive range.
358 *
359 * @param value a long value
360 * @param lower the lower endpoint of the inclusive range
361 * @param upper the upper endpoint of the inclusive range
362 * @param valueName the name of the argument to use if the check fails
363 *
364 * @return the validated long value
365 *
366 * @throws IllegalArgumentException if {@code value} was not within the range
367 */
368 public static long checkArgumentInRange(long value, long lower, long upper,
369 String valueName) {
370 if (value < lower) {
371 throw new IllegalArgumentException(
372 String.format(
373 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
374 } else if (value > upper) {
375 throw new IllegalArgumentException(
376 String.format(
377 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
378 }
379
380 return value;
381 }
382
383 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700384 * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700385 *
386 * @param value an array of boxed objects
387 * @param valueName the name of the argument to use if the check fails
388 *
389 * @return the validated array
390 *
391 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
392 */
393 public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
394 if (value == null) {
395 throw new NullPointerException(valueName + " must not be null");
396 }
397
398 for (int i = 0; i < value.length; ++i) {
399 if (value[i] == null) {
400 throw new NullPointerException(
401 String.format("%s[%d] must not be null", valueName, i));
402 }
403 }
404
405 return value;
406 }
407
408 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700409 * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
410 * {@code null}.
411 *
412 * @param value a {@link Collection} of boxed objects
413 * @param valueName the name of the argument to use if the check fails
414 *
415 * @return the validated {@link Collection}
416 *
417 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
418 */
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -0800419 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
420 final C value, final String valueName) {
Ruben Brunk91838de2014-07-16 17:24:17 -0700421 if (value == null) {
422 throw new NullPointerException(valueName + " must not be null");
423 }
424
425 long ctr = 0;
426 for (T elem : value) {
427 if (elem == null) {
428 throw new NullPointerException(
429 String.format("%s[%d] must not be null", valueName, ctr));
430 }
431 ++ctr;
432 }
433
434 return value;
435 }
436
437 /**
438 * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
439 *
440 * @param value a {@link Collection} of boxed elements.
441 * @param valueName the name of the argument to use if the check fails.
442
443 * @return the validated {@link Collection}
444 *
445 * @throws NullPointerException if the {@code value} was {@code null}
446 * @throws IllegalArgumentException if the {@code value} was empty
447 */
448 public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
449 final String valueName) {
450 if (value == null) {
451 throw new NullPointerException(valueName + " must not be null");
452 }
453 if (value.isEmpty()) {
454 throw new IllegalArgumentException(valueName + " is empty");
455 }
456 return value;
457 }
458
459 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700460 * Ensures that all elements in the argument floating point array are within the inclusive range
461 *
462 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
463 * will always be out of range.</p>
464 *
465 * @param value a floating point array of values
466 * @param lower the lower endpoint of the inclusive range
467 * @param upper the upper endpoint of the inclusive range
468 * @param valueName the name of the argument to use if the check fails
469 *
470 * @return the validated floating point value
471 *
472 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
473 * @throws NullPointerException if the {@code value} was {@code null}
474 */
475 public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
476 String valueName) {
477 checkNotNull(value, valueName + " must not be null");
478
479 for (int i = 0; i < value.length; ++i) {
480 float v = value[i];
481
482 if (Float.isNaN(v)) {
483 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
484 } else if (v < lower) {
485 throw new IllegalArgumentException(
486 String.format("%s[%d] is out of range of [%f, %f] (too low)",
487 valueName, i, lower, upper));
488 } else if (v > upper) {
489 throw new IllegalArgumentException(
490 String.format("%s[%d] is out of range of [%f, %f] (too high)",
491 valueName, i, lower, upper));
492 }
493 }
494
495 return value;
496 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700497}