blob: 1ead5b3de1de3094058f1c5ada203c8ffd68514e [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 /**
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080052 * 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 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -070059 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -080060 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 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -070076 public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080077 final Object errorMessage) {
78 if (TextUtils.isEmpty(string)) {
79 throw new IllegalArgumentException(String.valueOf(errorMessage));
80 }
81 return string;
82 }
83
84 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070085 * 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 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080092 public static @NonNull <T> T checkNotNull(final T reference) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070093 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 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800109 public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700110 if (reference == null) {
111 throw new NullPointerException(String.valueOf(errorMessage));
112 }
113 return reference;
114 }
115
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700116 /**
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
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800121 * @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
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700135 * @throws IllegalStateException if {@code expression} is false
136 */
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700137 public static void checkState(final boolean expression) {
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800138 checkState(expression, null);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700139 }
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700140
141 /**
142 * Check the requested flags, throwing if any requested flags are outside
143 * the allowed set.
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700144 *
145 * @return the validated requested flags.
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700146 */
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700147 public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700148 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 }
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700153
154 return requestedFlags;
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700155 }
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700156
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 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800165 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
166 final String errorMessage) {
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700167 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 *
Philip P. Moltmann9dcb86a2016-03-14 14:31:12 -0700177 * @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 *
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700193 * @param value a numeric long value
Philip P. Moltmann4723f362016-03-30 13:48:38 -0700194 * @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
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700209 * @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 /**
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700293 * 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 /**
Daichi Hirono2dd48252016-01-12 15:46:41 +0900320 * 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 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700347 * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700348 *
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 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700372 * 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 */
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -0800382 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
383 final C value, final String valueName) {
Ruben Brunk91838de2014-07-16 17:24:17 -0700384 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 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700423 * 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 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700460}