All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.amygdalum.extensions.hamcrest.collections.MapMatcher Maven / Gradle / Ivy
package net.amygdalum.extensions.hamcrest.collections;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.nullValue;
import java.util.AbstractMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.hamcrest.TypeSafeMatcher;
import org.hamcrest.core.IsNull;
public class MapMatcher extends TypeSafeMatcher>{
private Class key;
private Class value;
private boolean atLeast;
private Map,Matcher> entries;
public MapMatcher(Class key, Class value) {
this.key = key;
this.value = value;
this.entries = new LinkedHashMap<>();
}
public MapMatcher atLeast() {
atLeast = true;
return this;
}
public MapMatcher entry(K key, V value) {
return entry(matchKey(key), matchValue(value));
}
public MapMatcher entry(Matcher key, V value) {
return entry(key, matchValue(value));
}
public MapMatcher entry(K key, Matcher value) {
return entry(matchKey(key), value);
}
public MapMatcher entry(Matcher key, Matcher value) {
entries.put(key, value);
return this;
}
@SuppressWarnings("unchecked")
private Matcher matchKey(K element) {
if (element == null) {
return nullValue(key);
} else if (element instanceof Matcher>) {
return (Matcher) element;
} else {
return equalTo(element);
}
}
@SuppressWarnings("unchecked")
private Matcher matchValue(V element) {
if (element == null) {
return nullValue(value);
} else if (element instanceof Matcher>) {
return (Matcher) element;
} else {
return equalTo(element);
}
}
@Override
public void describeTo(Description description) {
description.appendValue(entries);
}
@Override
protected void describeMismatchSafely(Map item, Description mismatchDescription) {
List, Matcher>> unmatched = new LinkedList<>(entries.entrySet());
List> notfound = new LinkedList<>();
for (Entry entry : item.entrySet()) {
boolean success = tryMatch(unmatched, entry);
if (!success) {
notfound.add(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue()));
}
}
if (!unmatched.isEmpty()) {
mismatchDescription.appendText("missing entries ").appendValue(toMap(unmatched));
}
if (!atLeast && !unmatched.isEmpty() && !notfound.isEmpty()) {
mismatchDescription.appendText(", ");
}
if (!atLeast && !notfound.isEmpty()) {
mismatchDescription.appendText("unmatched entries ").appendValue(toDescriptionMap(notfound));
}
}
private Map, Matcher> toMap(List, Matcher>> entries) {
Map, Matcher> map = new LinkedHashMap<>();
for (Entry, Matcher> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
private Map toDescriptionMap(List> entries) {
Matcher keyMatcher = bestKeyMatcher();
Matcher valueMatcher = bestValueMatcher();
Map map = new LinkedHashMap<>();
for (Entry entry : entries) {
String key = descriptionOf(keyMatcher, entry.getKey());
String value = descriptionOf(valueMatcher, entry.getValue());
map.put(key, value);
}
return map;
}
private Matcher bestValueMatcher() {
for (Matcher matcher : entries.values()) {
if (matcher.getClass() != IsNull.class) {
return matcher;
}
}
return equalTo(null);
}
private Matcher bestKeyMatcher() {
for (Matcher matcher : entries.keySet()) {
if (matcher.getClass() != IsNull.class) {
return matcher;
}
}
return equalTo(null);
}
private String descriptionOf(Matcher valueMatcher, T value) {
StringDescription description = new StringDescription();
valueMatcher.describeMismatch(value, description);
return description.toString();
}
@Override
protected boolean matchesSafely(Map item) {
List, Matcher>> unmatched = new LinkedList<>(entries.entrySet());
for (Entry entry : item.entrySet()) {
boolean success = tryMatch(unmatched, entry);
if (!success && !atLeast) {
return false;
}
}
return unmatched.isEmpty();
}
private boolean tryMatch(List, Matcher>> unmatched, Entry entry) {
K key = entry.getKey();
V value = entry.getValue();
Iterator, Matcher>> matchers = unmatched.iterator();
while (matchers.hasNext()) {
Entry, Matcher> matcher = matchers.next();
if (matcher.getKey().matches(key) && matcher.getValue().matches(value)) {
matchers.remove();
return true;
}
}
return false;
}
public static MapMatcher noEntries(Class key, Class value) {
return new MapMatcher<>(key, value);
}
public static MapMatcher containsEntries(Class key, Class value) {
return new MapMatcher<>(key, value);
}
}