Skip to content

Commit

Permalink
Extend MembersThat and MembersShould to have starting,… (Resolves #239)
Browse files Browse the repository at this point in the history
#314

… containing and ending functionality and their negations.
  • Loading branch information
codecholeric authored May 24, 2020
2 parents eacee80 + 74dcc1b commit 93b3767
Show file tree
Hide file tree
Showing 10 changed files with 609 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,21 @@ public static DescribedPredicate<HasName> nameMatching(final String regex) {
return new NameMatchingPredicate(regex);
}

@PublicAPI(usage = ACCESS)
public static DescribedPredicate<HasName> nameStartingWith(final String prefix) {
return new NameStartingWithPredicate(prefix);
}

@PublicAPI(usage = ACCESS)
public static DescribedPredicate<HasName> nameContaining(final String infix) {
return new NameContainingPredicate(infix);
}

@PublicAPI(usage = ACCESS)
public static DescribedPredicate<HasName> nameEndingWith(final String postfix) {
return new NameEndingWithPredicate(postfix);
}

private static class NameEqualsPredicate extends DescribedPredicate<HasName> {
private final String name;

Expand Down Expand Up @@ -138,6 +153,49 @@ public boolean apply(HasName input) {
return pattern.matcher(input.getName()).matches();
}
}

private static class NameStartingWithPredicate extends DescribedPredicate<HasName> {
private final String prefix;

NameStartingWithPredicate(String prefix) {
super(String.format("name starting with '%s'", prefix));
this.prefix = prefix;
}

@Override
public boolean apply(HasName input) {
return input.getName().startsWith(prefix);
}

}

private static class NameContainingPredicate extends DescribedPredicate<HasName> {
private final String infix;

NameContainingPredicate(String infix) {
super(String.format("name containing '%s'", infix));
this.infix = infix;
}

@Override
public boolean apply(HasName input) {
return input.getName().contains(infix);
}
}

private static class NameEndingWithPredicate extends DescribedPredicate<HasName> {
private final String suffix;

NameEndingWithPredicate(String suffix) {
super(String.format("name ending with '%s'", suffix));
this.suffix = suffix;
}

@Override
public boolean apply(HasName input) {
return input.getName().endsWith(suffix);
}
}
}

final class Functions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@
import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName;
import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameEndingWith;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameStartingWith;
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
import static com.tngtech.archunit.core.domain.properties.HasParameterTypes.Predicates.rawParameterTypes;
import static com.tngtech.archunit.core.domain.properties.HasReturnType.Predicates.rawReturnType;
Expand Down Expand Up @@ -553,6 +556,48 @@ ArchCondition<HAS_FULL_NAME> haveFullNameMatching(String regex) {
return not(ArchConditions.<HAS_FULL_NAME>haveFullNameMatching(regex)).as("have full name not matching '%s'", regex);
}

@PublicAPI(usage = ACCESS)
public static <HAS_NAME extends HasName & HasDescription & HasSourceCodeLocation> ArchCondition<HAS_NAME>
haveNameStartingWith(String prefix) {
final DescribedPredicate<HAS_NAME> haveNameStartingWith = have(nameStartingWith(prefix)).forSubType();
return new StartingCondition<>(haveNameStartingWith, prefix);
}

@PublicAPI(usage = ACCESS)
public static <HAS_NAME extends HasName & HasDescription & HasSourceCodeLocation> ArchCondition<HAS_NAME>
haveNameNotStartingWith(String prefix) {
final DescribedPredicate<HAS_NAME> haveNameStartingWith = have(nameStartingWith(prefix)).forSubType();
return not(new StartingCondition<>(haveNameStartingWith, prefix)).as("have name not starting with '%s'", prefix);
}

