GH-995 - Allow filtering violations.
This commit is contained in:
@@ -40,7 +40,6 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.modulith.core.Types.JMoleculesTypes;
|
||||
import org.springframework.modulith.core.Types.JavaTypes;
|
||||
import org.springframework.modulith.core.Types.SpringTypes;
|
||||
import org.springframework.modulith.core.Violations.Violation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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.springframework.modulith.core;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An individual architectural violation.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @since 1.3.1
|
||||
*/
|
||||
public class Violation {
|
||||
|
||||
final String message;
|
||||
|
||||
Violation(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the violation message.
|
||||
*
|
||||
* @return the message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the {@link Violation}'s message contains the given candidate.
|
||||
*
|
||||
* @param candidate must not be {@literal null} or empty.
|
||||
*/
|
||||
public boolean hasMessageContaining(String candidate) {
|
||||
|
||||
Assert.hasText(candidate, "Candidate must not be null or empty!");
|
||||
|
||||
return message.contains(candidate);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
return this == obj
|
||||
|| obj instanceof Violation that
|
||||
&& Objects.equals(this.message, that.message);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(message);
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import static java.util.stream.Collectors.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -57,7 +58,7 @@ public class Violations extends RuntimeException {
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
static Collector<String, ?, Violations> toViolations() {
|
||||
return mapping(Violation::new, collectingAndThen(Collectors.toList(), Violations::new));
|
||||
return mapping(Violation::new, newViolations());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -68,7 +69,7 @@ public class Violations extends RuntimeException {
|
||||
public String getMessage() {
|
||||
|
||||
return violations.stream() //
|
||||
.map(Violation::message) //
|
||||
.map(Violation::getMessage) //
|
||||
.collect(Collectors.joining("\n- ", "- ", ""));
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ public class Violations extends RuntimeException {
|
||||
public List<String> getMessages() {
|
||||
|
||||
return violations.stream() //
|
||||
.map(Violation::message)
|
||||
.map(Violation::getMessage)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -104,6 +105,21 @@ public class Violations extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link Violations} that match the given {@link Predicate}.
|
||||
*
|
||||
* @param filter must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public Violations filter(Predicate<Violation> filter) {
|
||||
|
||||
Assert.notNull(filter, "Filter must not be null!");
|
||||
|
||||
return violations.stream()
|
||||
.filter(filter)
|
||||
.collect(newViolations());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Violations} with the given {@link RuntimeException} added to the current ones?
|
||||
*
|
||||
@@ -142,14 +158,16 @@ public class Violations extends RuntimeException {
|
||||
|
||||
var result = new ArrayList<>(left);
|
||||
|
||||
var messages = left.stream().map(Violation::message).toList();
|
||||
var messages = left.stream().map(Violation::getMessage).toList();
|
||||
|
||||
right.stream()
|
||||
.filter(it -> !messages.contains(it.message()))
|
||||
.filter(it -> !messages.contains(it.message))
|
||||
.forEach(result::add);
|
||||
|
||||
return result.size() == left.size() ? left : result;
|
||||
}
|
||||
|
||||
static record Violation(String message) {}
|
||||
private static Collector<Violation, ?, Violations> newViolations() {
|
||||
return collectingAndThen(Collectors.toList(), Violations::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,14 @@ class ViolationsUnitTests {
|
||||
assertThat(violations.getMessages())
|
||||
.containsExactlyInAnyOrder("First", "Second", "Third");
|
||||
}
|
||||
|
||||
@Test // GH-995
|
||||
void allowsFilteringViolations() {
|
||||
|
||||
var violations = Violations.NONE.and("First").and("Second")
|
||||
.filter(it -> it.hasMessageContaining("Sec"));
|
||||
|
||||
assertThat(violations.getMessages())
|
||||
.containsExactly("Second");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user