1 /* 2 * Copyright 2006-2008 The Kuali Foundation 3 * 4 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php 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 package org.kuali.rice.kns.util; 17 18 /** 19 * This class contains utility methods for making assertions in production code (not test code). 20 * Kuali is not using the {@code assert} keyword because those assertions 21 * are not enabled by default. We can use the methods of this class instead, or throw {@link AssertionError} directly. This makes 22 * assertions effective in production and development, and avoids any risk of changes to functionality because any side-effects that 23 * might be involved in the assertion are done consistently. Although {@code AssertionError} can be thrown directly, and sometimes 24 * the compiler requires this, in many cases these method invocations will be easier to read than the extra {@code if} block with 25 * its negated conditional. 26 * 27 * <p/> These assertions are for use in production code. They should not be confused with 28 * {@link junit.framework.Assert}, {@link junit.framework.AssertionFailedError}, nor {@link org.kuali.test.util.KualiTestAssertionUtils}, 29 * which are for test code. 30 * 31 * <p/> These methods 32 * should be used such that when they fail and throw {@code AssertionError}, it indicates that there is a bug in our software. 33 * Drawing attention to the bug this way, as soon as it's discovered, reduces the amount of work required to fix it. So, we should 34 * not catch {@code AssertionError} (or {@link Throwable}) and try to handle or work around it; it indicates a need to change some 35 * source code so that the assertion is never false. For more about why, when, and how to use assertions, see <a 36 * href="https://test.kuali.org/confluence/display/KULDEV/Assert+Keyword+And+AssertionError">Kuali's guide to assertions</a> and <a 37 * href="http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html">Sun's guide to assertions</a>. 38 * 39 * @see org.kuali.test.util.KualiTestAssertionUtils 40 */ 41 public class AssertionUtils { 42 43 /** 44 * Asserts that the {@code isTrue} parameter is true. If this assertion fails, the {@code AssertionError} it throws will have no 45 * detail message, only a stacktrace indicating the source file and line number containing the assertion that failed. <p/> This 46 * method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production code), and its 47 * signature is intended to resemble that of the {@code assert} keyword. 48 * 49 * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.) 50 * 51 * @throws AssertionError if {@code isTrue} is false 52 */ 53 public static void assertThat(boolean isTrue) { 54 if (!isTrue) { 55 throw new AssertionError(); 56 } 57 } 58 59 /** 60 * Asserts that the {@code isTrue} parameter is true, with a detail message. The purpose of the detail message is to capture and 61 * communicate details about the assertion failure that will help a developer diagnose and fix the bug that led this assertion 62 * to fail. It's meant to be interpreted in the context of a full stack trace and with the source code containing the failed 63 * assertion. It is <em>not</em> a user-level error message. Details like {@code "assertion failed"} are redundant, not 64 * useful. <p/> This method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production 65 * code), and its signature is intended to resemble that of the {@code assert} keyword. 66 * 67 * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.) 68 * 69 * @param detailMessage value to use for the {@code AssertionError}'s detail message. If this is an instance of 70 * {@link Throwable}, then it also becomes the {@code AssertionError}'s cause. (Primitives are auto-boxed by JDK 1.5.) 71 * Objects are converted {@link Object#toString toString}, but only if this assertion fails, so it's better not to 72 * convert this detail in advance. The code will be a little easier to read, and there will be some performance 73 * improvement (altho it may be insignificant). For example, passing just {@code accountingLine} is better than passing 74 * {@code accountingLine.toString()} or {@code "accounting line:"+accountingLine}. Since the assertion has failed, any 75 * inconsistent side-effects from the conversion are not an issue. A {@code null} reference is treated as the String 76 * {@code "null"}. 77 * 78 * @throws AssertionError if {@code isTrue} is false 79 */ 80 public static void assertThat(boolean isTrue, Object detailMessage) { 81 if (!isTrue) { 82 throw new AssertionError(detailMessage); 83 } 84 } 85 86 /** 87 * Asserts that the {@code isTrue} parameter is true. This method is convenient for formatting the detail message, and as an 88 * optimization for detail arguments that are expensive to convert to String. For example, suppose {@code foo} and {@code bar} 89 * are two objects with expensive {@link Object#toString} methods. If you use 90 * 91 * <pre> 92 * AssertionUtils.assertThat(foo.equals(bar), "foo: " + foo + " bar: " + bar); 93 * </pre> 94 * 95 * then both object's {@code toString} methods will be invoked every time this assertion is done, even though those details are 96 * not normally needed because this assertion normally succeeds. You can use this method instead to only do those 97 * {@code toString} invocations if this assertion fails: 98 * 99 * <pre> 100 * AssertionUtils.assertThat(foo.equals(bar), "foo: %s bar: %s", foo, bar); 101 * </pre> 102 * 103 * <p/> This method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production code). 104 * 105 * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.) 106 * 107 * @param detailMessageFormat a {@linkplain String#format format string} to be used in constructing the {@code AssertionError}'s 108 * detail message. The purpose of this message is to capture and communicate details about the assertion failure that 109 * will help a developer diagnose and fix the bug that led the assertion to fail. It's meant to be interpreted in the 110 * context of a full stack trace and with the source code containing the failed assertion. It is <em>not</em> a 111 * user-level error message. Details like {@code "assertion failed"} are redundant, not useful. This detail message 112 * cannot be {@code null}. 113 * 114 * @param detailMessageArgs one or more arguments to the format string. Nulls are allowed by some format conversions, such as 115 * {@code "%s"}. (Primitives are auto-boxed by JDK 1.5.) Zero arguments will invoke {@link #assertThat(boolean, Object)} 116 * instead, so the detail message will not be treated as a format string. 117 * 118 * @throws AssertionError if {@code isTrue} is false 119 * 120 * @throws java.util.IllegalFormatException if {@code detailMessageFormat} contains an illegal syntax, a format specifier that 121 * is incompatible with the given arguments, insufficient arguments given the format string, or other illegal 122 * conditions. For specification of all possible formatting errors, see the Details section of 123 * {@link java.util.Formatter}. 124 * 125 * @throws NullPointerException if the {@code detailMessageFormat} is {@code null} 126 * 127 * @see String#format 128 */ 129 public static void assertThat(boolean isTrue, String detailMessageFormat, Object... detailMessageArgs) { 130 if (!isTrue) { 131 throw new AssertionError(String.format(detailMessageFormat, detailMessageArgs)); 132 } 133 } 134 }