Preconditions.java revision 2dd48256e9657b013dd6fa0ca86d1d7c7c730428
1/*
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
19import java.util.Collection;
20
21/**
22 * Simple static methods to be called at the start of your own methods to verify
23 * correct arguments and state.
24 */
25public class Preconditions {
26
27    public static void checkArgument(boolean expression) {
28        if (!expression) {
29            throw new IllegalArgumentException();
30        }
31    }
32
33    /**
34     * Ensures that an object reference passed as a parameter to the calling
35     * method is not null.
36     *
37     * @param reference an object reference
38     * @return the non-null reference that was validated
39     * @throws NullPointerException if {@code reference} is null
40     */
41    public static <T> T checkNotNull(final T reference) {
42        if (reference == null) {
43            throw new NullPointerException();
44        }
45        return reference;
46    }
47
48    /**
49     * Ensures that an object reference passed as a parameter to the calling
50     * method is not null.
51     *
52     * @param reference an object reference
53     * @param errorMessage the exception message to use if the check fails; will
54     *     be converted to a string using {@link String#valueOf(Object)}
55     * @return the non-null reference that was validated
56     * @throws NullPointerException if {@code reference} is null
57     */
58    public static <T> T checkNotNull(final T reference, final Object errorMessage) {
59        if (reference == null) {
60            throw new NullPointerException(String.valueOf(errorMessage));
61        }
62        return reference;
63    }
64
65    /**
66     * Ensures the truth of an expression involving the state of the calling
67     * instance, but not involving any parameters to the calling method.
68     *
69     * @param expression a boolean expression
70     * @throws IllegalStateException if {@code expression} is false
71     */
72    public static void checkState(final boolean expression) {
73        if (!expression) {
74            throw new IllegalStateException();
75        }
76    }
77
78    /**
79     * Check the requested flags, throwing if any requested flags are outside
80     * the allowed set.
81     */
82    public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
83        if ((requestedFlags & allowedFlags) != requestedFlags) {
84            throw new IllegalArgumentException("Requested flags 0x"
85                    + Integer.toHexString(requestedFlags) + ", but only 0x"
86                    + Integer.toHexString(allowedFlags) + " are allowed");
87        }
88    }
89
90    /**
91     * Ensures that that the argument numeric value is non-negative.
92     *
93     * @param value a numeric int value
94     * @param errorMessage the exception message to use if the check fails
95     * @return the validated numeric value
96     * @throws IllegalArgumentException if {@code value} was negative
97     */
98    public static int checkArgumentNonnegative(final int value, final String errorMessage) {
99        if (value < 0) {
100            throw new IllegalArgumentException(errorMessage);
101        }
102
103        return value;
104    }
105
106    /**
107     * Ensures that that the argument numeric value is non-negative.
108     *
109     * @param value a numeric long value
110     * @param errorMessage the exception message to use if the check fails
111     * @return the validated numeric value
112     * @throws IllegalArgumentException if {@code value} was negative
113     */
114    public static long checkArgumentNonnegative(final long value, final String errorMessage) {
115        if (value < 0) {
116            throw new IllegalArgumentException(errorMessage);
117        }
118
119        return value;
120    }
121
122    /**
123     * Ensures that that the argument numeric value is positive.
124     *
125     * @param value a numeric int value
126     * @param errorMessage the exception message to use if the check fails
127     * @return the validated numeric value
128     * @throws IllegalArgumentException if {@code value} was not positive
129     */
130    public static int checkArgumentPositive(final int value, final String errorMessage) {
131        if (value <= 0) {
132            throw new IllegalArgumentException(errorMessage);
133        }
134
135        return value;
136    }
137
138    /**
139     * Ensures that the argument floating point value is a finite number.
140     *
141     * <p>A finite number is defined to be both representable (that is, not NaN) and
142     * not infinite (that is neither positive or negative infinity).</p>
143     *
144     * @param value a floating point value
145     * @param valueName the name of the argument to use if the check fails
146     *
147     * @return the validated floating point value
148     *
149     * @throws IllegalArgumentException if {@code value} was not finite
150     */
151    public static float checkArgumentFinite(final float value, final String valueName) {
152        if (Float.isNaN(value)) {
153            throw new IllegalArgumentException(valueName + " must not be NaN");
154        } else if (Float.isInfinite(value)) {
155            throw new IllegalArgumentException(valueName + " must not be infinite");
156        }
157
158        return value;
159    }
160
161    /**
162     * Ensures that the argument floating point value is within the inclusive range.
163     *
164     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
165     * will always be out of range.</p>
166     *
167     * @param value a floating point value
168     * @param lower the lower endpoint of the inclusive range
169     * @param upper the upper endpoint of the inclusive range
170     * @param valueName the name of the argument to use if the check fails
171     *
172     * @return the validated floating point value
173     *
174     * @throws IllegalArgumentException if {@code value} was not within the range
175     */
176    public static float checkArgumentInRange(float value, float lower, float upper,
177            String valueName) {
178        if (Float.isNaN(value)) {
179            throw new IllegalArgumentException(valueName + " must not be NaN");
180        } else if (value < lower) {
181            throw new IllegalArgumentException(
182                    String.format(
183                            "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
184        } else if (value > upper) {
185            throw new IllegalArgumentException(
186                    String.format(
187                            "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
188        }
189
190        return value;
191    }
192
193    /**
194     * Ensures that the argument int value is within the inclusive range.
195     *
196     * @param value a int value
197     * @param lower the lower endpoint of the inclusive range
198     * @param upper the upper endpoint of the inclusive range
199     * @param valueName the name of the argument to use if the check fails
200     *
201     * @return the validated int value
202     *
203     * @throws IllegalArgumentException if {@code value} was not within the range
204     */
205    public static int checkArgumentInRange(int value, int lower, int upper,
206            String valueName) {
207        if (value < lower) {
208            throw new IllegalArgumentException(
209                    String.format(
210                            "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
211        } else if (value > upper) {
212            throw new IllegalArgumentException(
213                    String.format(
214                            "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
215        }
216
217        return value;
218    }
219
220    /**
221     * Ensures that the argument long value is within the inclusive range.
222     *
223     * @param value a long value
224     * @param lower the lower endpoint of the inclusive range
225     * @param upper the upper endpoint of the inclusive range
226     * @param valueName the name of the argument to use if the check fails
227     *
228     * @return the validated long value
229     *
230     * @throws IllegalArgumentException if {@code value} was not within the range
231     */
232    public static long checkArgumentInRange(long value, long lower, long upper,
233            String valueName) {
234        if (value < lower) {
235            throw new IllegalArgumentException(
236                    String.format(
237                            "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
238        } else if (value > upper) {
239            throw new IllegalArgumentException(
240                    String.format(
241                            "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
242        }
243
244        return value;
245    }
246
247    /**
248     * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
249     *
250     * @param value an array of boxed objects
251     * @param valueName the name of the argument to use if the check fails
252     *
253     * @return the validated array
254     *
255     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
256     */
257    public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
258        if (value == null) {
259            throw new NullPointerException(valueName + " must not be null");
260        }
261
262        for (int i = 0; i < value.length; ++i) {
263            if (value[i] == null) {
264                throw new NullPointerException(
265                        String.format("%s[%d] must not be null", valueName, i));
266            }
267        }
268
269        return value;
270    }
271
272    /**
273     * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
274     * {@code null}.
275     *
276     * @param value a {@link Collection} of boxed objects
277     * @param valueName the name of the argument to use if the check fails
278     *
279     * @return the validated {@link Collection}
280     *
281     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
282     */
283    public static <T> Collection<T> checkCollectionElementsNotNull(final Collection<T> value,
284            final String valueName) {
285        if (value == null) {
286            throw new NullPointerException(valueName + " must not be null");
287        }
288
289        long ctr = 0;
290        for (T elem : value) {
291            if (elem == null) {
292                throw new NullPointerException(
293                        String.format("%s[%d] must not be null", valueName, ctr));
294            }
295            ++ctr;
296        }
297
298        return value;
299    }
300
301    /**
302     * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
303     *
304     * @param value a {@link Collection} of boxed elements.
305     * @param valueName the name of the argument to use if the check fails.
306
307     * @return the validated {@link Collection}
308     *
309     * @throws NullPointerException if the {@code value} was {@code null}
310     * @throws IllegalArgumentException if the {@code value} was empty
311     */
312    public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
313            final String valueName) {
314        if (value == null) {
315            throw new NullPointerException(valueName + " must not be null");
316        }
317        if (value.isEmpty()) {
318            throw new IllegalArgumentException(valueName + " is empty");
319        }
320        return value;
321    }
322
323    /**
324     * Ensures that all elements in the argument floating point array are within the inclusive range
325     *
326     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
327     * will always be out of range.</p>
328     *
329     * @param value a floating point array of values
330     * @param lower the lower endpoint of the inclusive range
331     * @param upper the upper endpoint of the inclusive range
332     * @param valueName the name of the argument to use if the check fails
333     *
334     * @return the validated floating point value
335     *
336     * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
337     * @throws NullPointerException if the {@code value} was {@code null}
338     */
339    public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
340            String valueName) {
341        checkNotNull(value, valueName + " must not be null");
342
343        for (int i = 0; i < value.length; ++i) {
344            float v = value[i];
345
346            if (Float.isNaN(v)) {
347                throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
348            } else if (v < lower) {
349                throw new IllegalArgumentException(
350                        String.format("%s[%d] is out of range of [%f, %f] (too low)",
351                                valueName, i, lower, upper));
352            } else if (v > upper) {
353                throw new IllegalArgumentException(
354                        String.format("%s[%d] is out of range of [%f, %f] (too high)",
355                                valueName, i, lower, upper));
356            }
357        }
358
359        return value;
360    }
361}
362