001    /*
002     * Created on Oct 17, 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.ShouldBeGreater.shouldBeGreater;
019    import static org.fest.assertions.error.ShouldBeGreaterOrEqual.shouldBeGreaterOrEqual;
020    import static org.fest.assertions.error.ShouldBeLess.shouldBeLess;
021    import static org.fest.assertions.error.ShouldBeLessOrEqual.shouldBeLessOrEqual;
022    import static org.fest.assertions.error.ShouldNotBeEqual.shouldNotBeEqual;
023    
024    import java.util.Comparator;
025    
026    import org.fest.assertions.core.AssertionInfo;
027    import org.fest.util.ComparatorBasedComparisonStrategy;
028    import org.fest.util.ComparisonStrategy;
029    import org.fest.util.StandardComparisonStrategy;
030    import org.fest.util.VisibleForTesting;
031    
032    /**
033     * Reusable assertions for <code>{@link Comparable}</code>s.
034     *
035     * @author Alex Ruiz
036     * @author Joel Costigliola
037     */
038    public class Comparables {
039    
040      private static final Comparables INSTANCE = new Comparables();
041    
042      /**
043       * Returns the singleton instance of this class based on {@link StandardComparisonStrategy}.
044       * @return the singleton instance of this class based on {@link StandardComparisonStrategy}.
045       */
046      public static Comparables instance() {
047        return INSTANCE;
048      }
049    
050      @VisibleForTesting Failures failures = Failures.instance();
051      ComparisonStrategy comparisonStrategy;
052    
053      @VisibleForTesting Comparables() {
054        this(StandardComparisonStrategy.instance());
055      }
056    
057      public Comparables(ComparisonStrategy comparisonStrategy) {
058        this.comparisonStrategy = comparisonStrategy;
059      }  
060    
061      @VisibleForTesting
062      public Comparator<?> getComparator() {
063        if (comparisonStrategy instanceof ComparatorBasedComparisonStrategy) {
064          return ((ComparatorBasedComparisonStrategy)comparisonStrategy).getComparator();
065        }
066        return null;
067      }
068    
069      @VisibleForTesting
070      void setFailures(Failures failures) {
071        this.failures = failures;
072      }
073    
074      /**
075       * Asserts that two T instances are equal.
076       * @param info contains information about the assertion.
077       * @param actual the actual value.
078       * @param expected the expected value.
079       * @throws AssertionError if the actual value is {@code null}.
080       * @throws AssertionError if the actual value is not equal to the expected one. This method will throw a
081       *           {@code org.junit.ComparisonFailure} instead if JUnit is in the classpath and the expected and actual
082       *           values are not equal.
083       */
084      public <T> void assertEqual(AssertionInfo info, T actual, T expected) {
085        assertNotNull(info, actual);
086        if (areEqual(actual, expected)) return;
087        throw failures.failure(info, shouldBeEqual(actual, expected, comparisonStrategy));
088      }
089    
090      protected <T> boolean areEqual(T actual, T expected) {
091        return comparisonStrategy.areEqual(actual, expected);
092      }
093    
094      /**
095       * Asserts that two T instances are not equal.
096       * @param info contains information about the assertion.
097       * @param actual the actual value.
098       * @param other the value to compare the actual value to.
099       * @throws AssertionError if the actual value is {@code null}.
100       * @throws AssertionError if the actual value is equal to the other one.
101       */
102      public <T> void assertNotEqual(AssertionInfo info, T actual, T other) {
103        assertNotNull(info, actual);
104        if (!areEqual(actual, other)) return;
105        throw failures.failure(info, shouldNotBeEqual(actual, other, comparisonStrategy));
106      }
107    
108      /**
109       * Asserts that two <code>{@link Comparable}</code>s are equal by invoking
110       * <code>{@link Comparable#compareTo(Object)}</code>.<br>
111       * Note that it does not rely on the custom {@link #comparisonStrategy} if one has been set.
112       * @param <T> used to guarantee that two objects of the same type are being compared against each other.
113       * @param info contains information about the assertion.
114       * @param actual the actual value.
115       * @param expected the expected value.
116       * @throws AssertionError if the actual value is {@code null}.
117       * @throws AssertionError if the actual value is not equal to the expected one. This method will throw a
118       * {@code org.junit.ComparisonFailure} instead if JUnit is in the classpath and the expected and actual
119       * values are not equal.
120       */
121      public <T extends Comparable<? super T>> void assertEqualByComparison(AssertionInfo info, T actual, T expected) {
122        assertNotNull(info, actual);
123        // we don't delegate to comparisonStrategy, as this assertion makes it clear it relies on Comparable
124        if (actual.compareTo(expected) == 0) return;
125        throw failures.failure(info, shouldBeEqual(actual, expected));
126      }
127    
128      /**
129       * Asserts that two <code>{@link Comparable}</code>s are not equal by invoking
130       * <code>{@link Comparable#compareTo(Object)}</code>.<br>
131       * Note that it does not rely on the custom {@link #comparisonStrategy} if one has been set.
132       * @param <T> used to guarantee that two objects of the same type are being compared against each other.
133       * @param info contains information about the assertion.
134       * @param actual the actual value.
135       * @param other the value to compare the actual value to.
136       * @throws AssertionError if the actual value is {@code null}.
137       * @throws AssertionError if the actual value is equal to the other one.
138       */
139      public <T extends Comparable<? super T>> void assertNotEqualByComparison(AssertionInfo info, T actual, T other) {
140        assertNotNull(info, actual);
141        // we don't delagate to comparisonStrategy, as this assertion makes it clear it relies on Comparable
142        if (actual.compareTo(other) != 0) return;
143        throw failures.failure(info, shouldNotBeEqual(actual, other));
144      }
145    
146      /**
147       * Asserts that the actual value is less than the other one.
148       * @param <T> used to guarantee that two objects of the same type are being compared against each other.
149       * @param info contains information about the assertion.
150       * @param actual the actual value.
151       * @param other the value to compare the actual value to.
152       * @throws AssertionError if the actual value is {@code null}.
153       * @throws AssertionError if the actual value is not less than the other one: this assertion will
154       * fail if the actual value is equal to or greater than the other value.
155       */
156      public <T extends Comparable<? super T>> void assertLessThan(AssertionInfo info, T actual, T other) {
157        assertNotNull(info, actual);
158        if (isLessThan(actual, other)) return;
159        throw failures.failure(info, shouldBeLess(actual, other, comparisonStrategy));
160      }
161    
162      /**
163       * Asserts that the actual value is less than or equal to the other one.
164       * @param <T> used to guarantee that two objects of the same type are being compared against each other.
165       * @param info contains information about the assertion.
166       * @param actual the actual value.
167       * @param other the value to compare the actual value to.
168       * @throws AssertionError if the actual value is {@code null}.
169       * @throws AssertionError if the actual value is greater than the other one.
170       */
171      public <T extends Comparable<? super T>> void assertLessThanOrEqualTo(AssertionInfo info, T actual, T other) {
172        assertNotNull(info, actual);
173        if (!isGreaterThan(actual, other)) return;
174        throw failures.failure(info, shouldBeLessOrEqual(actual, other, comparisonStrategy));
175      }
176    
177      /**
178       * Asserts that the actual value is greater than the other one.
179       * @param <T> used to guarantee that two objects of the same type are being compared against each other.
180       * @param info contains information about the assertion.
181       * @param actual the actual value.
182       * @param other the value to compare the actual value to.
183       * @throws AssertionError if the actual value is {@code null}.
184       * @throws AssertionError if the actual value is not greater than the other one: this assertion will
185       * fail if the actual value is equal to or less than the other value.
186       */
187      public <T extends Comparable<? super T>> void assertGreaterThan(AssertionInfo info, T actual, T other) {
188        assertNotNull(info, actual);
189        if (isGreaterThan(actual, other)) return;
190        throw failures.failure(info, shouldBeGreater(actual, other, comparisonStrategy));
191      }
192    
193      /**
194       * delegates to {@link #comparisonStrategy#isGreaterThan(Object, Object)} 
195       */
196      private boolean isGreaterThan(Object actual, Object other) {
197        return comparisonStrategy.isGreaterThan(actual, other);
198      }
199    
200      /**
201       * Asserts that the actual value is greater than or equal to the other one.
202       * @param <T> used to guarantee that two objects of the same type are being compared against each other.
203       * @param info contains information about the assertion.
204       * @param actual the actual value.
205       * @param other the value to compare the actual value to.
206       * @throws AssertionError if the actual value is {@code null}.
207       * @throws AssertionError if the actual value is less than the other one.
208       */
209      public <T extends Comparable<? super T>> void assertGreaterThanOrEqualTo(AssertionInfo info, T actual, T other) {
210        assertNotNull(info, actual);
211        if (!isLessThan(actual, other)) return;
212        throw failures.failure(info, shouldBeGreaterOrEqual(actual, other, comparisonStrategy));
213      }
214    
215      private boolean isLessThan(Object actual, Object other) {
216        return comparisonStrategy.isLessThan(actual, other);
217      }
218    
219      protected static <T> void assertNotNull(AssertionInfo info, T actual) {
220        Objects.instance().assertNotNull(info, actual);
221      }
222    }