001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2015-2016 ForgeRock AS.
015 */
016package org.forgerock.util;
017
018/**
019 * A input parameter-validating utility class using fluent invocation:
020 *
021 * <pre>
022 * public int divide(int dividend, int divisor) {
023 *     Reject.ifTrue(divisor == 0, &quot;Division by zero not supported&quot;);
024 *     return dividend / divisor;
025 * }
026 * </pre>
027 *
028 * The example above will cause an {@code IllegalArgumentException} to be thrown
029 * with the message given.
030 * <p>
031 * Another use case is validating constructor parameters:
032 *
033 * <pre>
034 * public TokenManager(final TokenFactory factory) {
035 *     Reject.ifNull(factory, &quot;Cannot instantiate TokenManager with null TokenFactory&quot;);
036 * }
037 * </pre>
038 *
039 * Sometimes, constructor parameters are passed to ancestor constructors which
040 * must be called first--thus, the {@code checkNotNull} syntax is available:
041 *
042 * <pre>
043 *     import static org.forgerock.util.Reject.checkNotNull;
044 *
045 *     public TokenManager(final TokenFactory factory) {
046 *         super(checkNotNull(factory));
047 *     }
048 * </pre>
049 *
050 * Note that the methods herein throw generic RuntimeExceptions as opposed to
051 * custom, application-specific error Exceptions. This class is intended for
052 * wide use among multiple projects whose Exception frameworks may differ. The
053 * implementer is encouraged to catch the generic exceptions thrown by this
054 * class and rethrow exceptions appropriate to the target application.
055 */
056public final class Reject {
057
058    /**
059     * Throws a {@code NullPointerException} if the <tt>object</tt> parameter is
060     * null, returns the object otherwise.
061     *
062     * @param <T>
063     *            The type of object to test.
064     * @param object
065     *            the object to test
066     * @return the object
067     * @throws NullPointerException
068     *             if {@code object} is null
069     */
070    public static <T> T checkNotNull(final T object) {
071        return checkNotNull(object, null);
072    }
073
074    /**
075     * Throws a {@code NullPointerException} if the <tt>object</tt> parameter is
076     * null, returns the object otherwise.
077     *
078     * @param <T>
079     *            The type of object to test.
080     * @param object
081     *            the object to test
082     * @param message
083     *            a custom exception message to use
084     * @return the object
085     * @throws NullPointerException
086     *             if {@code object} is null
087     */
088    public static <T> T checkNotNull(final T object, final String message) {
089        if (object == null) {
090            throw new NullPointerException(message);
091        }
092        return object;
093    }
094
095    /**
096     * Throws an {@code IllegalArgumentException} if the <tt>condition</tt>
097     * parameter is false.
098     *
099     * @param condition
100     *            the condition to test
101     * @throws IllegalArgumentException
102     *             if {@code condition} is false
103     */
104    public static void ifFalse(final boolean condition) {
105        ifFalse(condition, "Expected condition was true, found false");
106    }
107
108    /**
109     * Throws an {@code IllegalArgumentException} with a custom {@code message}
110     * if the <tt>condition</tt> parameter is false.
111     *
112     * @param condition
113     *            the condition to test
114     * @param message
115     *            a custom exception message to use
116     * @throws IllegalArgumentException
117     *             if {@code condition} is false
118     */
119    public static void ifFalse(final boolean condition, final String message) {
120        if (!condition) {
121            throw new IllegalArgumentException(message);
122        }
123    }
124
125    /**
126     * Alias for {@code checkNotNull} to be used in fluent {@code Reject.ifNull}
127     * syntax. Throws a {@code NullPointerException} if the <tt>object</tt>
128     * parameter is null.
129     *
130     * @param object
131     *            the object to test
132     * @throws NullPointerException
133     *             if {@code object} is null
134     */
135    public static void ifNull(final Object object) {
136        ifNull(object, null);
137    }
138
139    /**
140     * Throws a {@code NullPointerException} if any of the provided arguments
141     * are {@code null}.
142     *
143     * @param <T>
144     *            The type of object to test.
145     * @param objects
146     *            The objects to test.
147     * @throws NullPointerException
148     *             If any of the provided arguments are {@code null}.
149     */
150    @SafeVarargs
151    public static <T> void ifNull(final T... objects) {
152        /*
153         * This method is generic in order to play better with varargs.
154         * Otherwise invoking this method with an array of Strings will be
155         * flagged with a warning because of the potential ambiguity. See
156         * org.forgerock.util.RejectTest.ifNullVarArgsStrings().
157         */
158        for (final Object o : objects) {
159            if (o == null) {
160                throw new NullPointerException();
161            }
162        }
163    }
164
165    /**
166     * Alias for {@code checkNotNull} to be used in fluent {@code Reject.ifNull}
167     * syntax. Throws a {@code NullPointerException} if the <tt>object</tt>
168     * parameter is null.
169     *
170     * @param object
171     *            the object to test
172     * @param message
173     *            a custom exception message to use
174     * @throws NullPointerException
175     *             if {@code object} is null
176     */
177    public static void ifNull(final Object object, final String message) {
178        checkNotNull(object, message);
179    }
180
181    /**
182     * Throws an {@code IllegalArgumentException} if the <tt>condition</tt>
183     * parameter is true.
184     *
185     * @param condition
186     *            the condition to test
187     * @throws IllegalArgumentException
188     *             if {@code condition} is true
189     */
190    public static void ifTrue(final boolean condition) {
191        ifTrue(condition, "Expected condition was false, found true");
192    }
193
194    /**
195     * Throws an {@code IllegalArgumentException} with a custom {@code message}
196     * if the <tt>condition</tt> parameter is true.
197     *
198     * @param condition
199     *            the condition to test
200     * @param message
201     *            a custom exception message to use
202     * @throws IllegalArgumentException
203     *             if {@code condition} is true
204     */
205    public static void ifTrue(final boolean condition, final String message) {
206        if (condition) {
207            throw new IllegalArgumentException(message);
208        }
209    }
210
211    /**
212     * Throws an {@code IllegalStateException} with a custom {@code message}
213     * if the <tt>condition</tt> parameter is true.
214     *
215     * @param condition
216     *            the condition to test
217     * @param message
218     *            a custom exception message to use
219     * @throws IllegalStateException
220     *             if {@code condition} is true
221     */
222    public static void rejectStateIfTrue(final boolean condition, final String message) {
223        if (condition) {
224            throw new IllegalStateException(message);
225        }
226    }
227
228    // Prevent instantiation
229    private Reject() {
230        // nothing to do
231    }
232
233}