diff --git a/src/main/java/am/ik/yavi/constraint/CollectionConstraint.java b/src/main/java/am/ik/yavi/constraint/CollectionConstraint.java index d208a0b5..7d374078 100644 --- a/src/main/java/am/ik/yavi/constraint/CollectionConstraint.java +++ b/src/main/java/am/ik/yavi/constraint/CollectionConstraint.java @@ -29,6 +29,7 @@ import static am.ik.yavi.core.NullAs.VALID; import static am.ik.yavi.core.ViolationMessage.Default.COLLECTION_CONTAINS; import static am.ik.yavi.core.ViolationMessage.Default.COLLECTION_UNIQUE; +import static am.ik.yavi.core.ViolationMessage.Default.COLLECTION_CONTAINS_ALL; public class CollectionConstraint, E> extends ContainerConstraintBase> { @@ -69,6 +70,23 @@ public CollectionConstraint unique() { return this; } + public CollectionConstraint containsAll(Collection values) { + this.predicates().add(ConstraintPredicate.withViolatedValue(collection -> { + final Set missingValues = new HashSet<>(values); + + if (collection instanceof Set) { + missingValues.removeAll(collection); + } + else { + missingValues.removeAll(new HashSet<>(collection)); + } + + return missingValues.isEmpty() ? Optional.empty() : Optional.of(new ViolatedValue(missingValues)); + }, COLLECTION_CONTAINS_ALL, () -> new Object[] { values.toString() }, VALID)); + + return this; + } + @Override protected ToIntFunction size() { return Collection::size; diff --git a/src/main/java/am/ik/yavi/core/ViolationMessage.java b/src/main/java/am/ik/yavi/core/ViolationMessage.java index 57d459fc..a365a2d3 100644 --- a/src/main/java/am/ik/yavi/core/ViolationMessage.java +++ b/src/main/java/am/ik/yavi/core/ViolationMessage.java @@ -94,6 +94,8 @@ enum Default implements ViolationMessage { BYTE_SIZE_FIXED_SIZE("byteSize.fixedSize", "The byte size of \"{0}\" must be {1}. The given size is {2}"), // COLLECTION_CONTAINS("collection.contains", "\"{0}\" must contain {1}"), // COLLECTION_UNIQUE("collection.unique", "\"{0}\" must be unique. {1} is/are duplicated."), // + COLLECTION_CONTAINS_ALL("collection.containsAll", + "\"{0}\" must be have of all of the following values: {1}, missing values: {2}"), // MAP_CONTAINS_VALUE("map.containsValue", "\"{0}\" must contain value {1}"), // MAP_CONTAINS_KEY("map.containsKey", "\"{0}\" must contain key {1}"), // ARRAY_CONTAINS("array.contains", "\"{0}\" must contain {1}"), // diff --git a/src/test/java/am/ik/yavi/constraint/CollectionConstraintTest.java b/src/test/java/am/ik/yavi/constraint/CollectionConstraintTest.java index f26451a7..2a592a86 100644 --- a/src/test/java/am/ik/yavi/constraint/CollectionConstraintTest.java +++ b/src/test/java/am/ik/yavi/constraint/CollectionConstraintTest.java @@ -86,6 +86,33 @@ void unique() { assertThat(predicate.test(Arrays.asList("a", "b", "c", "b"))).isFalse(); } + @Test + void containsAll() { + List mustVisitCities = Arrays.asList("a", "b", "c"); + Predicate> predicate = retrievePredicate(c -> c.containsAll(mustVisitCities)); + + List visitingCities = Arrays.asList("a", "b", "c", "d"); + assertThat(predicate.test(visitingCities)).isTrue(); + + visitingCities = Arrays.asList("a", "b", "c"); + assertThat(predicate.test(visitingCities)).isTrue(); + + visitingCities = Arrays.asList("a", "b"); + assertThat(predicate.test(visitingCities)).isFalse(); + + visitingCities = Arrays.asList("a"); + assertThat(predicate.test(visitingCities)).isFalse(); + + visitingCities = Arrays.asList(); + assertThat(predicate.test(visitingCities)).isFalse(); + + visitingCities = Arrays.asList("a", "b", "d"); + assertThat(predicate.test(visitingCities)).isFalse(); + + visitingCities = Arrays.asList("x", "y"); + assertThat(predicate.test(visitingCities)).isFalse(); + } + private static Predicate> retrievePredicate( Function, List, String>, CollectionConstraint, List, String>> constraint) { return constraint.apply(new CollectionConstraint<>()).predicates().peekFirst().predicate();