001/**
002 * Copyright 2010-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.common.util.base;
017
018import static com.google.common.base.Preconditions.checkArgument;
019import static org.apache.commons.lang3.StringUtils.isNotBlank;
020import static org.apache.commons.lang3.StringUtils.isNotEmpty;
021
022import java.io.File;
023
024import com.google.common.base.Optional;
025import com.google.common.base.Preconditions;
026import com.google.common.collect.Iterables;
027
028/**
029 * Strongly mimic's Guava's {@code Preconditions} class with a sensible default error message for common situations
030 *
031 * <pre>
032 * {@code Guava:}
033 * checkArgument(StringUtils.isNotBlank(foo), &quot;'foo' cannot be blank&quot;);
034 * this.foo = foo;
035 * 
036 * {@code Kuali:}
037 * this.foo = checkNotBlank(foo, &quot;foo&quot;);
038 * </pre>
039 */
040public class Precondition {
041
042    private static final String NOT_NULL_MSG = "'%s' cannot be null";
043    private static final String EXISTS_MSG = "[%s] does not exist";
044    private static final String IS_DIR_MSG = "[%s] is not an existing directory";
045    private static final String IS_FILE_MSG = "[%s] is not an existing file";
046    private static final String NOT_BLANK_MSG = "'%s' cannot be blank";
047    private static final String NOT_EMPTY_MSG = "'%s' cannot be the empty string";
048    private static final String MIN_MSG = "%s not allowed. '%s' must be greater than or equal to %s";
049    private static final String MAX_MSG = "%s not allowed. '%s' must be less than or equal to %s";
050    private static final String EQUALS_MSG = "[%s] not allowed. '%s' must be equal to [%s]";
051    private static final String ARG_NAME = "argName";
052
053    /**
054     * Ensures that a File passed as an argument exists
055     *
056     * @param arg
057     *            a File passed as an argument
058     * @param argName
059     *            the name of the argument
060     *
061     * @return the non-null File that was validated
062     *
063     * @throws NullPointerException
064     *             If arg is null. The exception message contains the name of the argument that was null
065     * @throws IllegalArgumentException
066     *             If arg does not exist or argName is blank
067     */
068    public static File checkExists(File arg, String argName) {
069        checkNotBlank(argName, ARG_NAME);
070        checkNotNull(arg, argName);
071        checkArgument(arg.exists(), EXISTS_MSG, arg);
072        return arg;
073    }
074
075    /**
076     * Ensures that a File passed as an argument is an existing directory
077     *
078     * @param arg
079     *            a File passed as an argument
080     * @param argName
081     *            the name of the argument
082     *
083     * @return the non-null File that was validated
084     *
085     * @throws NullPointerException
086     *             If arg is null. The exception message contains the name of the argument that was null
087     * @throws IllegalArgumentException
088     *             If arg does not exist, is not a directory, or argName is blank
089     */
090    public static File checkIsDir(File arg, String argName) {
091        checkArgument(checkExists(arg, argName).isDirectory(), IS_DIR_MSG, arg);
092        return arg;
093    }
094
095    /**
096     * Ensures that a File passed as an argument is a normal file
097     *
098     * @param arg
099     *            a File passed as an argument
100     * @param argName
101     *            the name of the argument
102     *
103     * @return the non-null File that was validated
104     *
105     * @throws NullPointerException
106     *             If arg is null. The exception message contains the name of the argument that was null
107     * @throws IllegalArgumentException
108     *             If arg does not exist, is not a normal file, or argName is blank
109     */
110    public static File checkIsFile(File arg, String argName) {
111        checkArgument(checkExists(arg, argName).isFile(), IS_FILE_MSG, arg);
112        return arg;
113    }
114
115    /**
116     * Ensures that an object reference passed as an argument is not null
117     *
118     * @param arg
119     *            an object reference passed as an argument
120     * @param argName
121     *            the name of the argument
122     *
123     * @return the non-null object reference that was validated
124     *
125     * @throws NullPointerException
126     *             If arg is null. The exception message contains the name of the argument that was null
127     * @throws IllegalArgumentException
128     *             If argName is blank
129     */
130    public static <T> T checkNotNull(T arg, String argName) {
131        return Preconditions.checkNotNull(arg, NOT_NULL_MSG, checkNotBlank(argName, ARG_NAME));
132    }
133
134    /**
135     * Ensures that a String passed as an argument is not whitespace, empty ("") or null
136     *
137     * @param arg
138     *            a String passed as an argument
139     * @param argName
140     *            the name of the argument
141     *
142     * @return the non-blank String that was validated
143     *
144     * @throws IllegalArgumentException
145     *             If arg is blank. The exception message contains the name of the argument that was blank
146     * @throws IllegalArgumentException
147     *             If argName is blank
148     */
149    public static String checkNotBlank(String arg, String argName) {
150        checkArgument(isNotBlank(argName), NOT_BLANK_MSG, ARG_NAME);
151        checkArgument(isNotBlank(arg), NOT_BLANK_MSG, argName);
152        return arg;
153    }
154
155    /**
156     * Ensures that a String passed as an argument is the empty string ("") or null
157     *
158     * @param arg
159     *            a String passed as an argument
160     * @param argName
161     *            the name of the argument
162     *
163     * @return the non-blank String that was validated
164     *
165     * @throws IllegalArgumentException
166     *             If arg is blank. The exception message contains the name of the argument that was blank
167     * @throws IllegalArgumentException
168     *             If argName is blank
169     */
170    public static String checkNotEmpty(String arg, String argName) {
171        checkArgument(isNotBlank(argName), NOT_BLANK_MSG, ARG_NAME);
172        checkArgument(isNotEmpty(arg), NOT_EMPTY_MSG, argName);
173        return arg;
174    }
175
176    /**
177     * Ensures that an {@code Optional<String>} passed as an argument does not contain a string that is whitespace or empty ("").
178     *
179     * @param arg
180     *            an {@code Optional<String>} passed as an argument
181     * @param argName
182     *            the name of the argument
183     *
184     * @return the non-blank {@code Optional<String>} that was validated
185     *
186     * @throws IllegalArgumentException
187     *             If arg is blank. The exception message contains the name of the argument that was blank
188     * @throws IllegalArgumentException
189     *             If argName is blank
190     */
191    public static Optional<String> checkNotBlank(Optional<String> arg, String argName) {
192        if (arg.isPresent()) {
193            checkNotBlank(arg.get(), argName);
194        }
195        return arg;
196    }
197
198    /**
199     * Ensures that an {@code Optional<String>} passed as an argument is not the empty string ("").
200     *
201     * @param arg
202     *            an {@code Optional<String>} passed as an argument
203     * @param argName
204     *            the name of the argument
205     *
206     * @return the non-empty string {@code Optional<String>} that was validated
207     *
208     * @throws IllegalArgumentException
209     *             If arg is blank. The exception message contains the name of the argument that was blank
210     * @throws IllegalArgumentException
211     *             If argName is blank
212     */
213    public static Optional<String> checkNotEmpty(Optional<String> arg, String argName) {
214        if (arg.isPresent()) {
215            checkArgument(isNotEmpty(arg.get()), NOT_EMPTY_MSG, argName);
216        }
217        return arg;
218    }
219
220    /**
221     * If arg.isPresent(), check that the Integer it contains is greater than or equal to min
222     */
223    public static Optional<Integer> checkMin(Optional<Integer> arg, int min, String argName) {
224        if (arg.isPresent()) {
225            checkMin(arg.get(), min, argName);
226        }
227        return arg;
228    }
229
230    /**
231     * If arg.isPresent(), check that the Long it contains is greater than or equal to min
232     */
233    public static Optional<Long> checkMin(Optional<Long> arg, long min, String argName) {
234        if (arg.isPresent()) {
235            checkMin(arg.get(), min, argName);
236        }
237        return arg;
238    }
239
240    /**
241     * Check that arg is less than or equal to max
242     */
243    public static int checkMax(int arg, int max, String argName) {
244        checkNotBlank(argName, ARG_NAME);
245        checkArgument(arg <= max, MAX_MSG, arg, argName, max);
246        return arg;
247    }
248
249    /**
250     * Check that arg is less than or equal to max
251     */
252    public static long checkMax(long arg, long max, String argName) {
253        checkNotBlank(argName, ARG_NAME);
254        checkArgument(arg <= max, MAX_MSG, arg, argName, max);
255        return arg;
256    }
257
258    public static int checkRange(int arg, int min, int max, String argName) {
259        return checkMin(checkMax(arg, max, argName), min, argName);
260    }
261
262    /**
263     * Check that arg is greater than or equal to min.
264     */
265    public static int checkMin(int arg, int min, String argName) {
266        checkNotBlank(argName, ARG_NAME);
267        checkArgument(arg >= min, MIN_MSG, arg, argName, min);
268        return arg;
269    }
270
271    /**
272     * Check that arg is greater than or equal to min.
273     */
274    public static long checkMin(long arg, long min, String argName) {
275        checkNotBlank(argName, ARG_NAME);
276        checkArgument(arg >= min, MIN_MSG, arg, argName, min);
277        return arg;
278    }
279
280    public static <T> T checkEquals(T arg, T expected, String argName) {
281        checkNotNull(arg, checkNotBlank(argName, ARG_NAME));
282        checkNotNull(expected, "expected");
283        checkArgument(arg.equals(expected), EQUALS_MSG, argName, arg, expected);
284        return arg;
285    }
286
287    public static long checkEquals(long arg, long expected, String argName) {
288        checkNotBlank(argName, ARG_NAME);
289        checkArgument(arg == expected, EQUALS_MSG, argName, arg, expected);
290        return arg;
291    }
292
293    public static int checkEquals(int arg, int expected, String argName) {
294        checkNotBlank(argName, ARG_NAME);
295        checkArgument(arg == expected, EQUALS_MSG, argName, arg, expected);
296        return arg;
297    }
298
299    public static void checkTruths(int expected, boolean... expressions) {
300        checkMin(expected, 0, "expected");
301        checkArgument(expressions.length > 0, "must supply at least 1 expression");
302        int actual = 0;
303        for (boolean expression : expressions) {
304            actual = expression ? (actual + 1) : actual;
305        }
306        checkArgument(expected == actual, "expected %s of %s expression(s) to be true, but %s were true instead", expected, expressions.length, actual);
307    }
308
309    public static <I extends Iterable<T>, T> I checkSize(I iterable, int expected) {
310        int actual = Iterables.size(iterable);
311        checkArgument(expected == actual, "expected exactly %s element(s) but there were %s instead", expected, actual);
312        return iterable;
313    }
314
315}