diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedNaming.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedNaming.java
index 67dc24037f..698000927c 100644
--- a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedNaming.java
+++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedNaming.java
@@ -19,20 +19,20 @@ private Creator(String className, String simpleName) {
}
public ExpectedMessage notStartingWith(String prefix) {
- return expectedSimpleName(String.format("does not start with '%s'", prefix));
+ return expectedClassViolation(String.format("does not have simple name starting with '%s'", prefix));
}
public ExpectedMessage notEndingWith(String suffix) {
- return expectedSimpleName(String.format("does not end with '%s'", suffix));
+ return expectedClassViolation(String.format("does not have simple name ending with '%s'", suffix));
}
public ExpectedMessage containing(String infix) {
- return expectedSimpleName(String.format("contains '%s'", infix));
+ return expectedClassViolation(String.format("has simple name containing '%s'", infix));
}
- private ExpectedMessage expectedSimpleName(String suffix) {
- return new ExpectedMessage(String.format("simple name of %s %s in (%s.java:0)",
- className, suffix, simpleName));
+ private ExpectedMessage expectedClassViolation(String description) {
+ return new ExpectedMessage(String.format("Class <%s> %s in (%s.java:0)",
+ className, description, simpleName));
}
}
}
diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedViolation.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedViolation.java
index 1aac60b37a..0b46dd2a11 100644
--- a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedViolation.java
+++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedViolation.java
@@ -137,12 +137,12 @@ private ClassAssertionCreator(Class> clazz) {
}
public MessageAssertionChain.Link havingNameMatching(String regex) {
- return MessageAssertionChain.containsLine("Class <%s> matches '%s' in (%s.java:0)",
+ return MessageAssertionChain.containsLine("Class <%s> has name matching '%s' in (%s.java:0)",
clazz.getName(), regex, clazz.getSimpleName());
}
public MessageAssertionChain.Link havingSimpleNameContaining(String infix) {
- return MessageAssertionChain.containsLine("simple name of %s contains '%s' in (%s.java:0)",
+ return MessageAssertionChain.containsLine("Class <%s> has simple name containing '%s' in (%s.java:0)",
clazz.getName(), infix, clazz.getSimpleName());
}
diff --git a/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java b/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java
index 99b6169c71..2e56c7cea2 100644
--- a/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java
+++ b/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java
@@ -51,6 +51,19 @@ public String getDescription() {
return description;
}
+ /**
+ * Overwrites the description of this {@link DescribedPredicate}. E.g.
+ *
+ *
+ * classes().that(predicate.as("some customized description with '%s'", "parameter")).should().bePublic()
+ *
+ *
+ * would then yield {@code classes that some customized description with 'parameter' should be public}.
+ *
+ * @param description The new description of this {@link DescribedPredicate}
+ * @param params Optional arguments to fill into the description via {@link String#format(String, Object...)}
+ * @return An {@link DescribedPredicate} with adjusted {@link #getDescription() description}.
+ */
public DescribedPredicate as(String description, Object... params) {
return new AsPredicate<>(this, description, params);
}
@@ -68,7 +81,16 @@ public DescribedPredicate onResultOf(final Function super F, ? extends
}
/**
- * Workaround for the limitations of the Java type system {@code ->} Can't specify this contravariant type at the language level
+ * Convenience method to downcast the predicate. {@link DescribedPredicate DescribedPredicates} are contravariant by nature,
+ * i.e. an {@code DescribedPredicate} is an instance of {@code DescribedPredicate}, if and only if {@code V} is an instance of {@code T}.
+ *
+ * Take for example {@code Object > String}. Obviously a {@code DescribedPredicate} is also a {@code DescribedPredicate}.
+ *
+ * Unfortunately, the Java type system does not allow us to express this property of the type parameter of {@code DescribedPredicate}.
+ * So to avoid forcing users to cast everywhere it is possible to use this method which also documents the intention and reasoning.
+ *
+ * @return A {@link DescribedPredicate} accepting a subtype of the predicate's actual type parameter {@code T}
+ * @param A subtype of the {@link DescribedPredicate DescribedPredicate's} type parameter {@code T}
*/
@SuppressWarnings("unchecked") // DescribedPredicate is contravariant
public final DescribedPredicate forSubtype() {
diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java b/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java
index 07cfa69e23..07cdee02ea 100644
--- a/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java
+++ b/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java
@@ -18,9 +18,15 @@
import java.util.Collection;
import com.tngtech.archunit.PublicAPI;
+import com.tngtech.archunit.base.DescribedPredicate;
+import com.tngtech.archunit.base.HasDescription;
+import com.tngtech.archunit.core.domain.JavaClass;
+import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation;
import com.tngtech.archunit.lang.conditions.ArchConditions;
+import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
import static com.tngtech.archunit.PublicAPI.Usage.INHERITANCE;
+import static com.tngtech.archunit.lang.ConditionEvent.createMessage;
@PublicAPI(usage = INHERITANCE)
public abstract class ArchCondition {
@@ -63,6 +69,19 @@ public String getDescription() {
return description;
}
+ /**
+ * Overwrites the description of this {@link ArchCondition}. E.g.
+ *
+ *
+ * classes().should(condition.as("some customized description with '%s'", "parameter"))
+ *
+ *
+ * would then yield {@code classes should some customized description with 'parameter'}.
+ *
+ * @param description The new description of this {@link ArchCondition}
+ * @param args Optional arguments to fill into the description via {@link String#format(String, Object...)}
+ * @return An {@link ArchCondition} with adjusted {@link #getDescription() description}.
+ */
public ArchCondition as(String description, Object... args) {
return new ArchCondition(description, args) {
@Override
@@ -87,8 +106,125 @@ public String toString() {
return getDescription();
}
+ /**
+ * Convenience method to downcast the condition. {@link ArchCondition ArchConditions} are contravariant by nature,
+ * i.e. an {@code ArchCondition} is an instance of {@code ArchCondition}, if and only if {@code V} is an instance of {@code T}.
+ *
+ * Take for example {@code Object > String}. Obviously an {@code ArchCondition} is also an {@code ArchCondition}.
+ *
+ * Unfortunately, the Java type system does not allow us to express this property of the type parameter of {@code ArchCondition}.
+ * So to avoid forcing users to cast everywhere it is possible to use this method which also documents the intention and reasoning.
+ *
+ * @return An {@link ArchCondition} accepting a subtype of the condition's actual type parameter {@code T}
+ * @param A subtype of the {@link ArchCondition ArchCondition's} type parameter {@code T}
+ */
@SuppressWarnings("unchecked") // Cast is safe since input parameter is contravariant
public ArchCondition forSubtype() {
return (ArchCondition) this;
}
+
+ /**
+ * Creates an {@link ArchCondition} from a {@link DescribedPredicate}.
+ * For more information see {@link ConditionByPredicate ConditionByPredicate}.
+ * For more convenient versions of this method compare {@link ArchConditions#have(DescribedPredicate)} and {@link ArchConditions#be(DescribedPredicate)}.
+ *
+ * @param predicate Specifies which objects satisfy the condition.
+ * @return A {@link ConditionByPredicate ConditionByPredicate} derived from the supplied {@link DescribedPredicate predicate}
+ * @param The type of object the {@link ArchCondition condition} will check
+ *
+ * @see ArchConditions#have(DescribedPredicate)
+ * @see ArchConditions#be(DescribedPredicate)
+ */
+ @PublicAPI(usage = ACCESS)
+ public static ConditionByPredicate from(DescribedPredicate super T> predicate) {
+ return new ConditionByPredicate<>(predicate);
+ }
+
+ /**
+ * An {@link ArchCondition} that derives which objects satisfy/violate the condition from a {@link DescribedPredicate}.
+ * The description is taken from the defining {@link DescribedPredicate predicate} but can be overridden via {@link #as(String, Object...)}.
+ * How the message of each single {@link ConditionEvent event} is derived can be customized by {@link #describeEventsBy(EventDescriber)}.
+ *
+ * @param The type of object the condition will test
+ */
+ @PublicAPI(usage = ACCESS)
+ public static final class ConditionByPredicate extends ArchCondition {
+ private final DescribedPredicate predicate;
+ private final EventDescriber eventDescriber;
+
+ private ConditionByPredicate(DescribedPredicate super T> predicate) {
+ this(predicate, predicate.getDescription(), ((predicateDescription, satisfied) -> (satisfied ? "satisfies " : "does not satisfy ") + predicateDescription));
+ }
+
+ private ConditionByPredicate(
+ DescribedPredicate super T> predicate,
+ String description,
+ EventDescriber eventDescriber
+ ) {
+ super(description);
+ this.predicate = predicate.forSubtype();
+ this.eventDescriber = eventDescriber;
+ }
+
+ /**
+ * Adjusts how this {@link ConditionByPredicate condition} will create the description of the {@link ConditionEvent events}.
+ * E.g. assume the {@link DescribedPredicate predicate} of this condition is {@link JavaClass.Predicates#simpleName(String) simpleName(name)},
+ * then this method could be used to adjust the event description as
+ *
+ *
+ * condition.describeEventsBy((predicateDescription, satisfied) ->
+ * (satisfied ? "has " : "does not have ") + predicateDescription
+ * )
+ *
+ * @param eventDescriber Specifies how to create the description of the {@link ConditionEvent}
+ * whenever the predicate is evaluated against an object.
+ * @return A {@link ConditionByPredicate ConditionByPredicate} that describes its {@link ConditionEvent events} with the given {@link EventDescriber EventDescriber}
+ */
+ @PublicAPI(usage = ACCESS)
+ public ConditionByPredicate describeEventsBy(EventDescriber eventDescriber) {
+ return new ConditionByPredicate<>(
+ predicate,
+ getDescription(),
+ eventDescriber
+ );
+ }
+
+ @Override
+ public ConditionByPredicate as(String description, Object... args) {
+ return new ConditionByPredicate<>(predicate, String.format(description, args), eventDescriber);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // Cast is safe since input parameter is contravariant
+ public ConditionByPredicate forSubtype() {
+ return (ConditionByPredicate) this;
+ }
+
+ @Override
+ public void check(T object, ConditionEvents events) {
+ boolean satisfied = predicate.test(object);
+ String message = createMessage(object, eventDescriber.describe(predicate.getDescription(), satisfied));
+ events.add(new SimpleConditionEvent(object, satisfied, message));
+ }
+
+ /**
+ * Defines how to describe a single {@link ConditionEvent}. E.g. how to describe the concrete violation of some class
+ * {@code com.Example} that violates the {@link ConditionByPredicate}.
+ */
+ @FunctionalInterface
+ @PublicAPI(usage = INHERITANCE)
+ public interface EventDescriber {
+ /**
+ * Describes a {@link ConditionEvent} created by {@link ConditionByPredicate ConditionByPredicate},
+ * given the description of the defining predicate and whether the predicate was satisfied.
+ * For example, if the defining {@link DescribedPredicate} would be {@link JavaClass.Predicates#simpleName(String)}, then
+ * the created description could be {@code (satisfied ? "has " : "does not have ") + predicateDescription}.
+ *
+ * @param predicateDescription The description of the {@link DescribedPredicate} defining the {@link ConditionByPredicate ConditionByPredicate}
+ * @param satisfied Whether the object tested by the {@link ConditionByPredicate ConditionByPredicate} satisfied the condition
+ * @return The description of the {@link ConditionEvent} to be created
+ */
+ String describe(String predicateDescription, boolean satisfied);
+ }
+ }
}
diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java
index 81424d4e83..0f982a56c8 100644
--- a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java
+++ b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java
@@ -60,6 +60,7 @@
import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation;
import com.tngtech.archunit.core.domain.properties.HasThrowsClause;
import com.tngtech.archunit.lang.ArchCondition;
+import com.tngtech.archunit.lang.ArchCondition.ConditionByPredicate;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import com.tngtech.archunit.lang.conditions.ClassAccessesFieldCondition.ClassGetsFieldCondition;
@@ -86,6 +87,15 @@
import static com.tngtech.archunit.core.domain.JavaClass.Functions.GET_FIELD_ACCESSES_FROM_SELF;
import static com.tngtech.archunit.core.domain.JavaClass.Functions.GET_METHOD_CALLS_FROM_SELF;
import static com.tngtech.archunit.core.domain.JavaClass.Functions.GET_PACKAGE_NAME;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.ANONYMOUS_CLASSES;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.ENUMS;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.INNER_CLASSES;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.INTERFACES;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.LOCAL_CLASSES;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.MEMBER_CLASSES;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.NESTED_CLASSES;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.RECORDS;
+import static com.tngtech.archunit.core.domain.JavaClass.Predicates.TOP_LEVEL_CLASSES;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableFrom;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.equivalentTo;
@@ -117,8 +127,6 @@
import static com.tngtech.archunit.core.domain.properties.HasReturnType.Predicates.rawReturnType;
import static com.tngtech.archunit.core.domain.properties.HasThrowsClause.Predicates.throwsClauseContainingType;
import static com.tngtech.archunit.core.domain.properties.HasType.Predicates.rawType;
-import static com.tngtech.archunit.lang.ConditionEvent.createMessage;
-import static com.tngtech.archunit.lang.conditions.ArchPredicates.have;
import static java.util.Arrays.asList;
public final class ArchConditions {
@@ -459,7 +467,9 @@ public static ArchCondition notBe(final Class> clazz) {
@PublicAPI(usage = ACCESS)
public static ArchCondition be(final String className) {
- return new BeClassCondition(className);
+ return be(fullyQualifiedName(className).as(className))
+ .describeEventsBy((__, satisfied) -> (satisfied ? "is " : "is not ") + className)
+ .forSubtype();
}
@PublicAPI(usage = ACCESS)
@@ -469,29 +479,29 @@ public static ArchCondition notBe(final String className) {
@PublicAPI(usage = ACCESS)
public static ArchCondition haveName(final String name) {
- return new HaveConditionByPredicate<>(name(name));
+ return have(name(name));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition notHaveName(String name) {
- return not(ArchConditions.haveName(name));
+ return not(haveName(name));
}
@PublicAPI(usage = ACCESS)
public static
ArchCondition haveFullName(String fullName) {
- return new HaveConditionByPredicate<>(fullName(fullName));
+ return have(fullName(fullName));
}
@PublicAPI(usage = ACCESS)
public static
ArchCondition notHaveFullName(String fullName) {
- return not(new HaveConditionByPredicate<>(fullName(fullName)));
+ return not(haveFullName(fullName));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveFullyQualifiedName(final String name) {
- return new HaveConditionByPredicate<>(fullyQualifiedName(name));
+ return have(fullyQualifiedName(name));
}
@Internal
@@ -507,8 +517,7 @@ public static ArchCondition notHaveFullyQualifiedName(String name) {
@PublicAPI(usage = ACCESS)
public static ArchCondition haveSimpleName(final String name) {
- final DescribedPredicate haveSimpleName = have(simpleName(name));
- return new SimpleNameCondition(haveSimpleName, name);
+ return have(simpleName(name));
}
@PublicAPI(usage = ACCESS)
@@ -518,9 +527,7 @@ public static ArchCondition notHaveSimpleName(String name) {
@PublicAPI(usage = ACCESS)
public static ArchCondition haveSimpleNameStartingWith(final String prefix) {
- final DescribedPredicate predicate = have(simpleNameStartingWith(prefix));
-
- return new SimpleNameStartingWithCondition(predicate, prefix);
+ return have(simpleNameStartingWith(prefix));
}
@PublicAPI(usage = ACCESS)
@@ -530,9 +537,7 @@ public static ArchCondition haveSimpleNameNotStartingWith(String pref
@PublicAPI(usage = ACCESS)
public static ArchCondition haveSimpleNameContaining(final String infix) {
- final DescribedPredicate predicate = have(simpleNameContaining(infix));
-
- return new SimpleNameContainingCondition(predicate, infix);
+ return have(simpleNameContaining(infix));
}
@PublicAPI(usage = ACCESS)
@@ -542,9 +547,7 @@ public static ArchCondition haveSimpleNameNotContaining(final String
@PublicAPI(usage = ACCESS)
public static ArchCondition haveSimpleNameEndingWith(final String suffix) {
- final DescribedPredicate predicate = have(simpleNameEndingWith(suffix));
-
- return new SimpleNameEndingWithCondition(predicate, suffix);
+ return have(simpleNameEndingWith(suffix));
}
@PublicAPI(usage = ACCESS)
@@ -554,8 +557,7 @@ public static ArchCondition haveSimpleNameNotEndingWith(String suffix
@PublicAPI(usage = ACCESS)
public static ArchCondition haveNameMatching(final String regex) {
- final DescribedPredicate haveNameMatching = have(nameMatching(regex)).forSubtype();
- return new MatchingCondition<>(haveNameMatching, regex);
+ return have(nameMatching(regex));
}
@PublicAPI(usage = ACCESS)
@@ -566,8 +568,7 @@ public static
ArchCondition haveFullNameMatching(String regex) {
- final DescribedPredicate haveFullNameMatching = have(fullNameMatching(regex)).forSubtype();
- return new MatchingCondition<>(haveFullNameMatching, regex);
+ return have(fullNameMatching(regex));
}
@PublicAPI(usage = ACCESS)
@@ -577,71 +578,59 @@ ArchCondition haveFullNameMatching(String regex) {
}
@PublicAPI(usage = ACCESS)
- public static ArchCondition
- haveNameStartingWith(String prefix) {
- final DescribedPredicate haveNameStartingWith = have(nameStartingWith(prefix)).forSubtype();
- return new StartingCondition<>(haveNameStartingWith, prefix);
+ public static ArchCondition haveNameStartingWith(String prefix) {
+ return have(nameStartingWith(prefix));
}
@PublicAPI(usage = ACCESS)
- public static ArchCondition
- haveNameNotStartingWith(String prefix) {
- final DescribedPredicate haveNameStartingWith = have(nameStartingWith(prefix)).forSubtype();
- return not(new StartingCondition<>(haveNameStartingWith, prefix)).as("have name not starting with '%s'", prefix);
+ public static ArchCondition haveNameNotStartingWith(String prefix) {
+ return not(haveNameStartingWith(prefix)).forSubtype().as("have name not starting with '%s'", prefix);
}
@PublicAPI(usage = ACCESS)
- public static ArchCondition
- haveNameContaining(String infix) {
- final DescribedPredicate haveNameContaining = have(nameContaining(infix)).forSubtype();
- return new ContainingCondition<>(haveNameContaining, infix);
+ public static ArchCondition haveNameContaining(String infix) {
+ return have(nameContaining(infix));
}
@PublicAPI(usage = ACCESS)
- public static ArchCondition
- haveNameNotContaining(String infix) {
- final DescribedPredicate haveNameContaining = have(nameContaining(infix)).forSubtype();
- return not(new ContainingCondition<>(haveNameContaining, infix)).as("have name not containing '%s'", infix);
+ public static ArchCondition haveNameNotContaining(String infix) {
+ return not(haveNameContaining(infix)).forSubtype().as("have name not containing '%s'", infix);
}
@PublicAPI(usage = ACCESS)
- public static ArchCondition
- haveNameEndingWith(String suffix) {
- final DescribedPredicate haveNameEndingWith = have(nameEndingWith(suffix)).forSubtype();
- return new EndingCondition<>(haveNameEndingWith, suffix);
+ public static ArchCondition haveNameEndingWith(String suffix) {
+ return have(nameEndingWith(suffix));
}
@PublicAPI(usage = ACCESS)
- public static ArchCondition
- haveNameNotEndingWith(String suffix) {
- final DescribedPredicate haveNameEndingWith = have(nameEndingWith(suffix)).forSubtype();
- return not(new EndingCondition<>(haveNameEndingWith, suffix)).as("have name not ending with '%s'", suffix);
+ public static ArchCondition haveNameNotEndingWith(String suffix) {
+ return not(haveNameEndingWith(suffix)).forSubtype().as("have name not ending with '%s'", suffix);
}
@PublicAPI(usage = ACCESS)
public static ArchCondition resideInAPackage(final String packageIdentifier) {
- return new DoesConditionByPredicate<>(JavaClass.Predicates.resideInAPackage(packageIdentifier));
+ return does(JavaClass.Predicates.resideInAPackage(packageIdentifier));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition resideInAnyPackage(String... packageIdentifiers) {
- return new DoesConditionByPredicate<>(JavaClass.Predicates.resideInAnyPackage(packageIdentifiers));
+ return does(JavaClass.Predicates.resideInAnyPackage(packageIdentifiers));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition resideOutsideOfPackage(String packageIdentifier) {
- return new DoesConditionByPredicate<>(JavaClass.Predicates.resideOutsideOfPackage(packageIdentifier));
+ return does(JavaClass.Predicates.resideOutsideOfPackage(packageIdentifier));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition resideOutsideOfPackages(String... packageIdentifiers) {
- return new DoesConditionByPredicate<>(JavaClass.Predicates.resideOutsideOfPackages(packageIdentifiers));
+ return does(JavaClass.Predicates.resideOutsideOfPackages(packageIdentifiers));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveModifier(
final JavaModifier modifier) {
- return new HaveConditionByPredicate<>(modifier(modifier));
+ return have(modifier(modifier));
}
@PublicAPI(usage = ACCESS)
@@ -729,7 +718,7 @@ public static ArchCondition haveOnlyPrivateConstructors() {
@PublicAPI(usage = ACCESS)
public static & HasDescription & HasSourceCodeLocation> ArchCondition beAnnotatedWith(
Class extends Annotation> type) {
- return new IsConditionByPredicate<>(annotatedWith(type));
+ return be(annotatedWith(type));
}
/**
@@ -747,7 +736,7 @@ public static & HasDescription & HasS
@PublicAPI(usage = ACCESS)
public static & HasDescription & HasSourceCodeLocation> ArchCondition beAnnotatedWith(
String typeName) {
- return new IsConditionByPredicate<>(annotatedWith(typeName));
+ return be(annotatedWith(typeName));
}
/**
@@ -765,7 +754,7 @@ public static & HasDescription & HasS
@PublicAPI(usage = ACCESS)
public static & HasDescription & HasSourceCodeLocation> ArchCondition beAnnotatedWith(
final DescribedPredicate super JavaAnnotation>> predicate) {
- return new IsConditionByPredicate<>(annotatedWith(predicate));
+ return be(annotatedWith(predicate));
}
/**
@@ -783,7 +772,7 @@ public static & HasDescription & HasS
@PublicAPI(usage = ACCESS)
public static & HasDescription & HasSourceCodeLocation> ArchCondition beMetaAnnotatedWith(
Class extends Annotation> type) {
- return new IsConditionByPredicate<>(metaAnnotatedWith(type));
+ return be(metaAnnotatedWith(type));
}
/**
@@ -801,7 +790,7 @@ public static & HasDescription & HasS
@PublicAPI(usage = ACCESS)
public static & HasDescription & HasSourceCodeLocation> ArchCondition beMetaAnnotatedWith(
String typeName) {
- return new IsConditionByPredicate<>(metaAnnotatedWith(typeName));
+ return be(metaAnnotatedWith(typeName));
}
/**
@@ -819,7 +808,7 @@ public static & HasDescription & HasS
@PublicAPI(usage = ACCESS)
public static & HasDescription & HasSourceCodeLocation> ArchCondition beMetaAnnotatedWith(
final DescribedPredicate super JavaAnnotation>> predicate) {
- return new IsConditionByPredicate<>(metaAnnotatedWith(predicate));
+ return be(metaAnnotatedWith(predicate));
}
/**
@@ -836,7 +825,7 @@ public static & HasDescription & HasS
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition implement(Class> interfaceType) {
- return new ImplementsCondition(JavaClass.Predicates.implement(interfaceType));
+ return does(JavaClass.Predicates.implement(interfaceType));
}
/**
@@ -852,7 +841,7 @@ public static ArchCondition notImplement(Class> interfaceType) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition implement(String interfaceTypeName) {
- return new ImplementsCondition(JavaClass.Predicates.implement(interfaceTypeName));
+ return does(JavaClass.Predicates.implement(interfaceTypeName));
}
/**
@@ -868,7 +857,7 @@ public static ArchCondition notImplement(String interfaceTypeName) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition implement(DescribedPredicate super JavaClass> predicate) {
- return new ImplementsCondition(JavaClass.Predicates.implement(predicate));
+ return does(JavaClass.Predicates.implement(predicate));
}
/**
@@ -884,7 +873,7 @@ public static ArchCondition notImplement(DescribedPredicate super J
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beAssignableTo(Class> type) {
- return new IsConditionByPredicate<>(assignableTo(type));
+ return be(assignableTo(type));
}
/**
@@ -900,7 +889,7 @@ public static ArchCondition notBeAssignableTo(Class> type) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beAssignableTo(String typeName) {
- return new IsConditionByPredicate<>(assignableTo(typeName));
+ return be(assignableTo(typeName));
}
/**
@@ -916,7 +905,7 @@ public static ArchCondition notBeAssignableTo(String typeName) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beAssignableTo(DescribedPredicate super JavaClass> predicate) {
- return new IsConditionByPredicate<>(assignableTo(predicate));
+ return be(assignableTo(predicate));
}
/**
@@ -932,7 +921,7 @@ public static ArchCondition notBeAssignableTo(DescribedPredicate su
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beAssignableFrom(Class> type) {
- return new IsConditionByPredicate<>(assignableFrom(type));
+ return be(assignableFrom(type));
}
/**
@@ -948,7 +937,7 @@ public static ArchCondition notBeAssignableFrom(Class> type) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beAssignableFrom(String typeName) {
- return new IsConditionByPredicate<>(assignableFrom(typeName));
+ return be(assignableFrom(typeName));
}
/**
@@ -964,7 +953,7 @@ public static ArchCondition notBeAssignableFrom(String typeName) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beAssignableFrom(DescribedPredicate super JavaClass> predicate) {
- return new IsConditionByPredicate<>(assignableFrom(predicate));
+ return be(assignableFrom(predicate));
}
/**
@@ -981,7 +970,7 @@ public static ArchCondition notBeAssignableFrom(DescribedPredicate
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beInterfaces() {
- return InterfacesCondition.BE_INTERFACES;
+ return be(INTERFACES).describeEventsBy((__, satisfied) -> (satisfied ? "is an" : "is no") + " interface");
}
/**
@@ -989,7 +978,7 @@ public static ArchCondition beInterfaces() {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition notBeInterfaces() {
- return not(InterfacesCondition.BE_INTERFACES);
+ return not(beInterfaces());
}
/**
@@ -998,7 +987,7 @@ public static ArchCondition notBeInterfaces() {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beEnums() {
- return EnumsCondition.BE_ENUMS;
+ return be(ENUMS).describeEventsBy((__, satisfied) -> (satisfied ? "is an" : "is no") + " enum");
}
/**
@@ -1006,7 +995,7 @@ public static ArchCondition beEnums() {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition notBeEnums() {
- return not(EnumsCondition.BE_ENUMS);
+ return not(beEnums());
}
/**
@@ -1016,7 +1005,7 @@ public static ArchCondition notBeEnums() {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beRecords() {
- return RecordsCondition.BE_RECORDS;
+ return be(RECORDS).describeEventsBy((__, satisfied) -> (satisfied ? "is a" : "is no") + " record");
}
/**
@@ -1024,7 +1013,7 @@ public static ArchCondition beRecords() {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition notBeRecords() {
- return not(RecordsCondition.BE_RECORDS);
+ return not(beRecords());
}
/**
@@ -1142,7 +1131,7 @@ public static ArchCondition containNumberOfEl
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beDeclaredIn(Class> owner) {
- return new IsConditionByPredicate<>(declaredIn(owner));
+ return be(declaredIn(owner));
}
/**
@@ -1159,7 +1148,7 @@ public static ArchCondition notBeDeclaredIn(Class> owner) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition beDeclaredIn(String ownerTypeName) {
- return new IsConditionByPredicate<>(declaredIn(ownerTypeName));
+ return be(declaredIn(ownerTypeName));
}
/**
@@ -1177,7 +1166,7 @@ public static ArchCondition notBeDeclaredIn(String ownerTypeName) {
public static ArchCondition beDeclaredInClassesThat(DescribedPredicate super JavaClass> predicate) {
DescribedPredicate declaredIn = declaredIn(
predicate.as("classes that " + predicate.getDescription()));
- return new IsConditionByPredicate<>(declaredIn);
+ return be(declaredIn);
}
/**
@@ -1187,7 +1176,7 @@ public static ArchCondition beDeclaredInClassesThat(DescribedPredica
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawType(Class> type) {
- return new HaveConditionByPredicate<>(rawType(type));
+ return have(rawType(type));
}
/**
@@ -1195,7 +1184,7 @@ public static ArchCondition haveRawType(Class> type) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawType(String typeName) {
- return new HaveConditionByPredicate<>(rawType(typeName));
+ return have(rawType(typeName));
}
/**
@@ -1203,37 +1192,37 @@ public static ArchCondition haveRawType(String typeName) {
*/
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawType(DescribedPredicate super JavaClass> predicate) {
- return new HaveConditionByPredicate<>(rawType(predicate));
+ return have(rawType(predicate));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawParameterTypes(Class>... parameterTypes) {
- return new HaveConditionByPredicate<>(rawParameterTypes(parameterTypes));
+ return have(rawParameterTypes(parameterTypes));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawParameterTypes(String... parameterTypeNames) {
- return new HaveConditionByPredicate<>(rawParameterTypes(parameterTypeNames));
+ return have(rawParameterTypes(parameterTypeNames));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawParameterTypes(DescribedPredicate super List> predicate) {
- return new HaveConditionByPredicate<>(rawParameterTypes(predicate));
+ return have(rawParameterTypes(predicate));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawReturnType(Class> type) {
- return new HaveConditionByPredicate<>(rawReturnType(type));
+ return have(rawReturnType(type));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawReturnType(String typeName) {
- return new HaveConditionByPredicate<>(rawReturnType(typeName));
+ return have(rawReturnType(typeName));
}
@PublicAPI(usage = ACCESS)
public static ArchCondition haveRawReturnType(DescribedPredicate super JavaClass> predicate) {
- return new HaveConditionByPredicate<>(rawReturnType(predicate));
+ return have(rawReturnType(predicate));
}
@PublicAPI(usage = ACCESS)
@@ -1250,7 +1239,7 @@ public static ArchCondition declareThrowableOfType(String typeName
public static ArchCondition declareThrowableOfType(DescribedPredicate super JavaClass> predicate) {
DescribedPredicate> declareThrowableOfType = throwsClauseContainingType(predicate)
.as("declare throwable of type " + predicate.getDescription());
- return new DoesConditionByPredicate<>(declareThrowableOfType);
+ return does(declareThrowableOfType);
}
@PublicAPI(usage = ACCESS)
@@ -1282,18 +1271,56 @@ public static ArchCondition onlyBeCalledByConstructorsThat(Describ
origin.is(constructor().and(predicate)), GET_CALLS_OF_SELF);
}
- private static final IsConditionByPredicate BE_TOP_LEVEL_CLASSES =
- new IsConditionByPredicate<>("a top level class", JavaClass.Predicates.TOP_LEVEL_CLASSES);
- private static final IsConditionByPredicate BE_NESTED_CLASSES =
- new IsConditionByPredicate<>("a nested class", JavaClass.Predicates.NESTED_CLASSES);
- private static final IsConditionByPredicate BE_MEMBER_CLASSES =
- new IsConditionByPredicate<>("a member class", JavaClass.Predicates.MEMBER_CLASSES);
- private static final IsConditionByPredicate BE_INNER_CLASSES =
- new IsConditionByPredicate<>("an inner class", JavaClass.Predicates.INNER_CLASSES);
- private static final IsConditionByPredicate BE_ANONYMOUS_CLASSES =
- new IsConditionByPredicate<>("an anonymous class", JavaClass.Predicates.ANONYMOUS_CLASSES);
- private static final IsConditionByPredicate BE_LOCAL_CLASSES =
- new IsConditionByPredicate<>("a local class", JavaClass.Predicates.LOCAL_CLASSES);
+ /**
+ * Derives an {@link ArchCondition} from a {@link DescribedPredicate}. Similar to {@link ArchCondition#from(DescribedPredicate)},
+ * but more conveniently creates a message to be used within a 'have'-sentence.
+ *
+ * Take e.g. {@code have(simpleName("Demo"))}, then the condition description would be {@code "have simple name 'Demo'"},
+ * each satisfied event would be described as {@code "Class has simple name 'Demo' in (Example.java:0)"}
+ * and each violated one as {@code "Class does not have simple name 'Demo' in (Example.java:0)"}.
+ *
+ * @param predicate The predicate determining which objects satisfy/violate the condition
+ * @return A {@link ConditionByPredicate ConditionByPredicate} derived from the predicate and with 'have'-descriptions
+ * @param The type of object the condition will test, e.g. a {@link JavaClass}
+ */
+ @PublicAPI(usage = ACCESS)
+ public static ConditionByPredicate have(DescribedPredicate super T> predicate) {
+ return ArchCondition.from(predicate.forSubtype())
+ .as(ArchPredicates.have(predicate).getDescription())
+ .describeEventsBy((predicateDescription, satisfied) -> (satisfied ? "has " : "does not have ") + predicateDescription);
+ }
+
+ /**
+ * Derives an {@link ArchCondition} from a {@link DescribedPredicate}. Similar to {@link ArchCondition#from(DescribedPredicate)},
+ * but more conveniently creates a message to be used within a 'be'-sentence.
+ *
+ * Take e.g. {@code be(assignableTo(Demo.class))}, then the condition description would be {@code "be assignable to com.example.Demo"},
+ * each satisfied event would be described as {@code "Class is assignable to com.example.Demo in (Example.java:0)"}
+ * and each violated one as {@code "Class is not assignable to com.example.Demo in (Example.java:0)"}.
+ *
+ * @param predicate The predicate determining which objects satisfy/violate the condition
+ * @return A {@link ConditionByPredicate ConditionByPredicate} derived from the predicate and with 'be'-descriptions
+ * @param The type of object the condition will test, e.g. a {@link JavaClass}
+ */
+ @PublicAPI(usage = ACCESS)
+ public static ConditionByPredicate be(DescribedPredicate super T> predicate) {
+ return ArchCondition.from(predicate.forSubtype())
+ .as(ArchPredicates.be(predicate).getDescription())
+ .describeEventsBy((predicateDescription, satisfied) -> (satisfied ? "is " : "is not ") + predicateDescription);
+ }
+
+ private static final ArchCondition BE_TOP_LEVEL_CLASSES =
+ be(TOP_LEVEL_CLASSES).describeEventsBy((__, satisfied) -> (satisfied ? "is a" : "is no") + " top level class");
+ private static final ArchCondition BE_NESTED_CLASSES =
+ be(NESTED_CLASSES).describeEventsBy((__, satisfied) -> (satisfied ? "is a" : "is no") + " nested class");
+ private static final ArchCondition BE_MEMBER_CLASSES =
+ be(MEMBER_CLASSES).describeEventsBy((__, satisfied) -> (satisfied ? "is a" : "is no") + " member class");
+ private static final ArchCondition BE_INNER_CLASSES =
+ be(INNER_CLASSES).describeEventsBy((__, satisfied) -> (satisfied ? "is an" : "is no") + " inner class");
+ private static final ArchCondition BE_ANONYMOUS_CLASSES =
+ be(ANONYMOUS_CLASSES).describeEventsBy((__, satisfied) -> (satisfied ? "is an" : "is no") + " anonymous class");
+ private static final ArchCondition BE_LOCAL_CLASSES =
+ be(LOCAL_CLASSES).describeEventsBy((__, satisfied) -> (satisfied ? "is a" : "is no") + " local class");
private static class HaveOnlyModifiersCondition
extends AllAttributesMatchCondition {
@@ -1301,7 +1328,7 @@ private static class HaveOnlyModifiersCondition> getHasModifiers;
HaveOnlyModifiersCondition(String description, final JavaModifier modifier, Function> getHasModifiers) {
- super("have only " + description, new ModifierCondition<>(modifier));
+ super("have only " + description, be(modifier(modifier).as(modifier.toString().toLowerCase())));
this.getHasModifiers = getHasModifiers;
}
@@ -1311,89 +1338,6 @@ Collection relevantAttributes(JavaClass javaClass) {
}
}
- private static class ModifierCondition extends ArchCondition {
- private final JavaModifier modifier;
-
- ModifierCondition(JavaModifier modifier) {
- super("modifier " + modifier);
- this.modifier = modifier;
- }
-
- @Override
- public void check(T hasModifiers, ConditionEvents events) {
- boolean satisfied = hasModifiers.getModifiers().contains(modifier);
- String infix = (satisfied ? "is " : "is not ") + modifier.toString().toLowerCase();
- events.add(new SimpleConditionEvent(hasModifiers, satisfied, createMessage(hasModifiers, infix)));
- }
- }
-
- private static class ImplementsCondition extends ArchCondition {
- private final DescribedPredicate super JavaClass> implement;
-
- ImplementsCondition(DescribedPredicate super JavaClass> implement) {
- super(implement.getDescription());
- this.implement = implement;
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean satisfied = implement.test(javaClass);
- String description = satisfied
- ? implement.getDescription().replace("implement", "implements")
- : implement.getDescription().replace("implement", "does not implement");
- String message = createMessage(javaClass, description);
- events.add(new SimpleConditionEvent(javaClass, satisfied, message));
- }
- }
-
- private static class InterfacesCondition extends ArchCondition {
- private static final InterfacesCondition BE_INTERFACES = new InterfacesCondition();
-
- InterfacesCondition() {
- super("be interfaces");
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean isInterface = javaClass.isInterface();
- String message = createMessage(javaClass,
- (isInterface ? "is an" : "is not an") + " interface");
- events.add(new SimpleConditionEvent(javaClass, isInterface, message));
- }
- }
-
- private static class EnumsCondition extends ArchCondition {
- private static final EnumsCondition BE_ENUMS = new EnumsCondition();
-
- EnumsCondition() {
- super("be enums");
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean isEnum = javaClass.isEnum();
- String message = createMessage(javaClass,
- (isEnum ? "is an" : "is not an") + " enum");
- events.add(new SimpleConditionEvent(javaClass, isEnum, message));
- }
- }
-
- private static class RecordsCondition extends ArchCondition {
- private static final RecordsCondition BE_RECORDS = new RecordsCondition();
-
- RecordsCondition() {
- super("be records");
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean isRecord = javaClass.isRecord();
- String message = createMessage(javaClass,
- (isRecord ? "is a" : "is not a") + " record");
- events.add(new SimpleConditionEvent(javaClass, isRecord, message));
- }
- }
-
private static class NumberOfElementsCondition extends ArchCondition {
private final DescribedPredicate predicate;
private final SortedSet allElementNames = new TreeSet<>();
@@ -1421,238 +1365,8 @@ private String join(SortedSet strings) {
}
}
- private static class BeClassCondition extends ArchCondition {
- private final String className;
-
- BeClassCondition(String className) {
- super("be " + className);
- this.className = className;
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean itemEquivalentToClazz = javaClass.getName().equals(className);
- String message = createMessage(javaClass,
- (itemEquivalentToClazz ? "is " : "is not ") + className);
- events.add(new SimpleConditionEvent(javaClass, itemEquivalentToClazz, message));
- }
- }
-
- private static class SimpleNameCondition extends ArchCondition {
- private final DescribedPredicate haveSimpleName;
- private final String name;
-
- SimpleNameCondition(DescribedPredicate haveSimpleName, String name) {
- super(haveSimpleName.getDescription());
- this.haveSimpleName = haveSimpleName;
- this.name = name;
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean satisfied = haveSimpleName.test(javaClass);
- String message = createMessage(javaClass,
- String.format("%s simple name '%s'", satisfied ? "has" : "does not have", name));
- events.add(new SimpleConditionEvent(javaClass, satisfied, message));
- }
- }
-
- private static class SimpleNameStartingWithCondition extends ArchCondition {
- private final DescribedPredicate predicate;
- private final String prefix;
-
- SimpleNameStartingWithCondition(DescribedPredicate predicate, String prefix) {
- super(predicate.getDescription());
- this.predicate = predicate;
- this.prefix = prefix;
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean satisfied = predicate.test(javaClass);
- String message = String.format("simple name of %s %s with '%s' in %s",
- javaClass.getName(),
- satisfied ? "starts" : "does not start",
- prefix,
- javaClass.getSourceCodeLocation());
- events.add(new SimpleConditionEvent(javaClass, satisfied, message));
- }
- }
-
- private static class SimpleNameContainingCondition extends ArchCondition {
- private final DescribedPredicate predicate;
- private final String infix;
-
- SimpleNameContainingCondition(DescribedPredicate predicate, String infix) {
- super(predicate.getDescription());
- this.predicate = predicate;
- this.infix = infix;
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean satisfied = predicate.test(javaClass);
- String message = String.format("simple name of %s %s '%s' in %s",
- javaClass.getName(),
- satisfied ? "contains" : "does not contain",
- infix,
- javaClass.getSourceCodeLocation());
- events.add(new SimpleConditionEvent(javaClass, satisfied, message));
- }
- }
-
- private static class SimpleNameEndingWithCondition extends ArchCondition {
- private final DescribedPredicate predicate;
- private final String suffix;
-
- SimpleNameEndingWithCondition(DescribedPredicate predicate, String suffix) {
- super(predicate.getDescription());
- this.predicate = predicate;
- this.suffix = suffix;
- }
-
- @Override
- public void check(JavaClass javaClass, ConditionEvents events) {
- boolean satisfied = predicate.test(javaClass);
- String message = String.format("simple name of %s %s with '%s' in %s",
- javaClass.getName(),
- satisfied ? "ends" : "does not end",
- suffix,
- javaClass.getSourceCodeLocation());
- events.add(new SimpleConditionEvent(javaClass, satisfied, message));
- }
- }
-
- private static class MatchingCondition extends ArchCondition {
- private final DescribedPredicate matcher;
- private final String regex;
-
- MatchingCondition(DescribedPredicate matcher, String regex) {
- super(matcher.getDescription());
- this.matcher = matcher;
- this.regex = regex;
- }
-
- @Override
- public void check(T item, ConditionEvents events) {
- boolean satisfied = matcher.test(item);
- String message = createMessage(item,
- String.format("%s '%s'", satisfied ? "matches" : "does not match", regex));
- events.add(new SimpleConditionEvent(item, satisfied, message));
- }
- }
-
- private static class StartingCondition extends ArchCondition {
- private final DescribedPredicate startingWith;
- private final String prefix;
-
- StartingCondition(DescribedPredicate startingWith, String prefix) {
- super(startingWith.getDescription());
- this.startingWith = startingWith;
- this.prefix = prefix;
- }
-
- @Override
- public void check(T item, ConditionEvents events) {
- boolean satisfied = startingWith.test(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 extends ArchCondition {
- private final DescribedPredicate containing;
- private final String infix;
-
- ContainingCondition(DescribedPredicate containing, String infix) {
- super(containing.getDescription());
- this.containing = containing;
- this.infix = infix;
- }
-
- @Override
- public void check(T item, ConditionEvents events) {
- boolean satisfied = containing.test(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 extends ArchCondition {
- private final DescribedPredicate endingWith;
- private final String suffix;
-
- EndingCondition(DescribedPredicate endingWith, String suffix) {
- super(endingWith.getDescription());
- this.endingWith = endingWith;
- this.suffix = suffix;
- }
-
- @Override
- public void check(T item, ConditionEvents events) {
- boolean satisfied = endingWith.test(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
- extends ArchCondition {
- private final DescribedPredicate super T> predicate;
-
- DoesConditionByPredicate(DescribedPredicate super T> predicate) {
- super(predicate.getDescription());
- this.predicate = predicate;
- }
-
- @Override
- public void check(T item, ConditionEvents events) {
- boolean satisfied = predicate.test(item);
- String message = createMessage(item,
- (satisfied ? "does " : "does not ") + predicate.getDescription());
- events.add(new SimpleConditionEvent(item, satisfied, message));
- }
- }
-
- private static class IsConditionByPredicate extends ArchCondition {
- private final String eventDescription;
- private final DescribedPredicate predicate;
-
- IsConditionByPredicate(DescribedPredicate super T> predicate) {
- this(predicate.getDescription(), predicate);
- }
-
- IsConditionByPredicate(String eventDescription, DescribedPredicate super T> predicate) {
- super(ArchPredicates.be(predicate).getDescription());
- this.eventDescription = eventDescription;
- this.predicate = predicate.forSubtype();
- }
-
- @Override
- public void check(T member, ConditionEvents events) {
- boolean satisfied = predicate.test(member);
- String message = createMessage(member,
- (satisfied ? "is " : "is not ") + eventDescription);
- events.add(new SimpleConditionEvent(member, satisfied, message));
- }
- }
-
- private static class HaveConditionByPredicate extends ArchCondition {
- private final DescribedPredicate