Skip to content

Commit 0c6d42d

Browse files
committed
GH-995 - Allow filtering violations.
1 parent f1ba949 commit 0c6d42d

File tree

4 files changed

+120
-7
lines changed

4 files changed

+120
-7
lines changed

spring-modulith-core/src/main/java/org/springframework/modulith/core/ApplicationModule.java

-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import org.springframework.modulith.core.Types.JMoleculesTypes;
4141
import org.springframework.modulith.core.Types.JavaTypes;
4242
import org.springframework.modulith.core.Types.SpringTypes;
43-
import org.springframework.modulith.core.Violations.Violation;
4443
import org.springframework.util.Assert;
4544
import org.springframework.util.StringUtils;
4645
import org.springframework.util.function.SingletonSupplier;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.modulith.core;
17+
18+
import java.util.Objects;
19+
20+
import org.springframework.util.Assert;
21+
22+
/**
23+
* An individual architectural violation.
24+
*
25+
* @author Oliver Drotbohm
26+
* @since 1.3.1
27+
*/
28+
public class Violation {
29+
30+
final String message;
31+
32+
Violation(String message) {
33+
this.message = message;
34+
}
35+
36+
/**
37+
* Returns the violation message.
38+
*
39+
* @return the message
40+
*/
41+
public String getMessage() {
42+
return message;
43+
}
44+
45+
/**
46+
* Returns whether the {@link Violation}'s message contains the given candidate.
47+
*
48+
* @param candidate must not be {@literal null} or empty.
49+
*/
50+
public boolean hasMessageContaining(String candidate) {
51+
52+
Assert.hasText(candidate, "Candidate must not be null or empty!");
53+
54+
return message.contains(candidate);
55+
}
56+
57+
/*
58+
* (non-Javadoc)
59+
* @see java.lang.Object#toString()
60+
*/
61+
@Override
62+
public String toString() {
63+
return message;
64+
}
65+
66+
/*
67+
* (non-Javadoc)
68+
* @see java.lang.Object#equals(java.lang.Object)
69+
*/
70+
@Override
71+
public boolean equals(Object obj) {
72+
73+
return this == obj
74+
|| obj instanceof Violation that
75+
&& Objects.equals(this.message, that.message);
76+
}
77+
78+
/*
79+
* (non-Javadoc)
80+
* @see java.lang.Object#hashCode()
81+
*/
82+
@Override
83+
public int hashCode() {
84+
return Objects.hashCode(message);
85+
}
86+
}

spring-modulith-core/src/main/java/org/springframework/modulith/core/Violations.java

+24-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.ArrayList;
2121
import java.util.Collections;
2222
import java.util.List;
23+
import java.util.function.Predicate;
2324
import java.util.stream.Collector;
2425
import java.util.stream.Collectors;
2526

@@ -57,7 +58,7 @@ private Violations(List<Violation> violations) {
5758
* @return will never be {@literal null}.
5859
*/
5960
static Collector<String, ?, Violations> toViolations() {
60-
return mapping(Violation::new, collectingAndThen(Collectors.toList(), Violations::new));
61+
return mapping(Violation::new, newViolations());
6162
}
6263

6364
/*
@@ -68,7 +69,7 @@ private Violations(List<Violation> violations) {
6869
public String getMessage() {
6970

7071
return violations.stream() //
71-
.map(Violation::message) //
72+
.map(Violation::getMessage) //
7273
.collect(Collectors.joining("\n- ", "- ", ""));
7374
}
7475

@@ -81,7 +82,7 @@ public String getMessage() {
8182
public List<String> getMessages() {
8283

8384
return violations.stream() //
84-
.map(Violation::message)
85+
.map(Violation::getMessage)
8586
.toList();
8687
}
8788

@@ -104,6 +105,21 @@ public void throwIfPresent() {
104105
}
105106
}
106107

108+
/**
109+
* Returns {@link Violations} that match the given {@link Predicate}.
110+
*
111+
* @param violation must not be {@literal null}.
112+
* @return
113+
*/
114+
public Violations filter(Predicate<Violation> filter) {
115+
116+
Assert.notNull(filter, "Filter must not be null!");
117+
118+
return violations.stream()
119+
.filter(filter)
120+
.collect(newViolations());
121+
}
122+
107123
/**
108124
* Creates a new {@link Violations} with the given {@link RuntimeException} added to the current ones?
109125
*
@@ -142,14 +158,16 @@ private List<Violation> unionByMessage(List<Violation> left, List<Violation> rig
142158

143159
var result = new ArrayList<>(left);
144160

145-
var messages = left.stream().map(Violation::message).toList();
161+
var messages = left.stream().map(Violation::getMessage).toList();
146162

147163
right.stream()
148-
.filter(it -> !messages.contains(it.message()))
164+
.filter(it -> !messages.contains(it.message))
149165
.forEach(result::add);
150166

151167
return result.size() == left.size() ? left : result;
152168
}
153169

154-
static record Violation(String message) {}
170+
private static Collector<Violation, ?, Violations> newViolations() {
171+
return collectingAndThen(Collectors.toList(), Violations::new);
172+
}
155173
}

spring-modulith-core/src/test/java/org/springframework/modulith/core/ViolationsUnitTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,14 @@ void deduplicatesViolationsWithTheSameMessage() {
5151
assertThat(violations.getMessages())
5252
.containsExactlyInAnyOrder("First", "Second", "Third");
5353
}
54+
55+
@Test // GH-995
56+
void allowsFilteringViolations() {
57+
58+
var violations = Violations.NONE.and("First").and("Second")
59+
.filter(it -> it.hasMessageContaining("Sec"));
60+
61+
assertThat(violations.getMessages())
62+
.containsExactly("Second");
63+
}
5464
}

0 commit comments

Comments
 (0)