Skip to content

Commit babfa5f

Browse files
committed
Add (not)haveFullyQualifiedNameAnyOf to API
Signed-off-by: Per Lundberg <[email protected]>
1 parent c09534c commit babfa5f

File tree

10 files changed

+170
-1
lines changed

10 files changed

+170
-1
lines changed

archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.tngtech.archunit.PublicAPI;
2323
import com.tngtech.archunit.base.ChainableFunction;
2424
import com.tngtech.archunit.base.DescribedPredicate;
25+
import com.tngtech.archunit.core.domain.Formatters;
2526

2627
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
2728
import static com.tngtech.archunit.core.domain.properties.HasName.Utils.namesOf;
@@ -117,6 +118,11 @@ public static DescribedPredicate<HasName> name(String name) {
117118
return new NameEqualsPredicate(name);
118119
}
119120

121+
@PublicAPI(usage = ACCESS)
122+
public static DescribedPredicate<HasName> nameAnyOf(String... classNames) {
123+
return new NameEqualsAnyOfPredicate(classNames);
124+
}
125+
120126
/**
121127
* Matches names against a regular expression.
122128
*/
@@ -154,6 +160,26 @@ public boolean test(HasName input) {
154160
}
155161
}
156162

163+
private static class NameEqualsAnyOfPredicate extends DescribedPredicate<HasName> {
164+
private final String[] names;
165+
166+
NameEqualsAnyOfPredicate(String[] names) {
167+
super(String.format("name '%s'", Formatters.joinSingleQuoted(names)));
168+
this.names = names;
169+
}
170+
171+
@Override
172+
public boolean test(HasName input) {
173+
for (String name : names) {
174+
if (input.getName().equals(name)) {
175+
return true;
176+
}
177+
}
178+
179+
return false;
180+
}
181+
}
182+
157183
private static class NameMatchingPredicate extends DescribedPredicate<HasName> {
158184
private final Pattern pattern;
159185

archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName;
117117
import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching;
118118
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
119+
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameAnyOf;
119120
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining;
120121
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameEndingWith;
121122
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching;
@@ -518,6 +519,22 @@ public static ArchCondition<JavaClass> notHaveFullyQualifiedName(String name) {
518519
return not(haveFullyQualifiedName(name));
519520
}
520521

522+
@PublicAPI(usage = ACCESS)
523+
public static ArchCondition<JavaClass> haveFullyQualifiedNameAnyOf(String... classNames) {
524+
return have(fullyQualifiedNameAnyOf(classNames));
525+
}
526+
527+
@Internal
528+
public static DescribedPredicate<HasName> fullyQualifiedNameAnyOf(String[] classNames) {
529+
DescribedPredicate<HasName> predicate = nameAnyOf(classNames);
530+
return predicate.as("fully qualified " + predicate.getDescription());
531+
}
532+
533+
@PublicAPI(usage = ACCESS)
534+
public static ArchCondition<JavaClass> notHaveFullyQualifiedNameAnyOf(String... classNames) {
535+
return not(haveFullyQualifiedNameAnyOf(classNames));
536+
}
537+
521538
@PublicAPI(usage = ACCESS)
522539
public static ArchCondition<JavaClass> haveSimpleName(String name) {
523540
return have(simpleName(name));

archunit/src/main/java/com/tngtech/archunit/lang/syntax/ClassesThatInternal.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,16 @@ public CONJUNCTION doNotHaveFullyQualifiedName(String name) {
430430
return givenWith(SyntaxPredicates.doNotHaveFullyQualifiedName(name));
431431
}
432432

433+
@Override
434+
public CONJUNCTION haveFullyQualifiedNameAnyOf(String... classNames) {
435+
return givenWith(SyntaxPredicates.haveFullyQualifiedNameAnyOf(classNames));
436+
}
437+
438+
@Override
439+
public CONJUNCTION doNotHaveFullyQualifiedNameAnyOf(String... classNames) {
440+
return givenWith(SyntaxPredicates.doNotHaveFullyQualifiedNameAnyOf(classNames));
441+
}
442+
433443
@Override
434444
public CONJUNCTION haveSimpleName(String name) {
435445
return givenWith(SyntaxPredicates.haveSimpleName(name));

archunit/src/main/java/com/tngtech/archunit/lang/syntax/MembersDeclaredInClassesThat.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ public CONJUNCTION doNotHaveFullyQualifiedName(String name) {
7272
return givenWith(SyntaxPredicates.doNotHaveFullyQualifiedName(name));
7373
}
7474

75+
@Override
76+
public CONJUNCTION haveFullyQualifiedNameAnyOf(String... classNames) {
77+
return givenWith(SyntaxPredicates.haveFullyQualifiedNameAnyOf(classNames));
78+
}
79+
80+
@Override
81+
public CONJUNCTION doNotHaveFullyQualifiedNameAnyOf(String... classNames) {
82+
return givenWith(SyntaxPredicates.doNotHaveFullyQualifiedNameAnyOf(classNames));
83+
}
84+
7585
@Override
7686
public CONJUNCTION haveSimpleName(String name) {
7787
return givenWith(SyntaxPredicates.haveSimpleName(name));

archunit/src/main/java/com/tngtech/archunit/lang/syntax/SyntaxPredicates.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier;
3636
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching;
3737
import static com.tngtech.archunit.lang.conditions.ArchConditions.fullyQualifiedName;
38+
import static com.tngtech.archunit.lang.conditions.ArchConditions.fullyQualifiedNameAnyOf;
3839
import static com.tngtech.archunit.lang.conditions.ArchPredicates.have;
3940

4041
class SyntaxPredicates {
@@ -110,6 +111,14 @@ static DescribedPredicate<HasName> doNotHaveFullyQualifiedName(String name) {
110111
return doNot(have(fullyQualifiedName(name)));
111112
}
112113

114+
static DescribedPredicate<HasName> haveFullyQualifiedNameAnyOf(String[] classNames) {
115+
return have(fullyQualifiedNameAnyOf(classNames));
116+
}
117+
118+
static DescribedPredicate<HasName> doNotHaveFullyQualifiedNameAnyOf(String[] classNames) {
119+
return doNot(have(fullyQualifiedNameAnyOf(classNames)));
120+
}
121+
113122
static DescribedPredicate<JavaClass> haveSimpleName(String name) {
114123
return have(simpleName(name));
115124
}

archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/ClassesThat.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ public interface ClassesThat<CONJUNCTION> {
5555
@PublicAPI(usage = ACCESS)
5656
CONJUNCTION doNotHaveFullyQualifiedName(String name);
5757

58+
/**
59+
* Matches classes by their fully qualified class name.
60+
*
61+
* @param classNames One or more fully qualified class names
62+
* @return A syntax conjunction element, which can be completed to form a full rule
63+
*/
64+
@PublicAPI(usage = ACCESS)
65+
CONJUNCTION haveFullyQualifiedNameAnyOf(String... classNames);
66+
67+
/**
68+
* Matches classes that do not have a certain fully qualified class name.
69+
*
70+
* @param classNames One or more fully qualified class names
71+
* @return A syntax conjunction element, which can be completed to form a full rule
72+
*/
73+
@PublicAPI(usage = ACCESS)
74+
CONJUNCTION doNotHaveFullyQualifiedNameAnyOf(String... classNames);
75+
5876
/**
5977
* Matches classes by their simple class name.
6078
*

archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenClassesThatTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ public void doNotHaveFullyQualifiedName() {
7373
assertThatTypes(classes).matchInAnyOrder(String.class, Iterable.class);
7474
}
7575

76+
@Test
77+
public void haveFullyQualifiedNameAnyOf() {
78+
List<JavaClass> classes = filterResultOf(classes().that().haveFullyQualifiedNameAnyOf(List.class.getName()))
79+
.on(List.class, String.class, Iterable.class);
80+
81+
assertThatType(getOnlyElement(classes)).matches(List.class);
82+
}
83+
84+
@Test
85+
public void doNotHaveFullyQualifiedNameAnyOf() {
86+
List<JavaClass> classes = filterResultOf(classes().that().doNotHaveFullyQualifiedNameAnyOf(List.class.getName()))
87+
.on(List.class, String.class, Iterable.class);
88+
89+
assertThatTypes(classes).matchInAnyOrder(String.class, Iterable.class);
90+
}
91+
7692
@Test
7793
public void haveSimpleName() {
7894
List<JavaClass> classes = filterResultOf(classes().that().haveSimpleName(List.class.getSimpleName()))

archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersDeclaredInClassesThatTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ public void doNotHaveFullyQualifiedName() {
6868
assertThatMembers(members).matchInAnyOrderMembersOf(String.class, Iterable.class);
6969
}
7070

71+
@Test
72+
public void haveFullyQualifiedNameAnyOf() {
73+
List<JavaMember> members = filterResultOf(members().that().areDeclaredInClassesThat().haveFullyQualifiedNameAnyOf(List.class.getName()))
74+
.on(List.class, String.class, Iterable.class);
75+
76+
assertThatMembers(members).matchInAnyOrderMembersOf(List.class);
77+
}
78+
79+
@Test
80+
public void doNotHaveFullyQualifiedNameAnyOf() {
81+
List<JavaMember> members = filterResultOf(members().that().areDeclaredInClassesThat().doNotHaveFullyQualifiedNameAnyOf(List.class.getName()))
82+
.on(List.class, String.class, Iterable.class);
83+
84+
assertThatMembers(members).matchInAnyOrderMembersOf(String.class, Iterable.class);
85+
}
86+
7187
@Test
7288
public void haveSimpleName() {
7389
List<JavaMember> members = filterResultOf(members().that().areDeclaredInClassesThat().haveSimpleName(List.class.getSimpleName()))

archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ public void doNotHaveFullyQualifiedName(ClassesThat<ClassesShouldConjunction> no
8989
assertThatTypes(classes).matchInAnyOrder(ClassAccessingString.class, ClassAccessingIterable.class);
9090
}
9191

92+
@Test
93+
@UseDataProvider("no_classes_should_that_rule_starts")
94+
public void haveFullyQualifiedNameAnyOf(ClassesThat<ClassesShouldConjunction> noClassesShouldThatRuleStart) {
95+
Set<JavaClass> classes = filterClassesAppearingInFailureReport(
96+
noClassesShouldThatRuleStart.haveFullyQualifiedNameAnyOf(List.class.getName()))
97+
.on(ClassAccessingList.class, ClassAccessingString.class, ClassAccessingIterable.class);
98+
99+
assertThatType(getOnlyElement(classes)).matches(ClassAccessingList.class);
100+
}
101+
102+
@Test
103+
@UseDataProvider("no_classes_should_that_rule_starts")
104+
public void doNotHaveFullyQualifiedNameAnyOf(ClassesThat<ClassesShouldConjunction> noClassesShouldThatRuleStart) {
105+
Set<JavaClass> classes = filterClassesAppearingInFailureReport(
106+
noClassesShouldThatRuleStart.doNotHaveFullyQualifiedNameAnyOf(List.class.getName()))
107+
.on(ClassAccessingList.class, ClassAccessingString.class, ClassAccessingIterable.class);
108+
109+
assertThatTypes(classes).matchInAnyOrder(ClassAccessingString.class, ClassAccessingIterable.class);
110+
}
111+
92112
@Test
93113
@UseDataProvider("no_classes_should_that_rule_starts")
94114
public void haveSimpleName(ClassesThat<ClassesShouldConjunction> noClassesShouldThatRuleStart) {
@@ -1735,7 +1755,7 @@ static class DirectlyDependentClass3 {
17351755

17361756
@SuppressWarnings("unused")
17371757
static class Level1TransitivelyDependentClass1 {
1738-
Level2TransitivelyDependentClass1 transitiveDependency1;
1758+
Level2TransitivelyDependentClass1 transitiveDependency1;
17391759
}
17401760

17411761
static class Level2TransitivelyDependentClass1 {

archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldOnlyByClassesThatTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,32 @@ public void doNotHaveFullyQualifiedName(ClassesThat<ClassesShouldConjunction> cl
8484
assertThatTypes(classes).matchInAnyOrder(ClassAccessedByFoo.class, Foo.class);
8585
}
8686

87+
@Test
88+
@UseDataProvider("should_only_be_by_rule_starts")
89+
public void haveFullyQualifiedNameAnyOf(ClassesThat<ClassesShouldConjunction> classesShouldOnlyBeBy) {
90+
Set<JavaClass> classes = filterClassesAppearingInFailureReport(
91+
classesShouldOnlyBeBy.haveFullyQualifiedNameAnyOf(Foo.class.getName()))
92+
.on(ClassAccessedByFoo.class, Foo.class,
93+
ClassAccessedByBar.class, Bar.class,
94+
ClassAccessedByBaz.class, Baz.class);
95+
96+
assertThatTypes(classes).matchInAnyOrder(
97+
ClassAccessedByBar.class, Bar.class,
98+
ClassAccessedByBaz.class, Baz.class);
99+
}
100+
101+
@Test
102+
@UseDataProvider("should_only_be_by_rule_starts")
103+
public void doNotHaveFullyQualifiedNameAnyOf(ClassesThat<ClassesShouldConjunction> classesShouldOnlyBeBy) {
104+
Set<JavaClass> classes = filterClassesAppearingInFailureReport(
105+
classesShouldOnlyBeBy.doNotHaveFullyQualifiedNameAnyOf(Foo.class.getName()))
106+
.on(ClassAccessedByFoo.class, Foo.class,
107+
ClassAccessedByBar.class, Bar.class,
108+
ClassAccessedByBaz.class, Baz.class);
109+
110+
assertThatTypes(classes).matchInAnyOrder(ClassAccessedByFoo.class, Foo.class);
111+
}
112+
87113
@Test
88114
@UseDataProvider("should_only_be_by_rule_starts")
89115
public void haveSimpleName(ClassesThat<ClassesShouldConjunction> classesShouldOnlyBeBy) {
@@ -1422,6 +1448,7 @@ private static class StaticNestedClassBeingAccessed {
14221448

14231449
// This must be loaded via Reflection, otherwise the test will be tainted by the dependency on the class object
14241450
private static final Class<?> ClassAccessingAnonymousClass_Reference = classForName("com.tngtech.archunit.lang.syntax.elements.ShouldOnlyByClassesThatTest$ClassAccessingAnonymousClass");
1451+
14251452
private static class ClassAccessingAnonymousClass {
14261453
@SuppressWarnings("unused")
14271454
void access() {

0 commit comments

Comments
 (0)