/* * Created on Jan 23, 2008 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * * Copyright @2008-2013 the original author or authors. */ package org.fest.assertions; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.List; import java.util.Map; import static org.fest.util.Lists.newArrayList; import static org.fest.util.Preconditions.checkNotNull; import static org.fest.util.Strings.quote; import static org.fest.util.ToString.toStringOf; /** * Assertions for {@code Map}s. * <p/> * To create a new instance of this class invoke {@link Assertions#assertThat(Map)}. * * @author David DIDIER * @author Yvonne Wang * @author Alex Ruiz */ public class MapAssert extends GroupAssert<MapAssert, Map<?, ?>> { private static final String ENTRY = "entry"; private static final String ENTRIES = "entries"; /** * Creates a new {@link MapAssert}. * * @param actual the target to verify. */ protected MapAssert(@Nullable Map<?, ?> actual) { super(MapAssert.class, actual); } /** * Creates a new map entry. * * @param key the key of the entry. * @param value the value of the entry. * @return the created entry. * @see #includes(org.fest.assertions.MapAssert.Entry...) */ public static @Nonnull Entry entry(@Nullable Object key, @Nullable Object value) { return new Entry(key, value); } /** * Verifies that the actual {@code Map} contains the given entries. * <p/> * Example: * <pre> * // static import org.fest.assertions.Assertions.*; * // static import org.fest.assertions.MapAssert.*; * * assertThat(myMap).{@link #includes(org.fest.assertions.MapAssert.Entry...) includes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin)); * </pre> * * @param entries the given entries. * @return this assertion error. * @throws AssertionError if the actual map is {@code null}. * @throws AssertionError if the actual {@code Map} does not contain any of the given entries. * @throws NullPointerException if the given array of entries is {@code null}. * @throws NullPointerException if any of the entries in the given array is {@code null}. */ public @Nonnull MapAssert includes(@Nonnull Entry... entries) { isNotNull(); checkNotNull(entries); List<Entry> notFound = newArrayList(); for (Entry e : entries) { if (!containsEntry(checkNotNull(e))) { notFound.add(e); } } if (!notFound.isEmpty()) { failIfNotFound(entryOrEntries(notFound), notFound); } return this; } /** * Verifies that the actual {@code Map} does not contain the given entries. * <p/> * Example: * <pre> * // static import org.fest.assertions.Assertions.*; * // static import org.fest.assertions.MapAssert.*; * * assertThat(myMap).{@link #excludes(org.fest.assertions.MapAssert.Entry...) excludes}({@link #entry(Object, Object) entry}("jedi", yoda), {@link #entry(Object, Object) entry}("sith", anakin)); * </pre> * * @param entries the given entries. * @return this assertion error. * @throws AssertionError if the actual map is {@code null}. * @throws AssertionError if the actual {@code Map} contains any of the given entries. * @throws NullPointerException if the given array of entries is {@code null}. * @throws NullPointerException if any of the entries in the given array is {@code null}. */ public @Nonnull MapAssert excludes(@Nonnull Entry... entries) { isNotNull(); checkNotNull(entries); List<Entry> found = newArrayList(); for (Entry e : entries) { if (containsEntry(checkNotNull(e))) { found.add(e); } } if (!found.isEmpty()) { failIfFound(entryOrEntries(found), found); } return this; } private boolean containsEntry(@Nonnull Entry e) { if (!actual.containsKey(e.key)) { return false; } return actual.get(e.key).equals(e.value); } private @Nonnull String entryOrEntries(@Nonnull List<Entry> found) { return found.size() == 1 ? ENTRY : ENTRIES; } private void failIfNotFound(@Nonnull String description, @Nonnull Collection<?> notFound) { failIfCustomMessageIsSet(); String format = "the map:<%s> does not contain the %s:<%s>"; fail(String.format(format, formattedActual(), description, toStringOf(notFound))); } private void failIfFound(@Nonnull String description, @Nonnull Collection<?> found) { failIfCustomMessageIsSet(); fail(String.format("the map:<%s> contains the %s:<%s>", formattedActual(), description, toStringOf(found))); } private @Nonnull String formattedActual() { return checkNotNull(toStringOf(actual)); } /** * @return the number of elements in the actual {@code Map}. */ @Override protected int actualGroupSize() { isNotNull(); return actual.size(); } /** * An entry in a {@code Map}. * * @author Yvonne Wang */ public static class Entry { final Object key; final Object value; Entry(@Nullable Object key, @Nullable Object value) { this.key = key; this.value = value; } /** * @see java.lang.Object#toString() */ @Override public String toString() { return String.format("%s=%s", quote(key), quote(value)); } } }