Skip to content

Commit

Permalink
GH-253 - Fix verifications for aggregate references as collection ele…
Browse files Browse the repository at this point in the history
…ments.

Original pull request: GH-254.
  • Loading branch information
etrandafir93 authored and odrotbohm committed Sep 25, 2024
1 parent 054fc5f commit 1d7ed8f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaField;
import com.tngtech.archunit.core.domain.JavaParameterizedType;
import com.tngtech.archunit.core.domain.JavaType;
import com.tngtech.archunit.core.domain.properties.CanBeAnnotated;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
Expand All @@ -58,7 +60,8 @@
* @author Oliver Drotbohm
* @author Torsten Juergeleit
* @author Hasan Kara
* @see <a href="http://scabl.blogspot.com/2015/04/aeddd-9.html">Advancing Enterprise DDD - Reinstating the Aggregate</a>
* @see <a href="http://scabl.blogspot.com/2015/04/aeddd-9.html">Advancing Enterprise DDD - Reinstating the
* Aggregate</a>
*/
public class JMoleculesDddRules {

Expand Down Expand Up @@ -146,7 +149,8 @@ public static ArchRule entitiesShouldBeDeclaredForUseInSameAggregate() {
public static ArchRule aggregateReferencesShouldBeViaIdOrAssociation() {

DescribedPredicate<JavaField> referenceAnAggregateRoot = areAssignableTo(AggregateRoot.class)
.or(hasFieldTypeAnnotatedWith(org.jmolecules.ddd.annotation.AggregateRoot.class));
.or(hasFieldTypeAnnotatedWith(org.jmolecules.ddd.annotation.AggregateRoot.class))
.or(hasParameterizedFieldOfTypeAnnotatedWith(org.jmolecules.ddd.annotation.AggregateRoot.class));

return ArchRuleDefinition.fields() //
.that(new OwnerMatches(IS_IDENTIFIABLE).and(referenceAnAggregateRoot)) //
Expand Down Expand Up @@ -194,6 +198,11 @@ private static FieldTypeIsAnnotatedWith hasFieldTypeAnnotatedWith(Class<? extend
return new FieldTypeIsAnnotatedWith(type);
}

private static DescribedPredicate<? super JavaField> hasParameterizedFieldOfTypeAnnotatedWith(
Class<? extends Annotation> type) {
return new ParameterizedFieldOfTypeAnnotatedWith(type);
}

private static class IsDeclaredToUseTheSameAggregate extends ArchCondition<JavaField> {

private static final ResolvableType COLLECTION_TYPE = ResolvableType.forClass(Collection.class);
Expand Down Expand Up @@ -284,6 +293,37 @@ public boolean test(JavaField input) {
}
}

private static class ParameterizedFieldOfTypeAnnotatedWith extends DescribedPredicate<JavaField> {

private final DescribedPredicate<CanBeAnnotated> isAnnotatedWith;

public ParameterizedFieldOfTypeAnnotatedWith(Class<? extends Annotation> type) {

super("is collection of type annotated with %s", type.getSimpleName());

this.isAnnotatedWith = CanBeAnnotated.Predicates.annotatedWith(type);
}

/*
* (non-Javadoc)
* @see java.util.function.Predicate#test(java.lang.Object)
*/
@Override
public boolean test(JavaField input) {

if (!(input.getType() instanceof JavaParameterizedType)) {
return false;
}

JavaParameterizedType parameterizedType = (JavaParameterizedType) input.getType();

return parameterizedType.getActualTypeArguments()
.stream()
.map(JavaType::toErasure)
.anyMatch(isAnnotatedWith);
}
}

private static class IsAssignableTypeField extends DescribedPredicate<JavaField> {

private static final ResolvableType COLLECTION_TYPE = ResolvableType.forClass(Collection.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ void detectsViolations(JavaClasses classes) {
violation(SampleValueObject.class, "annotatedEntity", AnnotatedEntity.class, null),
violation(SampleValueObject.class, "aggregate", SampleAggregate.class, null),
violation(SampleValueObject.class, "annotatedAggregate", AnnotatedAggregate.class, null),
violation(SampleGrandChildEntity.class, "otherEntity", OtherEntity.class, OtherAggregate.class) // GH-222
violation(SampleGrandChildEntity.class, "otherEntity", OtherEntity.class, OtherAggregate.class), // GH-222
violation(OtherAnnotatedAggregate.class, "invalidAnnotatedAggregate", AnnotatedAggregate.class, null), //
violation(OtherAnnotatedAggregate.class, "invalidAnnotatedAggregateInCollection", Collection.class,
Association.class), //
violation(OtherAnnotatedAggregate.class, "invalidAnnotatedAggregateInMap", Map.class, Association.class) //
);
}

Expand Down Expand Up @@ -123,4 +127,20 @@ static class SampleValueObject implements ValueObject {
SampleAggregate aggregate;
AnnotatedAggregate annotatedAggregate;
}

@org.jmolecules.ddd.annotation.AggregateRoot
static class OtherAnnotatedAggregate {

@org.jmolecules.ddd.annotation.Identity Long id;
AnnotatedAggregate invalidAnnotatedAggregate;
Collection<AnnotatedAggregate> invalidAnnotatedAggregateInCollection;
Map<String, AnnotatedAggregate> invalidAnnotatedAggregateInMap;
}

@org.jmolecules.ddd.annotation.AggregateRoot
static class ThirdAnnotatedAggregate {

@org.jmolecules.ddd.annotation.Identity Long id;
AnnotatedEntity valid;
}
}

0 comments on commit 1d7ed8f

Please sign in to comment.