Skip to content

Commit

Permalink
GH-995 - Allow filtering violations.
Browse files Browse the repository at this point in the history
  • Loading branch information
odrotbohm committed Dec 18, 2024
1 parent f1ba949 commit dca73ee
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;

Expand Down Expand Up @@ -57,7 +58,7 @@ private Violations(List<Violation> violations) {
* @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());
}

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

return violations.stream() //
.map(Violation::message) //
.map(Violation::getMessage) //
.collect(Collectors.joining("\n- ", "- ", ""));
}

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

return violations.stream() //
.map(Violation::message)
.map(Violation::getMessage)
.toList();
}

Expand All @@ -104,6 +105,21 @@ public void throwIfPresent() {
}
}

/**
* 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?
*
Expand Down Expand Up @@ -142,14 +158,16 @@ private List<Violation> unionByMessage(List<Violation> left, List<Violation> rig

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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,14 @@ void deduplicatesViolationsWithTheSameMessage() {
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");
}
}

0 comments on commit dca73ee

Please sign in to comment.