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

fr.landel.utils.assertor.utils.AssertorMap Maven / Gradle / Ivy

/*-
 * #%L
 * utils-assertor
 * %%
 * Copyright (C) 2016 - 2018 Gilles Landel
 * %%
 * 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.
 * #L%
 */
package fr.landel.utils.assertor.utils;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.MapUtils;

import fr.landel.utils.assertor.StepAssertor;
import fr.landel.utils.assertor.commons.ConstantsAssertor;
import fr.landel.utils.assertor.commons.MessageAssertor;
import fr.landel.utils.assertor.commons.ParameterAssertor;
import fr.landel.utils.assertor.enums.EnumAnalysisMode;
import fr.landel.utils.assertor.enums.EnumType;
import fr.landel.utils.assertor.helper.HelperAssertor;
import fr.landel.utils.commons.CastUtils;
import fr.landel.utils.commons.MapUtils2;

/**
 * Utility class to prepare the check of {@link Map}
 *
 * @since Aug 10, 2016
 * @author Gilles
 *
 */
public class AssertorMap extends ConstantsAssertor {

    /**
     * Prepare the next step to validate that the {@link Map} size is equal to
     * {@code size}.
     * 
     * 

* precondition: {@link Map} cannot be {@code null} and size cannot be lower * than zero *

* * @param step * the current step * @param size * the size to validate * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor hasSize(final StepAssertor step, final int size, final MessageAssertor message) { final BiPredicate checker = (map, not) -> map.size() == size; return checkSize(step, size, checker, MSG.MAP.SIZE, message); } /** * Prepare the next step to validate that the {@link Map} size is greater * than {@code size}. * *

* precondition: {@link Map} cannot be {@code null} and size cannot be lower * than zero *

* * @param step * the current step * @param size * the size to validate * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor hasSizeGT(final StepAssertor step, final int size, final MessageAssertor message) { final BiPredicate checker = (map, not) -> map.size() > size; return checkSize(step, size, checker, MSG.MAP.SIZE_GT, message); } /** * Prepare the next step to validate that the {@link Map} size is greater * than or equal to {@code size}. * *

* precondition: {@link Map} cannot be {@code null} and size cannot be lower * than zero *

* * @param step * the current step * @param size * the size to validate * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor hasSizeGTE(final StepAssertor step, final int size, final MessageAssertor message) { final BiPredicate checker = (map, not) -> map.size() >= size; return checkSize(step, size, checker, MSG.MAP.SIZE_GTE, message); } /** * Prepare the next step to validate that the {@link Map} size is lower than * {@code size}. * *

* precondition: {@link Map} cannot be {@code null} and size cannot be lower * than zero *

* * @param step * the current step * @param size * the size to validate * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor hasSizeLT(final StepAssertor step, final int size, final MessageAssertor message) { final BiPredicate checker = (map, not) -> map.size() < size; return checkSize(step, size, checker, MSG.MAP.SIZE_LT, message); } /** * Prepare the next step to validate that the {@link Map} size is lower than * or equal to {@code size}. * *

* precondition: {@link Map} cannot be {@code null} and size cannot be lower * than zero *

* * @param step * the current step * @param size * the size to validate * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor hasSizeLTE(final StepAssertor step, final int size, final MessageAssertor message) { final BiPredicate checker = (map, not) -> map.size() <= size; return checkSize(step, size, checker, MSG.MAP.SIZE_LTE, message); } public static , K, V> StepAssertor checkSize(final StepAssertor step, final int size, final BiPredicate checker, final String messageKey, final MessageAssertor message) { final Predicate preChecker = (map) -> size >= 0 && map != null; return new StepAssertor<>(step, preChecker, checker, false, message, messageKey, false, new ParameterAssertor<>(size, EnumType.NUMBER_INTEGER)); } /** * Prepare the next step to validate if the {@link Map} is {@code null} or * empty * *

* precondition: none *

* * @param step * the current step * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor isEmpty(final StepAssertor step, final MessageAssertor message) { final BiPredicate checker = (map, not) -> MapUtils.isEmpty(map); return new StepAssertor<>(step, checker, false, message, MSG.MAP.EMPTY, false); } /** * Prepare the next step to validate if the {@link Map} is NOT {@code null} * and NOT empty * *

* precondition: none *

* * @param step * the current step * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor isNotEmpty(final StepAssertor step, final MessageAssertor message) { final BiPredicate checker = (map, not) -> MapUtils.isNotEmpty(map); return new StepAssertor<>(step, checker, false, message, MSG.MAP.EMPTY, true); } /** * Prepare the next step to validate if all map entries match the predicate. * *

* precondition: {@code map} cannot be {@code null} or empty and * {@code predicate} cannot be {@code null} *

* * @param step * the current step * @param predicate * the predicate used to check each entry * @param message * the message on predicate failed * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor allMatch(final StepAssertor step, final Predicate> predicate, final MessageAssertor message) { return match(step, predicate, true, MSG.MAP.MATCH_ALL, message); } /** * Prepare the next step to validate if any map entry matches the predicate. * *

* precondition: {@code map} cannot be {@code null} or empty and * {@code predicate} cannot be {@code null} *

* * @param step * the current step * @param predicate * the predicate used to check each entry * @param message * the message on predicate failed * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor anyMatch(final StepAssertor step, final Predicate> predicate, final MessageAssertor message) { return match(step, predicate, false, MSG.MAP.MATCH_ANY, message); } private static , K, V> StepAssertor match(final StepAssertor step, final Predicate> predicate, final boolean all, final String messageKey, final MessageAssertor message) { final Predicate preChecker = (map) -> MapUtils.isNotEmpty(map) && predicate != null; final BiPredicate checker = (object, not) -> AssertorMap.match(object, predicate, all, step.getAnalysisMode()); return new StepAssertor<>(step, preChecker, checker, false, message, messageKey, false, new ParameterAssertor<>(predicate, EnumType.UNKNOWN)); } private static boolean match(final Map map, final Predicate> predicate, final boolean all, final EnumAnalysisMode analysisMode) { final Set> entries = map.entrySet(); if (EnumAnalysisMode.STANDARD.equals(analysisMode)) { if (all) { for (final Entry entry : entries) { if (!predicate.test(entry)) { return false; } } return true; } else { for (final Entry entry : entries) { if (predicate.test(entry)) { return true; } } return false; } } else { final Stream> stream; if (EnumAnalysisMode.PARALLEL.equals(analysisMode)) { stream = entries.parallelStream(); } else { stream = entries.stream(); } if (all) { return stream.allMatch(predicate); } else { return stream.anyMatch(predicate); } } } /** * Prepare the next step to validate if the {@link Map} contains all * {@code map} entries * *

* precondition: neither {@link Map} can be {@code null} or empty *

* * @param step * the current step * @param map * the map containing entries to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsAll(final StepAssertor step, final Map map, final MessageAssertor message) { return contains(step, map, MSG.MAP.CONTAINS_MAP_ALL, true, message); } /** * Prepare the next step to validate if the {@link Map} contains all * {@code keys} entries * *

* precondition: neither {@link Map} and {@code keys} can be {@code null} or * empty *

* * @param step * the current step * @param keys * the keys to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsAll(final StepAssertor step, final Iterable keys, final MessageAssertor message) { return contains(step, keys, MSG.MAP.CONTAINS_KEYS_ALL, true, message); } /** * Prepare the next step to validate if the {@link Map} contains all * {@code values} entries * *

* precondition: neither {@link Map} and {@code values} can be {@code null} * or empty *

* * @param step * the current step * @param values * the values to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsAllValues(final StepAssertor step, final Iterable values, final MessageAssertor message) { return containsValues(step, values, MSG.MAP.CONTAINS_VALUES_ALL, true, message); } /** * Prepare the next step to validate if the {@link Map} contains any * {@code map} entries * *

* precondition: neither {@link Map} can be {@code null} or empty *

* * @param step * the current step * @param map * the map containing entries to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsAny(final StepAssertor step, final Map map, final MessageAssertor message) { return contains(step, map, MSG.MAP.CONTAINS_MAP_ANY, false, message); } /** * Prepare the next step to validate if the {@link Map} contains any * {@code keys} entries * *

* precondition: neither {@link Map} and {@code keys} can be {@code null} or * empty *

* * @param step * the current step * @param keys * the keys to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsAny(final StepAssertor step, final Iterable keys, final MessageAssertor message) { return contains(step, keys, MSG.MAP.CONTAINS_KEYS_ANY, false, message); } /** * Prepare the next step to validate if the {@link Map} contains any * {@code values} entries * *

* precondition: neither {@link Map} and {@code values} can be {@code null} * or empty *

* * @param step * the current step * @param values * the values to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsAnyValues(final StepAssertor step, final Iterable values, final MessageAssertor message) { return containsValues(step, values, MSG.MAP.CONTAINS_VALUES_ANY, false, message); } /** * Prepare the next step to validate if the {@link Map} contains the * specified key * *

* precondition: {@link Map} cannot be {@code null} or empty *

* * @param step * the current step * @param key * the key to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor contains(final StepAssertor step, final K key, final MessageAssertor message) { final Predicate preChecker = MapUtils::isNotEmpty; final BiPredicate checker = (map, not) -> map.containsKey(key); return new StepAssertor<>(step, preChecker, checker, false, message, MSG.MAP.CONTAINS_KEY, false, new ParameterAssertor<>(key)); } /** * Prepare the next step to validate if the {@link Map} contains the * specified pair key/value * *

* precondition: {@link Map} cannot be {@code null} or empty *

* * @param step * the current step * @param key * the key to find * @param value * the value to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor contains(final StepAssertor step, final K key, final V value, final MessageAssertor message) { final Predicate preChecker = MapUtils::isNotEmpty; final BiPredicate checker = (map, not) -> AssertorMap.contains(map, key, value); return new StepAssertor<>(step, preChecker, checker, false, message, MSG.MAP.CONTAINS_KEY, false, new ParameterAssertor<>(key), new ParameterAssertor<>(value)); } /** * Prepare the next step to validate if the {@link Map} contains the * specified value * *

* precondition: {@link Map} cannot be {@code null} or empty *

* * @param step * the current step * @param value * the value to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsValue(final StepAssertor step, final V value, final MessageAssertor message) { final Predicate preChecker = MapUtils::isNotEmpty; final BiPredicate checker = (map, not) -> map.containsValue(value); return new StepAssertor<>(step, preChecker, checker, false, message, MSG.MAP.CONTAINS_VALUE, false, new ParameterAssertor<>(value)); } private static , K, V> StepAssertor contains(final StepAssertor step, final Iterable keys, final CharSequence key, final boolean all, final MessageAssertor message) { final Predicate preChecker = (map) -> MapUtils.isNotEmpty(map) && !IterableUtils.isEmpty(keys); final BiPredicate checker = (map, not) -> AssertorMap.contains(map, keys, map::containsKey, all, not, step.getAnalysisMode()); return new StepAssertor<>(step, preChecker, checker, true, message, key, false, new ParameterAssertor<>(keys, EnumType.ITERABLE)); } private static , K, V> StepAssertor containsValues(final StepAssertor step, final Iterable values, final CharSequence key, final boolean all, final MessageAssertor message) { final Predicate preChecker = (map) -> MapUtils.isNotEmpty(map) && !IterableUtils.isEmpty(values); final BiPredicate checker = (map, not) -> AssertorMap.contains(map, values, map::containsValue, all, not, step.getAnalysisMode()); return new StepAssertor<>(step, preChecker, checker, true, message, key, false, new ParameterAssertor<>(values, EnumType.ITERABLE)); } private static , K, V> StepAssertor contains(final StepAssertor step, final Map map, final CharSequence key, final boolean all, final MessageAssertor message) { final Predicate preChecker = (map1) -> MapUtils.isNotEmpty(map1) && MapUtils.isNotEmpty(map); final BiPredicate checker = (map1, not) -> AssertorMap.contains(map1, map, all, not, step.getAnalysisMode()); return new StepAssertor<>(step, preChecker, checker, true, message, key, false, new ParameterAssertor<>(map, EnumType.MAP)); } private static , K, V, T> boolean contains(final M map, final Iterable objects, final Predicate predicate, final boolean all, final boolean not, final EnumAnalysisMode analysisMode) { long found = 0; if (EnumAnalysisMode.STANDARD.equals(analysisMode)) { for (T object : objects) { if (predicate.test(object)) { ++found; } } } else { found = StreamSupport.stream(objects.spliterator(), EnumAnalysisMode.PARALLEL.equals(analysisMode)).filter(predicate).count(); } return HelperAssertor.isValid(all, not, found, IterableUtils.size(objects)); } private static , K, V> boolean contains(final M map, final Map objects, final boolean all, final boolean not, final EnumAnalysisMode analysisMode) { final Set> entries = objects.entrySet(); if (EnumAnalysisMode.STANDARD.equals(analysisMode)) { if (all && !not) { for (final Entry entry : entries) { if (!AssertorMap.contains(map, entry.getKey(), entry.getValue())) { return false; } } return true; } else if (!all) { // any and not any for (final Entry entry : entries) { if (AssertorMap.contains(map, entry.getKey(), entry.getValue())) { return !not; } } return not; } else { // not all long found = 0; for (final Entry entry : entries) { if (AssertorMap.contains(map, entry.getKey(), entry.getValue())) { ++found; } } return HelperAssertor.isValid(all, not, found, entries.size()); } } else { final Stream> stream; if (EnumAnalysisMode.PARALLEL.equals(analysisMode)) { stream = entries.parallelStream(); } else { stream = entries.stream(); } return HelperAssertor.isValid(stream, e -> AssertorMap.contains(map, e.getKey(), e.getValue()), all, not, objects::size); } } private static , K, V> boolean contains(final M map, final K key, final V value) { if (map.containsKey(key)) { V val = map.get(key); if (val != null) { return val.equals(value); } else { return value == null; } } return false; } /** * Prepare the next step to validate if the {@link Map} contains the entries * in a specified order. To work correctly, the map must be sorted or * linked. * *

* precondition: {@link Map} and {@link Iterable} cannot be {@code null} or * empty *

* * @param step * the current step * @param keys * the keys to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsKeysInOrder(final StepAssertor step, final Iterable keys, final MessageAssertor message) { final Predicate preChecker = map1 -> MapUtils.isNotEmpty(map1) && !IterableUtils.isEmpty(keys); final BiPredicate checker = (map1, not) -> AssertorMap.hasInOrder(map1, keys, not, step.getAnalysisMode(), MapUtils2::areKeysEqual, CastUtils.cast(Object.class)); return new StepAssertor<>(step, preChecker, checker, true, message, MSG.MAP.CONTAINS_KEYS_IN_ORDER, false, new ParameterAssertor<>(keys, EnumType.ITERABLE)); } /** * Prepare the next step to validate if the {@link Map} contains the entries * in a specified order. To work correctly, the map must be sorted or * linked. * *

* precondition: {@link Map} and {@link Iterable} cannot be {@code null} or * empty *

* * @param step * the current step * @param values * the values to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsValuesInOrder(final StepAssertor step, final Iterable values, final MessageAssertor message) { final Predicate preChecker = map1 -> MapUtils.isNotEmpty(map1) && !IterableUtils.isEmpty(values); final BiPredicate checker = (map1, not) -> AssertorMap.hasInOrder(map1, values, not, step.getAnalysisMode(), MapUtils2::areValuesEqual, CastUtils.cast(Object.class)); return new StepAssertor<>(step, preChecker, checker, true, message, MSG.MAP.CONTAINS_VALUES_IN_ORDER, false, new ParameterAssertor<>(values, EnumType.ITERABLE)); } /** * Prepare the next step to validate if the {@link Map} contains the entries * in a specified order. To work correctly, the map must be sorted or * linked. * *

* precondition: {@link Map} cannot be {@code null} or empty *

* * @param step * the current step * @param map * the map entries to find * @param message * the message if invalid * @param * the {@link Map} type * @param * the {@link Map} key elements type * @param * the {@link Map} value elements type * @return the next step */ public static , K, V> StepAssertor containsInOrder(final StepAssertor step, final Map map, final MessageAssertor message) { final Predicate preChecker = map1 -> MapUtils.isNotEmpty(map1) && MapUtils.isNotEmpty(map); final BiPredicate checker = (map1, not) -> AssertorMap.hasInOrder(map1, IterableUtils.toList(map.entrySet()), not, step.getAnalysisMode(), MapUtils2::areEntriesEqual, CastUtils.cast(Entry.class)); return new StepAssertor<>(step, preChecker, checker, true, message, MSG.MAP.CONTAINS_MAP_IN_ORDER, false, new ParameterAssertor<>(map, EnumType.MAP)); } private static , K, V, T> boolean hasInOrder(final M map, final Iterable objects, final boolean not, final EnumAnalysisMode analysisMode, final BiPredicate, T> entriesEqualChecker, final Class objectsClass) { int found = 0; final int size1 = map.size(); final int size2 = IterableUtils.size(objects); if (size1 < size2) { return not; } final Set> entries1 = map.entrySet(); final List entries2 = IterableUtils.toList(objects); if (EnumAnalysisMode.STANDARD.equals(analysisMode)) { for (Entry entry1 : entries1) { if (found < size2) { if (entriesEqualChecker.test(entry1, entries2.get(found))) { ++found; } else if (found > 0) { found = 0; } } } } else { final AtomicInteger count = new AtomicInteger(0); final Stream> stream; if (EnumAnalysisMode.PARALLEL.equals(analysisMode)) { stream = entries1.parallelStream(); } else { stream = entries1.stream(); } stream.forEachOrdered(o -> { int inc = count.get(); if (inc < size2) { if (entriesEqualChecker.test(o, entries2.get(inc))) { count.incrementAndGet(); } else if (inc > 0) { count.set(0); } } }); found = count.get(); } return not ^ (found == size2); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy