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