blob: 53cb56ebecd9d612d61796ab34e2e187edd5acc0 [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. Moltmannc2ad2262016-01-13 09:17:15 -080038 * Ensures that an string reference passed as a parameter to the calling
39 * method is not empty.
40 *
41 * @param string an string reference
42 * @return the string reference that was validated
43 * @throws IllegalArgumentException if {@code string} is empty
44 */
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -080045 public static @NonNull String checkStringNotEmpty(final String string) {
46 if (TextUtils.isEmpty(string)) {
47 throw new IllegalArgumentException();
48 }
49 return string;
50 }
51
52 /**
53 * Ensures that an string reference passed as a parameter to the calling
54 * method is not empty.
55 *
56 * @param string an string reference
57 * @param errorMessage the exception message to use if the check fails; will
58 * be converted to a string using {@link String#valueOf(Object)}
59 * @return the string reference that was validated
60 * @throws IllegalArgumentException if {@code string} is empty
61 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080062 public static @NonNull String checkStringNotEmpty(final String string,
63 final Object errorMessage) {
64 if (TextUtils.isEmpty(string)) {
65 throw new IllegalArgumentException(String.valueOf(errorMessage));
66 }
67 return string;
68 }
69
70 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070071 * Ensures that an object reference passed as a parameter to the calling
72 * method is not null.
73 *
74 * @param reference an object reference
75 * @return the non-null reference that was validated
76 * @throws NullPointerException if {@code reference} is null
77 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080078 public static @NonNull <T> T checkNotNull(final T reference) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070079 if (reference == null) {
80 throw new NullPointerException();
81 }
82 return reference;
83 }
84
85 /**
86 * Ensures that an object reference passed as a parameter to the calling
87 * method is not null.
88 *
89 * @param reference an object reference
90 * @param errorMessage the exception message to use if the check fails; will
91 * be converted to a string using {@link String#valueOf(Object)}
92 * @return the non-null reference that was validated
93 * @throws NullPointerException if {@code reference} is null
94 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -080095 public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070096 if (reference == null) {
97 throw new NullPointerException(String.valueOf(errorMessage));
98 }
99 return reference;
100 }
101
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700102 /**
103 * Ensures the truth of an expression involving the state of the calling
104 * instance, but not involving any parameters to the calling method.
105 *
106 * @param expression a boolean expression
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800107 * @param message exception message
108 * @throws IllegalStateException if {@code expression} is false
109 */
110 public static void checkState(final boolean expression, String message) {
111 if (!expression) {
112 throw new IllegalStateException(message);
113 }
114 }
115
116 /**
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
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700121 * @throws IllegalStateException if {@code expression} is false
122 */
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700123 public static void checkState(final boolean expression) {
Makoto Onuki1a5ee772016-02-12 15:34:57 -0800124 checkState(expression, null);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700125 }
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700126
127 /**
128 * Check the requested flags, throwing if any requested flags are outside
129 * the allowed set.
130 */
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700131 public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
Jeff Sharkeyee2f7df2013-09-26 11:32:30 -0700132 if ((requestedFlags & allowedFlags) != requestedFlags) {
133 throw new IllegalArgumentException("Requested flags 0x"
134 + Integer.toHexString(requestedFlags) + ", but only 0x"
135 + Integer.toHexString(allowedFlags) + " are allowed");
136 }
137 }
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700138
139 /**
140 * Ensures that that the argument numeric value is non-negative.
141 *
142 * @param value a numeric int value
143 * @param errorMessage the exception message to use if the check fails
144 * @return the validated numeric value
145 * @throws IllegalArgumentException if {@code value} was negative
146 */
Philip P. Moltmannc2ad2262016-01-13 09:17:15 -0800147 public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
148 final String errorMessage) {
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700149 if (value < 0) {
150 throw new IllegalArgumentException(errorMessage);
151 }
152
153 return value;
154 }
155
156 /**
157 * Ensures that that the argument numeric value is non-negative.
158 *
159 * @param value a numeric long value
160 * @param errorMessage the exception message to use if the check fails
161 * @return the validated numeric value
162 * @throws IllegalArgumentException if {@code value} was negative
163 */
164 public static long checkArgumentNonnegative(final long value, final String errorMessage) {
165 if (value < 0) {
166 throw new IllegalArgumentException(errorMessage);
167 }
168
169 return value;
170 }
171
172 /**
173 * Ensures that that the argument numeric value is positive.
174 *
175 * @param value a numeric int value
176 * @param errorMessage the exception message to use if the check fails
177 * @return the validated numeric value
178 * @throws IllegalArgumentException if {@code value} was not positive
179 */
180 public static int checkArgumentPositive(final int value, final String errorMessage) {
181 if (value <= 0) {
182 throw new IllegalArgumentException(errorMessage);
183 }
184
185 return value;
186 }
187
188 /**
189 * Ensures that the argument floating point value is a finite number.
190 *
191 * <p>A finite number is defined to be both representable (that is, not NaN) and
192 * not infinite (that is neither positive or negative infinity).</p>
193 *
194 * @param value a floating point value
195 * @param valueName the name of the argument to use if the check fails
196 *
197 * @return the validated floating point value
198 *
199 * @throws IllegalArgumentException if {@code value} was not finite
200 */
201 public static float checkArgumentFinite(final float value, final String valueName) {
202 if (Float.isNaN(value)) {
203 throw new IllegalArgumentException(valueName + " must not be NaN");
204 } else if (Float.isInfinite(value)) {
205 throw new IllegalArgumentException(valueName + " must not be infinite");
206 }
207
208 return value;
209 }
210
211 /**
212 * Ensures that the argument floating point value is within the inclusive range.
213 *
214 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
215 * will always be out of range.</p>
216 *
217 * @param value a floating point value
218 * @param lower the lower endpoint of the inclusive range
219 * @param upper the upper endpoint of the inclusive range
220 * @param valueName the name of the argument to use if the check fails
221 *
222 * @return the validated floating point value
223 *
224 * @throws IllegalArgumentException if {@code value} was not within the range
225 */
226 public static float checkArgumentInRange(float value, float lower, float upper,
227 String valueName) {
228 if (Float.isNaN(value)) {
229 throw new IllegalArgumentException(valueName + " must not be NaN");
230 } else if (value < lower) {
231 throw new IllegalArgumentException(
232 String.format(
233 "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
234 } else if (value > upper) {
235 throw new IllegalArgumentException(
236 String.format(
237 "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
238 }
239
240 return value;
241 }
242
243 /**
Yin-Chia Yeh97f1c852014-05-28 16:36:05 -0700244 * Ensures that the argument int value is within the inclusive range.
245 *
246 * @param value a int value
247 * @param lower the lower endpoint of the inclusive range
248 * @param upper the upper endpoint of the inclusive range
249 * @param valueName the name of the argument to use if the check fails
250 *
251 * @return the validated int value
252 *
253 * @throws IllegalArgumentException if {@code value} was not within the range
254 */
255 public static int checkArgumentInRange(int value, int lower, int upper,
256 String valueName) {
257 if (value < lower) {
258 throw new IllegalArgumentException(
259 String.format(
260 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
261 } else if (value > upper) {
262 throw new IllegalArgumentException(
263 String.format(
264 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
265 }
266
267 return value;
268 }
269
270 /**
Daichi Hirono2dd48252016-01-12 15:46:41 +0900271 * Ensures that the argument long value is within the inclusive range.
272 *
273 * @param value a long value
274 * @param lower the lower endpoint of the inclusive range
275 * @param upper the upper endpoint of the inclusive range
276 * @param valueName the name of the argument to use if the check fails
277 *
278 * @return the validated long value
279 *
280 * @throws IllegalArgumentException if {@code value} was not within the range
281 */
282 public static long checkArgumentInRange(long value, long lower, long upper,
283 String valueName) {
284 if (value < lower) {
285 throw new IllegalArgumentException(
286 String.format(
287 "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
288 } else if (value > upper) {
289 throw new IllegalArgumentException(
290 String.format(
291 "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
292 }
293
294 return value;
295 }
296
297 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700298 * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700299 *
300 * @param value an array of boxed objects
301 * @param valueName the name of the argument to use if the check fails
302 *
303 * @return the validated array
304 *
305 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
306 */
307 public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
308 if (value == null) {
309 throw new NullPointerException(valueName + " must not be null");
310 }
311
312 for (int i = 0; i < value.length; ++i) {
313 if (value[i] == null) {
314 throw new NullPointerException(
315 String.format("%s[%d] must not be null", valueName, i));
316 }
317 }
318
319 return value;
320 }
321
322 /**
Ruben Brunk91838de2014-07-16 17:24:17 -0700323 * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
324 * {@code null}.
325 *
326 * @param value a {@link Collection} of boxed objects
327 * @param valueName the name of the argument to use if the check fails
328 *
329 * @return the validated {@link Collection}
330 *
331 * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
332 */
Philip P. Moltmann76d7e3e2016-01-15 13:22:13 -0800333 public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
334 final C value, final String valueName) {
Ruben Brunk91838de2014-07-16 17:24:17 -0700335 if (value == null) {
336 throw new NullPointerException(valueName + " must not be null");
337 }
338
339 long ctr = 0;
340 for (T elem : value) {
341 if (elem == null) {
342 throw new NullPointerException(
343 String.format("%s[%d] must not be null", valueName, ctr));
344 }
345 ++ctr;
346 }
347
348 return value;
349 }
350
351 /**
352 * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
353 *
354 * @param value a {@link Collection} of boxed elements.
355 * @param valueName the name of the argument to use if the check fails.
356
357 * @return the validated {@link Collection}
358 *
359 * @throws NullPointerException if the {@code value} was {@code null}
360 * @throws IllegalArgumentException if the {@code value} was empty
361 */
362 public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
363 final String valueName) {
364 if (value == null) {
365 throw new NullPointerException(valueName + " must not be null");
366 }
367 if (value.isEmpty()) {
368 throw new IllegalArgumentException(valueName + " is empty");
369 }
370 return value;
371 }
372
373 /**
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700374 * Ensures that all elements in the argument floating point array are within the inclusive range
375 *
376 * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
377 * will always be out of range.</p>
378 *
379 * @param value a floating point array of values
380 * @param lower the lower endpoint of the inclusive range
381 * @param upper the upper endpoint of the inclusive range
382 * @param valueName the name of the argument to use if the check fails
383 *
384 * @return the validated floating point value
385 *
386 * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
387 * @throws NullPointerException if the {@code value} was {@code null}
388 */
389 public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
390 String valueName) {
391 checkNotNull(value, valueName + " must not be null");
392
393 for (int i = 0; i < value.length; ++i) {
394 float v = value[i];
395
396 if (Float.isNaN(v)) {
397 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
398 } else if (v < lower) {
399 throw new IllegalArgumentException(
400 String.format("%s[%d] is out of range of [%f, %f] (too low)",
401 valueName, i, lower, upper));
402 } else if (v > upper) {
403 throw new IllegalArgumentException(
404 String.format("%s[%d] is out of range of [%f, %f] (too high)",
405 valueName, i, lower, upper));
406 }
407 }
408
409 return value;
410 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700411}