001    /*
002     * Created on Nov 18, 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.api;
016    
017    import java.util.Collection;
018    import java.util.Comparator;
019    
020    import org.fest.assertions.core.Assert;
021    import org.fest.assertions.core.Condition;
022    import org.fest.assertions.core.WritableAssertionInfo;
023    import org.fest.assertions.description.Description;
024    import org.fest.assertions.internal.Conditions;
025    import org.fest.assertions.internal.Objects;
026    import org.fest.util.ComparatorBasedComparisonStrategy;
027    import org.fest.util.VisibleForTesting;
028    
029    
030    /**
031     * Base class for all assertions.
032     * @param <S> the "self" type of this assertion class. Please read &quot;<a href="http://bit.ly/anMa4g"
033     *          target="_blank">Emulating 'self types' using Java Generics to simplify fluent API implementation</a>&quot;
034     *          for more details.
035     * @param <A> the type of the "actual" value.
036     * 
037     * @author Alex Ruiz
038     * @author Joel Costigliola
039     */
040    public abstract class AbstractAssert<S, A> implements Assert<S, A> {
041    
042      @VisibleForTesting
043      Objects objects = Objects.instance();
044      
045      @VisibleForTesting
046      Conditions conditions = Conditions.instance();
047    
048      @VisibleForTesting
049      final WritableAssertionInfo info;
050      
051      // visibility is protected to allow us write custom assertions that need access to actual
052      @VisibleForTesting
053      protected final A actual;
054      protected final S myself;
055    
056      protected AbstractAssert(A actual, Class<S> selfType) {
057        myself = selfType.cast(this);
058        this.actual = actual;
059        info = new WritableAssertionInfo();
060      }
061    
062      /** {@inheritDoc} */
063      public final S as(String description) {
064        return describedAs(description);
065      }
066    
067      /** {@inheritDoc} */
068      public final S as(Description description) {
069        return describedAs(description);
070      }
071    
072      /** {@inheritDoc} */
073      public final S describedAs(String description) {
074        info.description(description);
075        return myself;
076      }
077    
078      /** {@inheritDoc} */
079      public final S describedAs(Description description) {
080        info.description(description);
081        return myself;
082      }
083    
084      /** {@inheritDoc} */
085      public S isEqualTo(A expected) {
086        objects.assertEqual(info, actual, expected);
087        return myself;
088      }
089    
090      /** {@inheritDoc} */
091      public S isNotEqualTo(A other) {
092        objects.assertNotEqual(info, actual, other);
093        return myself;
094      }
095    
096      /** {@inheritDoc} */
097      public final void isNull() {
098        objects.assertNull(info, actual);
099      }
100    
101      /** {@inheritDoc} */
102      public final S isNotNull() {
103        objects.assertNotNull(info, actual);
104        return myself;
105      }
106    
107      /** {@inheritDoc} */
108      public final S isSameAs(A expected) {
109        objects.assertSame(info, actual, expected);
110        return myself;
111      }
112    
113      /** {@inheritDoc} */
114      public final S isNotSameAs(A other) {
115        objects.assertNotSame(info, actual, other);
116        return myself;
117      }
118    
119      /** {@inheritDoc} */
120      public final S isIn(A... values) {
121        objects.assertIsIn(info, actual, values);
122        return myself;
123      }
124    
125      /** {@inheritDoc} */
126      public final S isNotIn(A... values) {
127        objects.assertIsNotIn(info, actual, values);
128        return myself;
129      }
130    
131      /** {@inheritDoc} */
132      public final S isIn(Collection<?> values) {
133        objects.assertIsIn(info, actual, values);
134        return myself;
135      }
136    
137      /** {@inheritDoc} */
138      public final S isNotIn(Collection<?> values) {
139        objects.assertIsNotIn(info, actual, values);
140        return myself;
141      }
142    
143      /** {@inheritDoc} */
144      public final S is(Condition<A> condition) {
145        conditions.assertIs(info, actual, condition);
146        return myself;
147      }
148    
149      /** {@inheritDoc} */
150      public final S isNot(Condition<A> condition) {
151        conditions.assertIsNot(info, actual, condition);
152        return myself;
153      }
154    
155      /** {@inheritDoc} */
156      public final S has(Condition<A> condition) {
157        conditions.assertHas(info, actual, condition);
158        return myself;
159      }
160    
161      /** {@inheritDoc} */
162      public final S doesNotHave(Condition<A> condition) {
163        conditions.assertDoesNotHave(info, actual, condition);
164        return myself;
165      }
166    
167      /**
168       * The description of this assertion set with {@link #describedAs(String)} or {@link #describedAs(Description)}.
169       * @return the description String representation of this assertion. 
170       */
171      public final String descriptionText() {
172        return info.descriptionText();
173      }
174    
175      /** {@inheritDoc} */
176      public S usingComparator(Comparator<?> customComparator) {  
177        // using a specific strategy to compare actual with other objects.
178        this.objects = new Objects(new ComparatorBasedComparisonStrategy(customComparator));
179        return myself;
180      }
181    
182      /** {@inheritDoc} */
183      public S usingDefaultComparator() {  
184        // fall back to default strategy to compare actual with other objects.
185        this.objects = Objects.instance();
186        return myself;
187      }
188      
189      /** {@inheritDoc} */
190      @Override 
191      public final boolean equals(Object obj) {
192        throw new UnsupportedOperationException("'equals' is not supported...maybe you intended to call 'isEqualTo'");
193      }  
194      
195      /**
196       * Always returns 1.
197       * @return 1.
198       */
199      @Override 
200      public final int hashCode() { 
201              return 1;
202      }  
203      
204    }