001    /*
002     * Created on Dec 27, 2006
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 @2006-2009 the original author or authors.
015     */
016    package org.fest.assertions;
017    
018    import static org.fest.assertions.Collections.found;
019    import static org.fest.assertions.Collections.notFound;
020    import static org.fest.assertions.Formatting.inBrackets;
021    import static org.fest.util.Collections.duplicatesFrom;
022    import static org.fest.util.Strings.concat;
023    
024    import java.util.*;
025    
026    import org.fest.util.Collections;
027    
028    /**
029     * Understands assertions for collections. To create a new instance of this class use the
030     * method <code>{@link Assertions#assertThat(Collection)}</code>.
031     *
032     * @author Yvonne Wang
033     * @author Alex Ruiz
034     */
035    public class CollectionAssert extends GroupAssert<Collection<?>> {
036    
037      /**
038       * Creates a new </code>{@link CollectionAssert}</code>.
039       * @param actual the target to verify.
040       */
041      protected CollectionAssert(Collection<?> actual) {
042        super(actual);
043      }
044    
045      /**
046       * Verifies that the actual collection contains the given objects.
047       * @param objects the objects to look for.
048       * @return this assertion object.
049       * @throws AssertionError if the actual collection is <code>null</code>.
050       * @throws NullPointerException if the given array is <code>null</code>.
051       * @throws AssertionError if the actual collection does not contain the given objects.
052       */
053      public CollectionAssert contains(Object...objects) {
054        isNotNull();
055        validateIsNotNull(objects);
056        Collection<Object> notFound = notFoundInActual(objects);
057        if (notFound.isEmpty()) return this;
058        throw failureIfExpectedElementsNotFound(notFound);
059      }
060    
061      private Collection<Object> notFoundInActual(Object... objects) {
062        return notFound(actual, objects);
063      }
064    
065      /**
066       * Verifies that the actual collection contains the given objects <strong>only</strong>.
067       * @param objects the objects to look for.
068       * @return this assertion object.
069       * @throws AssertionError if the actual collection is <code>null</code>.
070       * @throws NullPointerException if the given array is <code>null</code>.
071       * @throws AssertionError if the actual collection does not contain the given objects, or if the actual collection
072       * contains elements other than the ones specified.
073       */
074      public CollectionAssert containsOnly(Object...objects) {
075        isNotNull();
076        validateIsNotNull(objects);
077        List<Object> copy = new ArrayList<Object>(actual);
078        List<Object> notFound = notFoundInCopy(copy, objects);
079        if (!notFound.isEmpty()) throw failureIfExpectedElementsNotFound(notFound);
080        if (copy.isEmpty()) return this;
081        throw failureIfUnexpectedElementsFound(copy);
082      }
083    
084      private List<Object> notFoundInCopy(List<Object> copy, Object... objects) {
085        List<Object> notFound = new ArrayList<Object>();
086        for (Object o : objects) {
087          if (!copy.contains(o)) {
088            notFound.add(o);
089            continue;
090          }
091          copy.remove(o);
092        }
093        return notFound;
094      }
095    
096      private AssertionError failureIfExpectedElementsNotFound(Collection<Object> notFound) {
097        failIfCustomMessageIsSet();
098        return failure(concat("collection:", format(actual), " does not contain element(s):", format(notFound)));
099      }
100    
101      private AssertionError failureIfUnexpectedElementsFound(List<Object> unexpected) {
102        failIfCustomMessageIsSet();
103        return failure(concat("unexpected element(s):", format(unexpected), " in collection:", format(actual)));
104      }
105    
106      /**
107       * Verifies that the actual collection does not contain the given objects.
108       * @param objects the objects that the collection should exclude.
109       * @return this assertion object.
110       * @throws AssertionError if the actual collection is <code>null</code>.
111       * @throws NullPointerException if the given array is <code>null</code>.
112       * @throws AssertionError if the actual collection contains any of the given objects.
113       */
114      public CollectionAssert excludes(Object...objects) {
115        isNotNull();
116        validateIsNotNull(objects);
117        Collection<Object> found = found(actual, objects);
118        if (found.isEmpty()) return this;
119        failIfCustomMessageIsSet();
120        throw failure(concat("collection:", format(actual), " does not exclude element(s):", format(found)));
121      }
122    
123      private void validateIsNotNull(Object[] objects) {
124        if (objects == null)
125          throw new NullPointerException(formattedErrorMessage("the given array of objects should not be null"));
126      }
127    
128      /**
129       * Verifies that the actual collection does not have duplicates.
130       * @return this assertion object.
131       * @throws AssertionError if the actual collection is <code>null</code>.
132       * @throws AssertionError if the actual collection has duplicates.
133       */
134      public CollectionAssert doesNotHaveDuplicates() {
135        isNotNull();
136        Collection<?> duplicates = duplicatesFrom(actual);
137        if (duplicates.isEmpty()) return this;
138        failIfCustomMessageIsSet();
139        throw failure(concat("collection:", format(actual), " contains duplicate(s):", format(duplicates)));
140      }
141    
142      private String format(Collection<?> c) {
143        return inBrackets(c);
144      }
145    
146      /** {@inheritDoc} */
147      public CollectionAssert as(String description) {
148        description(description);
149        return this;
150      }
151    
152      /** {@inheritDoc} */
153      public CollectionAssert describedAs(String description) {
154        return as(description);
155      }
156    
157      /** {@inheritDoc} */
158      public CollectionAssert as(Description description) {
159        description(description);
160        return this;
161      }
162    
163      /** {@inheritDoc} */
164      public CollectionAssert describedAs(Description description) {
165        return as(description);
166      }
167    
168      /**
169       * Verifies that the actual collection satisfies the given condition.
170       * @param condition the given condition.
171       * @return this assertion object.
172       * @throws NullPointerException if the given condition is <code>null</code>.
173       * @throws AssertionError if the actual collection does not satisfy the given condition.
174       * @see #is(Condition)
175       */
176      public CollectionAssert satisfies(Condition<Collection<?>> condition) {
177        assertSatisfies(condition);
178        return this;
179      }
180    
181      /**
182       * Verifies that the actual collection does not satisfy the given condition.
183       * @param condition the given condition.
184       * @return this assertion object.
185       * @throws NullPointerException if the given condition is <code>null</code>.
186       * @throws AssertionError if the actual collection satisfies the given condition.
187       * @see #isNot(Condition)
188       */
189      public CollectionAssert doesNotSatisfy(Condition<Collection<?>> condition) {
190        assertDoesNotSatisfy(condition);
191        return this;
192      }
193    
194      /**
195       * Alias for <code>{@link #satisfies(Condition)}</code>.
196       * @param condition the given condition.
197       * @return this assertion object.
198       * @throws NullPointerException if the given condition is <code>null</code>.
199       * @throws AssertionError if the actual collection does not satisfy the given condition.
200       * @since 1.2
201       */
202      public CollectionAssert is(Condition<Collection<?>> condition) {
203        assertIs(condition);
204        return this;
205      }
206    
207      /**
208       * Alias for <code>{@link #doesNotSatisfy(Condition)}</code>.
209       * @param condition the given condition.
210       * @return this assertion object.
211       * @throws NullPointerException if the given condition is <code>null</code>.
212       * @throws AssertionError if the actual collection satisfies the given condition.
213       * @since 1.2
214       */
215      public CollectionAssert isNot(Condition<Collection<?>> condition) {
216        assertIsNot(condition);
217        return this;
218      }
219    
220      /**
221       * Verifies that the actual collection is <code>null</code> or empty.
222       * @throws AssertionError if the actual collection is not <code>null</code> or not empty.
223       */
224      public void isNullOrEmpty() {
225        if (Collections.isEmpty(actual)) return;
226        failIfCustomMessageIsSet();
227        fail(concat("expecting a null or empty collection, but was:", format(actual)));
228      }
229    
230      /**
231       * Verifies that the actual collection is not <code>null</code>.
232       * @return this assertion object.
233       * @throws AssertionError if the actual collection is <code>null</code>.
234       */
235      public CollectionAssert isNotNull() {
236        if (actual != null) return this;
237        failIfCustomMessageIsSet();
238        throw failure("expecting a non-null collection, but it was null");
239      }
240    
241      /**
242       * Verifies that the actual collection is empty (not <code>null</code> with zero elements.)
243       * @throws AssertionError if the actual collection is <code>null</code>.
244       * @throws AssertionError if the actual collection is not empty.
245       */
246      public void isEmpty() {
247        isNotNull();
248        if (Collections.isEmpty(actual)) return;
249        failIfCustomMessageIsSet();
250        fail(concat("expecting empty collection, but was:", format(actual)));
251      }
252    
253      /**
254       * Verifies that the actual collection contains at least on element.
255       * @return this assertion object.
256       * @throws AssertionError if the actual collection is <code>null</code>.
257       * @throws AssertionError if the actual collection is empty.
258       */
259      public CollectionAssert isNotEmpty() {
260        isNotNull();
261        if (!actual.isEmpty()) return this;
262        failIfCustomMessageIsSet();
263        throw failure("expecting a non-empty collection, but it was empty");
264      }
265    
266      /**
267       * Verifies that the number of elements in the actual collection is equal to the given one.
268       * @param expected the expected number of elements in the actual collection.
269       * @return this assertion object.
270       * @throws AssertionError if the actual collection is <code>null</code>.
271       * @throws AssertionError if the number of elements of the actual collection is not equal to the given one.
272       */
273      public CollectionAssert hasSize(int expected) {
274        int actualSize = actualGroupSize();
275        if (actualSize == expected) return this;
276        failIfCustomMessageIsSet();
277        throw failure(concat(
278            "expected size:", inBrackets(expected)," but was:", inBrackets(actualSize), " for collection:", format(actual)));
279      }
280    
281      /**
282       * Returns the number of elements in the actual collection.
283       * @return the number of elements in the actual collection.
284       */
285      protected int actualGroupSize() {
286        isNotNull();
287        return actual.size();
288      }
289    
290      /**
291       * Verifies that the actual collection is equal to the given one.
292       * @param expected the given collection to compare the actual collection to.
293       * @return this assertion object.
294       * @throws AssertionError if the actual collection is not equal to the given one.
295       */
296      public CollectionAssert isEqualTo(Collection<?> expected) {
297        assertEqualTo(expected);
298        return this;
299      }
300    
301      /**
302       * Verifies that the actual collection is not equal to the given one.
303       * @param other the given collection to compare the actual collection to.
304       * @return this assertion object.
305       * @throws AssertionError if the actual collection is equal to the given one.
306       */
307      public CollectionAssert isNotEqualTo(Collection<?> other) {
308        assertNotEqualTo(other);
309        return this;
310      }
311    
312      /**
313       * Verifies that the actual collection is the same as the given one.
314       * @param expected the given collection to compare the actual collection to.
315       * @return this assertion object.
316       * @throws AssertionError if the actual collection is not the same as the given one.
317       */
318      public CollectionAssert isSameAs(Collection<?> expected) {
319        assertSameAs(expected);
320        return this;
321      }
322    
323      /**
324       * Verifies that the actual collection is not the same as the given one.
325       * @param other the given collection to compare the actual collection to.
326       * @return this assertion object.
327       * @throws AssertionError if the actual collection is the same as the given one.
328       */
329      public CollectionAssert isNotSameAs(Collection<?> other) {
330        assertNotSameAs(other);
331        return this;
332      }
333    
334      /** {@inheritDoc} */
335      public CollectionAssert overridingErrorMessage(String message) {
336        replaceDefaultErrorMessagesWith(message);
337        return this;
338      }
339    }