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 }