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