All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.axonframework.test.matchers.MapEntryMatcher Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2023. Axon Framework
 *
 * 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.
 */

package org.axonframework.test.matchers;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import java.util.HashMap;
import java.util.Map;

import static java.util.Collections.unmodifiableMap;
import static org.axonframework.test.matchers.EqualsMatcher.equalTo;

/**
 * Matcher that will match an Object if that object is a {@link Map} of which all
 * keys-values pairs are equal to pairs of the expected instance.
 *
 * @author bliessens
 * @since 3.3
 */
public class MapEntryMatcher extends TypeSafeMatcher> {

    private final Map, Matcher> matchers = new HashMap<>();
    private final Map expectedEntries;

    private final Map additionalEntries = new HashMap<>();
    private final Map missingEntries = new HashMap<>();

    public MapEntryMatcher(Map expectedMap) {
        this.expectedEntries = new HashMap<>(expectedMap);
        for (Map.Entry entry : expectedMap.entrySet()) {
            this.matchers.put(equalTo(entry.getKey()), equalTo(entry.getValue()));
        }
    }

    @Override
    protected boolean matchesSafely(Map actualMap) {
        additionalEntries.clear();
        missingEntries.clear();
        final Matching> matching = new Matching(matchers);
        for (Map.Entry item : actualMap.entrySet()) {
            if (!matching.matches(item)) {
                additionalEntries.put(item.getKey(), item.getValue());
            }
        }
        if (!matching.isFinished(actualMap)) {
            for (Map.Entry item : expectedEntries.entrySet()) {
                if (matching.matches(item)) {
                    missingEntries.put(item.getKey(), item.getValue());
                }
            }
            return false;
        }
        return additionalEntries.isEmpty();
    }

    public Map getAdditionalEntries() {
        return unmodifiableMap(additionalEntries);
    }

    public Map getMissingEntries() {
        return unmodifiableMap(missingEntries);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("map containing ").appendValueList("[", ",", "]", expectedEntries.entrySet());
    }

    private static class Matching {
        private final Map, Matcher> matchers;

        public Matching(Map, Matcher> matchers) {
            this.matchers = new HashMap(matchers);
        }

        public boolean matches(Map.Entry item) {
            if (matchers.isEmpty()) {
                return false;
            }
            for (Map.Entry, Matcher> matcherEntry : matchers.entrySet()) {

                if (matcherEntry.getKey().matches(item.getKey()) && matcherEntry.getValue().matches(item.getValue())) {
                    matchers.remove(matcherEntry.getKey());
                    return true;
                }
            }
            return false;
        }

        public boolean isFinished(Map items) {
            return matchers.isEmpty();
        }

    }
}