001    /*
002     * Created on Dec 21, 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.internal;
016    
017    import static org.fest.assertions.error.ShouldNotContain.shouldNotContain;
018    import static org.fest.assertions.error.ShouldContain.shouldContain;
019    import static org.fest.assertions.error.ShouldHaveSize.shouldHaveSize;
020    import static org.fest.assertions.error.ShouldNotBeEmpty.shouldNotBeEmpty;
021    import static org.fest.assertions.error.ShouldBeEmpty.shouldBeEmpty;
022    import static org.fest.assertions.error.ShouldBeNullOrEmpty.shouldBeNullOrEmpty;
023    import static org.fest.util.Objects.areEqual;
024    
025    import java.util.*;
026    
027    import org.fest.assertions.core.AssertionInfo;
028    import org.fest.assertions.data.MapEntry;
029    import org.fest.util.VisibleForTesting;
030    
031    /**
032     * Reusable assertions for <code>{@link Map}</code>s.
033     *
034     * @author Alex Ruiz
035     */
036    public class Maps {
037    
038      private static Maps INSTANCE = new Maps();
039    
040      /**
041       * Returns the singleton instance of this class.
042       * @return the singleton instance of this class.
043       */
044      public static Maps instance() {
045        return INSTANCE ;
046      }
047    
048      @VisibleForTesting Failures failures = Failures.instance();
049    
050      @VisibleForTesting Maps() {}
051    
052      /**
053       * Asserts that the given {@code Map} is {@code null} or empty.
054       * @param info contains information about the assertion.
055       * @param actual the given map.
056       * @throws AssertionError if the given {@code Map} is not {@code null} *and* contains one or more entries.
057       */
058      public void assertNullOrEmpty(AssertionInfo info, Map<?, ?> actual) {
059        if (actual == null || actual.isEmpty()) return;
060        throw failures.failure(info, shouldBeNullOrEmpty(actual));
061      }
062    
063      /**
064       * Asserts that the given {@code Map} is empty.
065       * @param info contains information about the assertion.
066       * @param actual the given {@code Map}.
067       * @throws AssertionError if the given {@code Map} is {@code null}.
068       * @throws AssertionError if the given {@code Map} is not empty.
069       */
070      public void assertEmpty(AssertionInfo info, Map<?, ?> actual) {
071        assertNotNull(info, actual);
072        if (actual.isEmpty()) return;
073        throw failures.failure(info, shouldBeEmpty(actual));
074      }
075    
076      /**
077       * Asserts that the given {@code Map} is not empty.
078       * @param info contains information about the assertion.
079       * @param actual the given {@code Map}.
080       * @throws AssertionError if the given {@code Map} is {@code null}.
081       * @throws AssertionError if the given {@code Map} is empty.
082       */
083      public void assertNotEmpty(AssertionInfo info, Map<?, ?> actual) {
084        assertNotNull(info, actual);
085        if (!actual.isEmpty()) return;
086        throw failures.failure(info, shouldNotBeEmpty());
087      }
088    
089      /**
090       * Asserts that the number of entries in the given {@code Map} is equal to the expected one.
091       * @param info contains information about the assertion.
092       * @param actual the given {@code Map}.
093       * @param expectedSize the expected size of {@code actual}.
094       * @throws AssertionError if the given {@code Map} is {@code null}.
095       * @throws AssertionError if the number of entries in the given {@code Map} is different than the expected one.
096       */
097      public void assertHasSize(AssertionInfo info, Map<?, ?> actual, int expectedSize) {
098        assertNotNull(info, actual);
099        int sizeOfActual = actual.size();
100        if (sizeOfActual == expectedSize) return;
101        throw failures.failure(info, shouldHaveSize(actual, sizeOfActual, expectedSize));
102      }
103    
104      /**
105       * Asserts that the given {@code Map} contains the given entries, in any order.
106       * @param info contains information about the assertion.
107       * @param actual the given {@code Map}.
108       * @param entries the entries that are expected to be in the given {@code Map}.
109       * @throws NullPointerException if the array of entries is {@code null}.
110       * @throws IllegalArgumentException if the array of entries is empty.
111       * @throws NullPointerException if any of the entries in the given array is {@code null}.
112       * @throws AssertionError if the given {@code Map} is {@code null}.
113       * @throws AssertionError if the given {@code Map} does not contain the given entries.
114       */
115      public void assertContains(AssertionInfo info, Map<?, ?> actual, MapEntry[] entries) {
116        isNotEmptyOrNull(entries);
117        assertNotNull(info, actual);
118        Set<MapEntry> notFound = new LinkedHashSet<MapEntry>();
119        for (MapEntry entry : entries) if (!containsEntry(actual, entry)) notFound.add(entry);
120        if (notFound.isEmpty()) return;
121        throw failures.failure(info, shouldContain(actual, entries, notFound));
122      }
123    
124      /**
125       * Asserts that the given {@code Map} does not contain the given entries.
126       * @param info contains information about the assertion.
127       * @param actual the given {@code Map}.
128       * @param entries the entries that are expected to be in the given {@code Map}.
129       * @throws NullPointerException if the array of entries is {@code null}.
130       * @throws IllegalArgumentException if the array of entries is empty.
131       * @throws NullPointerException if any of the entries in the given array is {@code null}.
132       * @throws AssertionError if the given {@code Map} is {@code null}.
133       * @throws AssertionError if the given {@code Map} contains any of the given entries.
134       */
135      public void assertDoesNotContain(AssertionInfo info, Map<?, ?> actual, MapEntry[] entries) {
136        isNotEmptyOrNull(entries);
137        assertNotNull(info, actual);
138        Set<MapEntry> found = new LinkedHashSet<MapEntry>();
139        for (MapEntry entry : entries) if (containsEntry(actual, entry)) found.add(entry);
140        if (found.isEmpty()) return;
141        throw failures.failure(info, shouldNotContain(actual, entries, found));
142      }
143    
144      private void isNotEmptyOrNull(MapEntry[] entries) {
145        if (entries == null) throw new NullPointerException("The array of entries to look for should not be null");
146        if (entries.length == 0) throw new IllegalArgumentException("The array of entries to look for should not be empty");
147      }
148    
149      private boolean containsEntry(Map<?, ?> actual, MapEntry entry) {
150        if (entry == null) throw new NullPointerException("Entries to look for should not be null");
151        if (!actual.containsKey(entry.key)) return false;
152        return areEqual(actual.get(entry.key), entry.value);
153      }
154    
155      private void assertNotNull(AssertionInfo info, Map<?, ?> actual) {
156        Objects.instance().assertNotNull(info, actual);
157      }
158    }