@PublicAPI(usage = ACCESS)
public static <HAS_NAME extends HasName & HasDescription & HasSourceCodeLocation> ArchCondition<HAS_NAME>
haveNameContaining(String infix) {
final DescribedPredicate<HAS_NAME> haveNameContaining = have(nameContaining(infix)).forSubType();
return new ContainingCondition<>(haveNameContaining, infix);
}

@PublicAPI(usage = ACCESS)
public static <HAS_NAME extends HasName & HasDescription & HasSourceCodeLocation> ArchCondition<HAS_NAME>
haveNameNotContaining(String infix) {
final DescribedPredicate<HAS_NAME> haveNameContaining = have(nameContaining(infix)).forSubType();
return not(new ContainingCondition<>(haveNameContaining, infix)).as("have name not containing '%s'", infix);
}

@PublicAPI(usage = ACCESS)
public static <HAS_NAME extends HasName & HasDescription & HasSourceCodeLocation> ArchCondition<HAS_NAME>
haveNameEndingWith(String suffix) {
final DescribedPredicate<HAS_NAME> haveNameEndingWith = have(nameEndingWith(suffix)).forSubType();
return new EndingCondition<>(haveNameEndingWith, suffix);
}

@PublicAPI(usage = ACCESS)
public static <HAS_NAME extends HasName & HasDescription & HasSourceCodeLocation> ArchCondition<HAS_NAME>
haveNameNotEndingWith(String suffix) {
final DescribedPredicate<HAS_NAME> haveNameEndingWith = have(nameEndingWith(suffix)).forSubType();
return not(new EndingCondition<>(haveNameEndingWith, suffix)).as("have name not ending with '%s'", suffix);
}

@PublicAPI(usage = ACCESS)
public static ArchCondition<JavaClass> resideInAPackage(final String packageIdentifier) {
return new DoesConditionByPredicate<>(JavaClass.Predicates.resideInAPackage(packageIdentifier));
Expand Down Expand Up @@ -1243,6 +1288,63 @@ public void check(T item, ConditionEvents events) {
}
}

private static class StartingCondition<T extends HasDescription & HasSourceCodeLocation> extends ArchCondition<T> {
private final DescribedPredicate<T> startingWith;
private final String prefix;

StartingCondition(DescribedPredicate<T> startingWith, String prefix) {
super(startingWith.getDescription());
this.startingWith = startingWith;
this.prefix = prefix;
}

@Override
public void check(T item, ConditionEvents events) {
boolean satisfied = startingWith.apply(item);
String message = createMessage(item,
String.format("name %s '%s'", satisfied ? "starts with" : "does not start with", prefix));
events.add(new SimpleConditionEvent(item, satisfied, message));
}
}

private static class ContainingCondition<T extends HasDescription & HasSourceCodeLocation> extends ArchCondition<T> {
private final DescribedPredicate<T> containing;
private final String infix;

ContainingCondition(DescribedPredicate<T> containing, String infix) {
super(containing.getDescription());
this.containing = containing;
this.infix = infix;
}

@Override
public void check(T item, ConditionEvents events) {
boolean satisfied = containing.apply(item);
String message = createMessage(item,
String.format("name %s '%s'", satisfied ? "contains" : "does not contain", infix));
events.add(new SimpleConditionEvent(item, satisfied, message));
}
}

private static class EndingCondition<T extends HasDescription & HasSourceCodeLocation> extends ArchCondition<T> {
private final DescribedPredicate<T> endingWith;
private final String suffix;

EndingCondition(DescribedPredicate<T> endingWith, String suffix) {
super(endingWith.getDescription());
this.endingWith = endingWith;
this.suffix = suffix;
}

@Override
public void check(T item, ConditionEvents events) {
boolean satisfied = endingWith.apply(item);
String message = createMessage(item,
String.format("name %s '%s'", satisfied ? "ends with" : "does not end with", suffix));
events.add(new SimpleConditionEvent(item, satisfied, message));
}
}

