001    /*
002     * Created on Aug 4, 2010
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * 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 is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     * 
013     * Copyright @2010-2011 the original author or authors.
014     */
015    package org.fest.assertions.internal;
016    
017    import static org.fest.assertions.error.ShouldBeEqual.shouldBeEqual;
018    import static org.fest.assertions.error.ShouldBeIn.shouldBeIn;
019    import static org.fest.assertions.error.ShouldBeInstance.shouldBeInstance;
020    import static org.fest.assertions.error.ShouldBeInstanceOfAny.shouldBeInstanceOfAny;
021    import static org.fest.assertions.error.ShouldBeSame.shouldBeSame;
022    import static org.fest.assertions.error.ShouldNotBeEqual.shouldNotBeEqual;
023    import static org.fest.assertions.error.ShouldNotBeIn.shouldNotBeIn;
024    import static org.fest.assertions.error.ShouldNotBeNull.shouldNotBeNull;
025    import static org.fest.assertions.error.ShouldNotBeSame.shouldNotBeSame;
026    import static org.fest.util.ToString.toStringOf;
027    
028    import java.util.Collection;
029    import java.util.Comparator;
030    
031    import org.fest.assertions.core.AssertionInfo;
032    import org.fest.util.ComparatorBasedComparisonStrategy;
033    import org.fest.util.ComparisonStrategy;
034    import org.fest.util.StandardComparisonStrategy;
035    import org.fest.util.VisibleForTesting;
036    
037    /**
038     * Reusable assertions for {@code Object}s.
039     * 
040     * @author Yvonne Wang
041     * @author Alex Ruiz
042     */
043    public class Objects {
044    
045      private static final Objects INSTANCE = new Objects();
046    
047      /**
048       * Returns the singleton instance of this class based on {@link StandardComparisonStrategy}.
049       * @return the singleton instance of this class based on {@link StandardComparisonStrategy}.
050       */
051      public static Objects instance() {
052        return INSTANCE;
053      }
054    
055      @VisibleForTesting
056      Failures failures = Failures.instance();
057    
058      private ComparisonStrategy comparisonStrategy;
059      
060      @VisibleForTesting
061      Objects() {
062        this(StandardComparisonStrategy.instance());
063      }
064    
065      public Objects(ComparisonStrategy comparisonStrategy) {
066        this.comparisonStrategy = comparisonStrategy;
067      }
068      
069      @VisibleForTesting
070      public Comparator<?> getComparator() {
071        if (comparisonStrategy instanceof ComparatorBasedComparisonStrategy) {
072          return ((ComparatorBasedComparisonStrategy)comparisonStrategy).getComparator();
073        }
074        return null;
075      }
076    
077      /**
078       * Verifies that the given object is an instance of the given type.
079       * @param info contains information about the assertion.
080       * @param actual the given object.
081       * @param type the type to check the given object against.
082       * @throws NullPointerException if the given type is {@code null}.
083       * @throws AssertionError if the given object is {@code null}.
084       * @throws AssertionError if the given object is not an instance of the given type.
085       */
086      public void assertIsInstanceOf(AssertionInfo info, Object actual, Class<?> type) {
087        if (type == null) throw new NullPointerException("The given type should not be null");
088        assertNotNull(info, actual);
089        if (type.isInstance(actual)) return;
090        throw failures.failure(info, shouldBeInstance(actual, type));
091      }
092    
093      /**
094       * Verifies that the given object is an instance of any of the given types.
095       * @param info contains information about the assertion.
096       * @param actual the given object.
097       * @param types the types to check the given object against.
098       * @throws NullPointerException if the given array is {@code null}.
099       * @throws IllegalArgumentException if the given array is empty.
100       * @throws NullPointerException if the given array has {@code null} elements.
101       * @throws AssertionError if the given object is {@code null}.
102       * @throws AssertionError if the given object is not an instance of any of the given types.
103       */
104      public void assertIsInstanceOfAny(AssertionInfo info, Object actual, Class<?>[] types) {
105        checkIsNotNullAndIsNotEmpty(types);
106        assertNotNull(info, actual);
107        boolean found = false;
108        for (Class<?> type : types) {
109          if (type == null) {
110            String format = "The given array of types:<%s> should not have null elements";
111            throw new NullPointerException(String.format(format, toStringOf(types)));
112          }
113          if (type.isInstance(actual)) {
114            found = true;
115            break;
116          }
117        }
118        if (found) return;
119        throw failures.failure(info, shouldBeInstanceOfAny(actual, types));
120      }
121    
122      private void checkIsNotNullAndIsNotEmpty(Class<?>[] types) {
123        if (types == null) throw new NullPointerException("The given array of types should not be null");
124        if (types.length == 0) throw new IllegalArgumentException("The given array of types should not be empty");
125      }
126    
127      /**
128       * Asserts that two objects are equal.
129       * @param info contains information about the assertion.
130       * @param actual the "actual" object.
131       * @param expected the "expected" object.
132       * @throws AssertionError if {@code actual} is not equal to {@code expected}. This method will throw a
133       *           {@code org.junit.ComparisonFailure} instead if JUnit is in the classpath and the given objects are not
134       *           equal.
135       */
136      public void assertEqual(AssertionInfo info, Object actual, Object expected) {
137        if (areEqual(actual, expected)) return;
138        throw failures.failure(info, shouldBeEqual(actual, expected, comparisonStrategy));
139      }
140    
141      /**
142       * Asserts that two objects are not equal.
143       * @param info contains information about the assertion.
144       * @param actual the given object.
145       * @param other the object to compare {@code actual} to.
146       * @throws AssertionError if {@code actual} is equal to {@code other}.
147       */
148      public void assertNotEqual(AssertionInfo info, Object actual, Object other) {
149        if (!areEqual(actual, other)) return;
150        throw failures.failure(info, shouldNotBeEqual(actual, other, comparisonStrategy));
151      }
152    
153      /**
154       * Compares actual and other with standard strategy (null safe equals check).
155       * @param actual the object to compare to other
156       * @param other the object to compare to actual
157       * @return true if actual and other are equal (null safe equals check), false otherwise.
158       */
159      private boolean areEqual(Object actual, Object other) {
160        return comparisonStrategy.areEqual(other, actual);
161      }
162    
163      /**
164       * Asserts that the given object is {@code null}.
165       * @param info contains information about the assertion.
166       * @param actual the given object.
167       * @throws AssertionError if the given object is not {@code null}.
168       */
169      public void assertNull(AssertionInfo info, Object actual) {
170        if (actual == null) return;
171        throw failures.failure(info, shouldBeEqual(actual, null, comparisonStrategy));
172      }
173    
174      /**
175       * Asserts that the given object is not {@code null}.
176       * @param info contains information about the assertion.
177       * @param actual the given object.
178       * @throws AssertionError if the given object is {@code null}.
179       */
180      public void assertNotNull(AssertionInfo info, Object actual) {
181        if (actual != null) return;
182        throw failures.failure(info, shouldNotBeNull());
183      }
184    
185      /**
186       * Asserts that two objects refer to the same object.
187       * @param info contains information about the assertion.
188       * @param actual the given object.
189       * @param expected the expected object.
190       * @throws AssertionError if the given objects do not refer to the same object.
191       */
192      public void assertSame(AssertionInfo info, Object actual, Object expected) {
193        if (actual == expected) return;
194        throw failures.failure(info, shouldBeSame(actual, expected));
195      }
196    
197      /**
198       * Asserts that two objects do not refer to the same object.
199       * @param info contains information about the assertion.
200       * @param actual the given object.
201       * @param other the object to compare {@code actual} to.
202       * @throws AssertionError if the given objects refer to the same object.
203       */
204      public void assertNotSame(AssertionInfo info, Object actual, Object other) {
205        if (actual != other) return;
206        throw failures.failure(info, shouldNotBeSame(actual));
207      }
208    
209      /**
210       * Asserts that the given object is present in the given array.
211       * @param info contains information about the assertion.
212       * @param actual the given object.
213       * @param values the given array.
214       * @throws NullPointerException if the given array is {@code null}.
215       * @throws IllegalArgumentException if the given array is empty.
216       * @throws AssertionError if the given object is not present in the given array.
217       */
218      public void assertIsIn(AssertionInfo info, Object actual, Object[] values) {
219        checkIsNotNullAndNotEmpty(values);
220        assertNotNull(info, actual);
221        if (isActualIn(actual, values)) return;
222        throw failures.failure(info, shouldBeIn(actual, values, comparisonStrategy));
223      }
224    
225      /**
226       * Asserts that the given object is not present in the given array.
227       * @param info contains information about the assertion.
228       * @param actual the given object.
229       * @param values the given array.
230       * @throws NullPointerException if the given array is {@code null}.
231       * @throws IllegalArgumentException if the given array is empty.
232       * @throws AssertionError if the given object is present in the given array.
233       */
234      public void assertIsNotIn(AssertionInfo info, Object actual, Object[] values) {
235        checkIsNotNullAndNotEmpty(values);
236        assertNotNull(info, actual);
237        if (!isActualIn(actual, values)) return;
238        throw failures.failure(info, shouldNotBeIn(actual, values, comparisonStrategy));
239      }
240    
241      private void checkIsNotNullAndNotEmpty(Object[] values) {
242        if (values == null) throw new NullPointerException("The given array should not be null");
243        if (values.length == 0) throw new IllegalArgumentException("The given array should not be empty");
244      }
245    
246      private boolean isActualIn(Object actual, Object[] values) {
247        for (Object value : values)
248          if (areEqual(value, actual)) return true;
249        return false;
250      }
251    
252      /**
253       * Asserts that the given object is present in the given collection.
254       * @param info contains information about the assertion.
255       * @param actual the given object.
256       * @param values the given collection.
257       * @throws NullPointerException if the given collection is {@code null}.
258       * @throws IllegalArgumentException if the given collection is empty.
259       * @throws AssertionError if the given object is not present in the given collection.
260       */
261      public void assertIsIn(AssertionInfo info, Object actual, Collection<?> values) {
262        checkIsNotNullAndNotEmpty(values);
263        assertNotNull(info, actual);
264        if (isActualIn(actual, values)) return;
265        throw failures.failure(info, shouldBeIn(actual, values, comparisonStrategy));
266      }
267    
268      /**
269       * Asserts that the given object is not present in the given collection.
270       * @param info contains information about the assertion.
271       * @param actual the given object.
272       * @param values the given collection.
273       * @throws NullPointerException if the given collection is {@code null}.
274       * @throws IllegalArgumentException if the given collection is empty.
275       * @throws AssertionError if the given object is present in the given collection.
276       */
277      public void assertIsNotIn(AssertionInfo info, Object actual, Collection<?> values) {
278        checkIsNotNullAndNotEmpty(values);
279        assertNotNull(info, actual);
280        if (!isActualIn(actual, values)) return;
281        throw failures.failure(info, shouldNotBeIn(actual, values, comparisonStrategy));
282      }
283    
284      private void checkIsNotNullAndNotEmpty(Collection<?> values) {
285        if (values == null) throw new NullPointerException("The given collection should not be null");
286        if (values.isEmpty()) throw new IllegalArgumentException("The given collection should not be empty");
287      }
288    
289      private boolean isActualIn(Object actual, Collection<?> values) {
290        for (Object value : values)
291          if (areEqual(value, actual)) return true;
292        return false;
293      }
294    }