001    /*
002     * Created on May 21, 2007
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2007-2011 the original author or authors.
015     */
016    package org.fest.assertions;
017    
018    import static org.fest.assertions.ErrorMessages.*;
019    import static org.fest.assertions.Fail.*;
020    import static org.fest.assertions.Formatting.format;
021    import static org.fest.util.Collections.list;
022    import static org.fest.util.Objects.areEqual;
023    
024    import java.util.Collection;
025    
026    /**
027     * Template for assertions.
028     * @param <S> used to simulate "self types." For more information please read &quot;<a
029     * href="http://passion.forco.de/content/emulating-self-types-using-java-generics-simplify-fluent-api-implementation"
030     * target="_blank">Emulating 'self types' using Java Generics to simplify fluent API implementation</a>.&quot;
031     * @param <A> the type the "actual" value.
032     *
033     * @author Yvonne Wang
034     * @author Alex Ruiz
035     */
036    public abstract class GenericAssert<S, A> extends Assert {
037    
038      protected final A actual;
039      protected final S myself;
040    
041      /**
042       * Creates a new <code>{@link GenericAssert}</code>.
043       * @param selfType the "self type."
044       * @param actual the actual value to verify.
045       */
046      protected GenericAssert(Class<S> selfType, A actual) {
047        this.actual = actual;
048        myself = selfType.cast(this);
049      }
050    
051      /**
052       * Asserts that the actual value (specified in the constructor of this class) is {@code null}.
053       * @throws AssertionError if the actual value is not {@code null}.
054       */
055      public final void isNull() {
056        failIfNotNull(customErrorMessage(), rawDescription(), actual);
057      }
058    
059      /**
060       * Verifies that the actual value satisfies the given condition.
061       * @param condition the given condition.
062       * @return this assertion object.
063       * @throws NullPointerException if the given condition is {@code null}.
064       * @throws AssertionError if the actual value does not satisfy the given condition.
065       * @see #is(Condition)
066       */
067      public final S satisfies(Condition<A> condition) {
068        if (matches(condition)) return myself;
069        failIfCustomMessageIsSet();
070        throw failure(errorMessageIfConditionNotSatisfied(condition));
071      }
072    
073      private String errorMessageIfConditionNotSatisfied(Condition<A> condition) {
074        return condition.addDescriptionTo(format("actual value:<%s> should satisfy condition", actual));
075      }
076    
077      /**
078       * Verifies that the actual value does not satisfy the given condition.
079       * @param condition the given condition.
080       * @return this assertion object.
081       * @throws NullPointerException if the given condition is {@code null}.
082       * @throws AssertionError if the actual value satisfies the given condition.
083       * @see #isNot(Condition)
084       */
085      public final S doesNotSatisfy(Condition<A> condition) {
086        if (!matches(condition)) return myself;
087        failIfCustomMessageIsSet();
088        throw failure(errorMessageIfConditionSatisfied(condition));
089      }
090    
091      private String errorMessageIfConditionSatisfied(Condition<A> condition) {
092        return condition.addDescriptionTo(format("actual value:<%s> should not satisfy condition", actual));
093      }
094    
095      /**
096       * Alias for <code>{@link #satisfies(Condition)}</code>.
097       * @param condition the given condition.
098       * @return this assertion object.
099       * @throws NullPointerException if the given condition is {@code null}.
100       * @throws AssertionError if the actual value does not satisfy the given condition.
101       * @since 1.2
102       */
103      public final S is(Condition<A> condition) {
104        if (matches(condition)) return myself;
105        failIfCustomMessageIsSet();
106        throw failure(errorMessageIfIsNot(condition));
107      }
108    
109      private String errorMessageIfIsNot(Condition<A> condition) {
110        return condition.addDescriptionTo(format("actual value:<%s> should be", actual));
111      }
112    
113      /**
114       * Alias for <code>{@link #doesNotSatisfy(Condition)}</code>.
115       * @param condition the given condition.
116       * @return this assertion object.
117       * @throws NullPointerException if the given condition is {@code null}.
118       * @throws AssertionError if the actual value satisfies the given condition.
119       * @since 1.2
120       */
121      public final S isNot(Condition<A> condition) {
122        if (!matches(condition)) return myself;
123        failIfCustomMessageIsSet();
124        throw failure(errorMessageIfIs(condition));
125      }
126    
127      private boolean matches(Condition<A> condition) {
128        validateIsNotNull(condition);
129        return condition.matches(actual);
130      }
131    
132      private void validateIsNotNull(Condition<A> condition) {
133        if (condition == null) throw new NullPointerException("Condition to check should not be null");
134      }
135    
136      private String errorMessageIfIs(Condition<A> condition) {
137        return condition.addDescriptionTo(format("actual value:<%s> should not be", actual));
138      }
139    
140      /**
141       * Sets the description of the actual value, to be used in as message of any <code>{@link AssertionError}</code>
142       * thrown when an assertion fails. This method should be called before any assertion method, otherwise any assertion
143       * failure will not show the provided description.
144       * <p>
145       * For example:
146       * <pre>
147       * assertThat(val).<strong>as</strong>(&quot;name&quot;).isEqualTo(&quot;Frodo&quot;);
148       * </pre>
149       * </p>
150       * @param description the description of the actual value.
151       * @return this assertion object.
152       */
153      public S as(String description) {
154        description(description);
155        return myself;
156      }
157    
158      /**
159       * Alias for <code>{@link #as(String)}</code>, since "as" is a keyword in
160       * <a href="http://groovy.codehaus.org/" target="_blank">Groovy</a>. This method should be called before any assertion
161       * method, otherwise any assertion failure will not show the provided description.
162       * <p>
163       * For example:
164       * <pre>
165       * assertThat(val).<strong>describedAs</strong>(&quot;name&quot;).isEqualTo(&quot;Frodo&quot;);
166       * </pre>
167       * </p>
168       * @param description the description of the actual value.
169       * @return this assertion object.
170       */
171      public S describedAs(String description) {
172        return as(description);
173      }
174    
175      /**
176       * Sets the description of the actual value, to be used in as message of any <code>{@link AssertionError}</code>
177       * thrown when an assertion fails. This method should be called before any assertion method, otherwise any assertion
178       * failure will not show the provided description.
179       * <p>
180       * For example:
181       * <pre>
182       * assertThat(val).<strong>as</strong>(new BasicDescription(&quot;name&quot;)).isEqualTo(&quot;Frodo&quot;);
183       * </pre>
184       * </p>
185       * @param description the description of the actual value.
186       * @return this assertion object.
187       */
188      public S as(Description description) {
189        description(description);
190        return myself;
191      }
192    
193      /**
194       * Alias for <code>{@link #as(Description)}</code>, since "as" is a keyword in
195       * <a href="http://groovy.codehaus.org/" target="_blank">Groovy</a>. This method should be called before any assertion
196       * method, otherwise any assertion failure will not show the provided description.
197       * <p>
198       * For example:
199       * <pre>
200       * assertThat(val).<strong>describedAs</strong>(new BasicDescription(&quot;name&quot;)).isEqualTo(&quot;Frodo&quot;);
201       * </pre>
202       * </p>
203       * @param description the description of the actual value.
204       * @return this assertion object.
205       */
206      public S describedAs(Description description) {
207        return as(description);
208      }
209    
210      /**
211       * Verifies that the actual value is equal to the given one.
212       * @param expected the given value to compare the actual value to.
213       * @return this assertion object.
214       * @throws AssertionError if the actual value is not equal to the given one.
215       */
216      public S isEqualTo(A expected) {
217        failIfNotEqual(customErrorMessage(), rawDescription(), actual, expected);
218        return myself;
219      }
220    
221      /**
222       * Verifies that the actual value is not equal to the given one.
223       * @param other the given value to compare the actual value to.
224       * @return this assertion object.
225       * @throws AssertionError if the actual value is equal to the given one.
226       */
227      public S isNotEqualTo(A other) {
228        failIfEqual(customErrorMessage(), rawDescription(), actual, other);
229        return myself;
230      }
231    
232      /**
233       * Verifies that the actual value is not {@code null}.
234       * @return this assertion object.
235       * @throws AssertionError if the actual value is {@code null}.
236       */
237      public final S isNotNull() {
238        failIfActualIsNull(customErrorMessage(), rawDescription(), actual);
239        return myself;
240      }
241    
242      /**
243       * Verifies that the actual value is the same as the given one.
244       * @param expected the given value to compare the actual value to.
245       * @return this assertion object.
246       * @throws AssertionError if the actual value is not the same as the given one.
247       */
248      public final S isSameAs(A expected) {
249        failIfNotSame(customErrorMessage(), rawDescription(), actual, expected);
250        return myself;
251      }
252    
253      /**
254       * Verifies that the actual value is not the same as the given one.
255       * @param other the given value to compare the actual value to.
256       * @return this assertion object.
257       * @throws AssertionError if the actual value is the same as the given one.
258       */
259      public final S isNotSameAs(A other) {
260        failIfSame(customErrorMessage(), rawDescription(), actual, other);
261        return myself;
262      }
263    
264      /**
265       * Verifies that the actual value is in the given values.
266       * @param values the given values to search the actual value in.
267       * @return this assertion object.
268       * @throws AssertionError if the actual value is not in the given values.
269       * @throws NullPointerException if the given parameter is null.
270       */
271      public final S isIn(Object... values) {
272        return isIn(list(values));
273      }
274    
275      /**
276       * Verifies that the actual value is in the given collection.
277       * @param values the given collection to search the actual value in. must not be null.
278       * @return this assertion object.
279       * @throws AssertionError if the actual value is not in the given collection.
280       * @throws NullPointerException if the given collection is null.
281       */
282      public final S isIn(Collection<?> values) {
283        if (values == null) throw new NullPointerException(formattedErrorMessage("expecting values parameter not to be null"));
284        if (isActualIn(values)) return myself;
285        failIfCustomMessageIsSet();
286        throw failure(unexpectedNotIn(customErrorMessage(), actual, values));
287      }
288    
289      /**
290       * Verifies that the actual value is in the given values.
291       * @param values the given values to search the actual value in.
292       * @return this assertion object.
293       * @throws AssertionError if the actual value is not in the given values.
294       * @throws NullPointerException if the given parameter is null.
295       */
296      public final S isNotIn(Object... values) {
297        return isNotIn(list(values));
298      }
299    
300      /**
301       * Verifies that the actual value is in the given collection.
302       * @param values the given collection to search the actual value in. must not be null.
303       * @return this assertion object.
304       * @throws AssertionError if the actual value is not in the given collection.
305       * @throws NullPointerException if the given collection is null.
306       */
307      public final S isNotIn(Collection<?> values) {
308        if (values == null) throw new NullPointerException(formattedErrorMessage("expecting values parameter not to be null"));
309        if (!isActualIn(values)) return myself;
310        failIfCustomMessageIsSet();
311        throw failure(unexpectedIn(customErrorMessage(), actual, values));
312      }
313    
314      private boolean isActualIn(Collection<?> values) {
315        if (values.isEmpty()) return false;
316        for (Object value : values)
317          if (areEqual(actual, value)) return true;
318        return false;
319      }
320    
321      /**
322       * Replaces the default message displayed in case of a failure with the given one.
323       * <p>
324       * For example, the following assertion:
325       * <pre>
326       * assertThat("Hello").isEqualTo("Bye");
327       * </pre>
328       * will fail with the default message "<em>expected:<'[Bye]'> but was:<'[Hello]'></em>."
329       * </p>
330       * <p>
331       * We can replace this message with our own:
332       * <pre>
333       * assertThat("Hello").overridingErrorMessage("'Hello' should be equal to 'Bye'").isEqualTo("Bye");
334       * </pre>
335       * in this case, the assertion will fail showing the message "<em>'Hello' should be equal to 'Bye'</em>".
336       * </p>
337       * @param message the given error message, which will replace the default one.
338       * @return this assertion.
339       * @since 1.2
340       */
341      public S overridingErrorMessage(String message) {
342        replaceDefaultErrorMessagesWith(message);
343        return myself;
344      }
345    }