001 /*
002 * Created on Jan 23, 2008
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 @2008-2010 the original author or authors.
014 */
015 package org.fest.assertions;
016
017 import static org.fest.assertions.Formatting.inBrackets;
018 import static org.fest.util.Strings.*;
019
020 import java.util.*;
021
022 /**
023 * Understands assertions for <code>{@link Map}</code>s. To create a new instance of this class use the method
024 * <code>{@link Assertions#assertThat(Map)}</code>.
025 *
026 * @author David DIDIER
027 * @author Yvonne Wang
028 * @author Alex Ruiz
029 */
030 public class MapAssert extends GroupAssert<Map<?, ?>> {
031
032 private static final String ENTRY = "entry";
033 private static final String ENTRIES= "entries";
034
035 /**
036 * Creates a new </code>{@link MapAssert}</code>.
037 * @param actual the target to verify.
038 */
039 protected MapAssert(Map<?, ?> actual) {
040 super(actual);
041 }
042
043 /** {@inheritDoc} */
044 @Override public MapAssert as(String description) {
045 description(description);
046 return this;
047 }
048
049 /** {@inheritDoc} */
050 @Override public MapAssert describedAs(String description) {
051 return as(description);
052 }
053
054 /** {@inheritDoc} */
055 @Override public MapAssert as(Description description) {
056 description(description);
057 return this;
058 }
059
060 /** {@inheritDoc} */
061 @Override public MapAssert describedAs(Description description) {
062 return as(description);
063 }
064
065
066 /**
067 * Verifies that the actual <code>{@link Map}</code> contains the given entries.
068 * <p>
069 * Example:
070 * <pre>
071 * // static import org.fest.assertions.Assertions.*;
072 * // static import org.fest.assertions.MapAssert.*;
073 *
074 * assertThat(myMap).{@link #includes(org.fest.assertions.MapAssert.Entry...) includes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin));
075 * </pre>
076 * </p>
077 * @param entries the given entries.
078 * @return this assertion error.
079 * @throws AssertionError if the actual map is <code>null</code>.
080 * @throws AssertionError if the actual <code>Map</code> does not contain any of the given entries.
081 * @throws NullPointerException if the given array of entries is <code>null</code>.
082 * @throws NullPointerException if any of the entries in the given array is <code>null</code>.
083 */
084 public MapAssert includes(Entry...entries) {
085 isNotNull();
086 validate(ENTRIES, entries);
087 List<Entry> notFound = new ArrayList<Entry>();
088 for (Entry e : entries) if (!containsEntry(e)) notFound.add(e);
089 if (!notFound.isEmpty()) failIfNotFound(entryOrEntries(notFound), notFound);
090 return this;
091 }
092
093 /**
094 * Verifies that the actual <code>{@link Map}</code> does not contain the given entries.
095 * <p>
096 * Example:
097 * <pre>
098 * // static import org.fest.assertions.Assertions.*;
099 * // static import org.fest.assertions.MapAssert.*;
100 *
101 * assertThat(myMap).{@link #excludes(org.fest.assertions.MapAssert.Entry...) excludes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin));
102 * </pre>
103 * </p>
104 * @param entries the given entries.
105 * @return this assertion error.
106 * @throws AssertionError if the actual map is <code>null</code>.
107 * @throws AssertionError if the actual <code>Map</code> contains any of the given entries.
108 * @throws NullPointerException if the given array of entries is <code>null</code>.
109 * @throws NullPointerException if any of the entries in the given array is <code>null</code>.
110 */
111 public MapAssert excludes(Entry...entries) {
112 isNotNull();
113 validate(ENTRIES, entries);
114 List<Entry> found = new ArrayList<Entry>();
115 for (Entry e : entries) if (containsEntry(e)) found.add(e);
116 if (!found.isEmpty()) failIfFound(entryOrEntries(found), found);
117 return this;
118 }
119
120 private boolean containsEntry(Entry e) {
121 if (e == null)
122 throw new NullPointerException(formattedErrorMessage("Entries to check should not contain null"));
123 if (!actual.containsKey(e.key)) return false;
124 return actual.get(e.key).equals(e.value);
125 }
126
127 private String entryOrEntries(List<Entry> found) {
128 return found.size() == 1 ? ENTRY : ENTRIES;
129 }
130
131 /**
132 * Creates a new map entry.
133 * @param key the key of the entry.
134 * @param value the value of the entry.
135 * @return the created entry.
136 * @see #includes(org.fest.assertions.MapAssert.Entry...)
137 */
138 public static Entry entry(Object key, Object value) {
139 return new Entry(key, value);
140 }
141
142 /**
143 * Understands an entry in a <code>{@link Map}</code>.
144 *
145 * @author Yvonne Wang
146 */
147 public static class Entry {
148 final Object key;
149 final Object value;
150
151 Entry(Object key, Object value) {
152 this.key = key;
153 this.value = value;
154 }
155
156 /** @see java.lang.Object#toString() */
157 @Override public String toString() {
158 return concat(quote(key), "=", quote(value));
159 }
160 }
161
162 private void failIfNotFound(String description, Collection<?> notFound) {
163 failIfCustomMessageIsSet();
164 fail(concat("the map:", formattedActual(), " does not contain the ", description, ":", inBrackets(notFound)));
165 }
166
167 private void validate(String description, Object[] objects) {
168 if (objects == null)
169 throw new NullPointerException(
170 formattedErrorMessage(concat("The given array of ", description, " should not be null")));
171 }
172
173 private void failIfFound(String description, Collection<?> found) {
174 failIfCustomMessageIsSet();
175 fail(concat("the map:", formattedActual(), " contains the ", description, ":", inBrackets(found)));
176 }
177
178 /**
179 * Verifies that the number of elements in the actual <code>{@link Map}</code> is equal to the given one.
180 * @param expected the expected number of elements in the actual <code>Map</code>.
181 * @return this assertion object.
182 * @throws AssertionError if the actual map is <code>null</code>.
183 * @throws AssertionError if the number of elements of the actual <code>Map</code> is not equal to the given one.
184 */
185 @Override public MapAssert hasSize(int expected) {
186 isNotNull();
187 int actualSize = actualGroupSize();
188 if (actualSize == expected) return this;
189 failIfCustomMessageIsSet();
190 throw failure(concat(
191 "expected size:", inBrackets(expected)," but was:", inBrackets(actualSize), " for map:", inBrackets(actual)));
192 }
193
194 private String formattedActual() {
195 return inBrackets(actual);
196 }
197
198 /**
199 * Verifies that the actual <code>{@link Map}</code> is equal to the given one.
200 * @param expected the given map to compare the actual <code>Map</code> to.
201 * @return this assertion object.
202 * @throws AssertionError if the actual <code>Map</code> is not equal to the given one.
203 */
204 @Override public MapAssert isEqualTo(Map<?, ?> expected) {
205 assertEqualTo(expected);
206 return this;
207 }
208
209 /**
210 * Verifies that the actual <code>{@link Map}</code> contains at least on element.
211 * @return this assertion object.
212 * @throws AssertionError if the actual <code>Map</code> is empty.
213 */
214 @Override public MapAssert isNotEmpty() {
215 assertIsNotEmpty();
216 return this;
217 }
218
219 /**
220 * Verifies that the actual <code>{@link Map}</code> is not equal to the given one.
221 * @param other the given map to compare the actual <code>Map</code> to.
222 * @return this assertion object.
223 * @throws AssertionError if the actual <code>Map</code> is equal to the given one.
224 */
225 @Override public MapAssert isNotEqualTo(Map<?, ?> other) {
226 assertNotEqualTo(other);
227 return this;
228 }
229
230 /**
231 * Verifies that the actual <code>{@link Map}</code> is not <code>null</code>.
232 * @return this assertion object.
233 * @throws AssertionError if the actual <code>Map</code> is <code>null</code>.
234 */
235 @Override public MapAssert isNotNull() {
236 assertNotNull();
237 return this;
238 }
239
240 /**
241 * Verifies that the actual <code>{@link Map}</code> is not the same as the given one.
242 * @param other the given map to compare the actual <code>Map</code> to.
243 * @return this assertion object.
244 * @throws AssertionError if the actual <code>Map</code> is the same as the given one.
245 */
246 @Override public MapAssert isNotSameAs(Map<?, ?> other) {
247 assertNotSameAs(other);
248 return this;
249 }
250
251 /**
252 * Verifies that the actual <code>{@link Map}</code> is the same as the given one.
253 * @param expected the given map to compare the actual <code>Map</code> to.
254 * @return this assertion object.
255 * @throws AssertionError if the actual <code>Map</code> is not the same as the given one.
256 */
257 @Override public MapAssert isSameAs(Map<?, ?> expected) {
258 assertSameAs(expected);
259 return this;
260 }
261
262 /**
263 * Verifies that the actual <code>{@link Map}</code> satisfies the given condition.
264 * @param condition the given condition.
265 * @return this assertion object.
266 * @throws NullPointerException if the given condition is <code>null</code>.
267 * @throws AssertionError if the actual <code>Map</code> does not satisfy the given condition.
268 * @see #is(Condition)
269 */
270 @Override public MapAssert satisfies(Condition<Map<?, ?>> condition) {
271 assertSatisfies(condition);
272 return this;
273 }
274
275 /**
276 * Verifies that the actual <code>{@link Map}</code> does not satisfy the given condition.
277 * @param condition the given condition.
278 * @return this assertion object.
279 * @throws NullPointerException if the given condition is <code>null</code>.
280 * @throws AssertionError if the actual <code>Map</code> satisfies the given condition.
281 * @see #isNot(Condition)
282 */
283 @Override public MapAssert doesNotSatisfy(Condition<Map<?, ?>> condition) {
284 assertDoesNotSatisfy(condition);
285 return this;
286 }
287
288 /**
289 * Alias for <code>{@link #satisfies(Condition)}</code>.
290 * @param condition the given condition.
291 * @return this assertion object.
292 * @throws NullPointerException if the given condition is <code>null</code>.
293 * @throws AssertionError if the actual <code>Map</code> does not satisfy the given condition.
294 * @since 1.2
295 */
296 @Override public MapAssert is(Condition<Map<?, ?>> condition) {
297 assertIs(condition);
298 return this;
299 }
300
301 /**
302 * Alias for <code>{@link #doesNotSatisfy(Condition)}</code>.
303 * @param condition the given condition.
304 * @return this assertion object.
305 * @throws NullPointerException if the given condition is <code>null</code>.
306 * @throws AssertionError if the actual <code>Map</code> satisfies the given condition.
307 * @since 1.2
308 */
309 @Override public MapAssert isNot(Condition<Map<?, ?>> condition) {
310 assertIsNot(condition);
311 return this;
312 }
313
314 /**
315 * Returns the number of elements in the actual <code>{@link Map}</code>.
316 * @return the number of elements in the actual <code>{@link Map}</code>.
317 */
318 @Override protected int actualGroupSize() {
319 isNotNull();
320 return actual.size();
321 }
322
323 /** {@inheritDoc} */
324 @Override public MapAssert overridingErrorMessage(String message) {
325 replaceDefaultErrorMessagesWith(message);
326 return this;
327 }
328 }