private static class DoesConditionByPredicate<T extends HasDescription & HasSourceCodeLocation>
extends ArchCondition<T> {
private final DescribedPredicate<? super T> predicate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,37 @@ public SELF haveFullNameMatching(String regex) {
public SELF haveFullNameNotMatching(String regex) {
return addCondition(ArchConditions.haveFullNameNotMatching(regex));
}

@Override
public SELF haveNameStartingWith(String prefix) {
return addCondition(ArchConditions.haveNameStartingWith(prefix));
}

@Override
public SELF haveNameNotStartingWith(String prefix) {
return addCondition(ArchConditions.haveNameNotStartingWith(prefix));
}

@Override
public SELF haveNameContaining(String infix) {
return addCondition(ArchConditions.haveNameContaining(infix));
}

@Override
public SELF haveNameNotContaining(String infix) {
return addCondition(ArchConditions.haveNameNotContaining(infix));
}

@Override
public SELF haveNameEndingWith(String suffix) {
return addCondition(ArchConditions.haveNameEndingWith(suffix));
}

@Override
public SELF haveNameNotEndingWith(String suffix) {
return addCondition(ArchConditions.haveNameNotEndingWith(suffix));
}

@Override
public SELF bePublic() {
return addCondition(ArchConditions.bePublic());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName;
import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameEndingWith;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameStartingWith;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.are;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.have;

Expand Down Expand Up @@ -93,6 +96,36 @@ public CONJUNCTION haveFullNameNotMatching(String regex) {
return givenWith(have(not(fullNameMatching(regex)).as("full name not matching '%s'", regex)));
}

@Override
public CONJUNCTION haveNameStartingWith(String prefix) {
return givenWith(have(nameStartingWith(prefix)));
}

@Override
public CONJUNCTION haveNameNotStartingWith(String prefix) {
return givenWith(have(not(nameStartingWith(prefix)).as("name not starting with '%s'", prefix)));
}

@Override
public CONJUNCTION haveNameContaining(String infix) {
return givenWith(have(nameContaining(infix)));
}

@Override
public CONJUNCTION haveNameNotContaining(String infix) {
return givenWith(have(not(nameContaining(infix)).as("name not containing '%s'", infix)));
}

@Override
public CONJUNCTION haveNameEndingWith(String suffix) {
return givenWith(have(nameEndingWith(suffix)));
}

@Override
public CONJUNCTION haveNameNotEndingWith(String suffix) {
return givenWith(have(not(nameEndingWith(suffix)).as("name not ending with '%s'", suffix)));
}

@Override
public CONJUNCTION arePublic() {
return givenWith(SyntaxPredicates.arePublic());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,60 @@ public interface MembersShould<CONJUNCTION extends MembersShouldConjunction<?>>
@PublicAPI(usage = ACCESS)
CONJUNCTION haveFullNameNotMatching(String regex);

/**
* Asserts that members have a name starting with the specified prefix.
*
* @param prefix A prefix the member name should start with
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
CONJUNCTION haveNameStartingWith(String prefix);

/**
* Asserts that members have a name not starting with the specified prefix.
*
* @param prefix A prefix the member name should not start with
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
CONJUNCTION haveNameNotStartingWith(String prefix);

/**
* Asserts that members have a name containing the specified infix.
*
* @param infix An infix the member name should contain
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
CONJUNCTION haveNameContaining(String infix);

/**
* Asserts that members have a name not containing the specified infix.
*
* @param infix An infix the member name should not contain
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
CONJUNCTION haveNameNotContaining(String infix);

/**
* Asserts that members have a name ending with the specified suffix.
*
* @param suffix A suffix the member name should end with
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
CONJUNCTION haveNameEndingWith(String suffix);

/**
* Asserts that members have a name not ending with the specified suffix.
*
* @param suffix A suffix the member name should not end with
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
CONJUNCTION haveNameNotEndingWith(String suffix);

/**
* Asserts that members are public.
*
Expand Down
Loading

0 comments on commit 93b3767

Please sign in to comment.