diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java index b02102a4b6..6c7019a8d0 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java @@ -63,7 +63,9 @@ static Dependency from(JavaAccess access) { } static Dependency fromInheritance(JavaClass origin, JavaClass targetSuperType) { - String originDescription = origin.getDescription(); + String originType = origin.isInterface() ? "Interface" : "Class"; + String originDescription = originType + " " + bracketFormat(origin.getName()); + String dependencyType = !origin.isInterface() && targetSuperType.isInterface() ? "implements" : "extends"; String targetType = targetSuperType.isInterface() ? "interface" : "class"; diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java index 34902af53f..12022a44d6 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java @@ -81,7 +81,8 @@ public class JavaClass implements HasName.AndFullName, HasAnnotations, HasModifi private final Set interfaces = new HashSet<>(); private final Set subClasses = new HashSet<>(); private Optional enclosingClass = Optional.absent(); - private Map annotations = Collections.emptyMap(); + private Supplier> annotations = + Suppliers.ofInstance(Collections.emptyMap()); private Supplier> allMethods; private Supplier> allConstructors; private Supplier> allFields; @@ -121,8 +122,7 @@ public SourceCodeLocation getSourceCodeLocation() { @Override public String getDescription() { - String originType = isInterface() ? "Interface" : "Class"; - return originType + " <" + getName() + ">"; + return "Class <" + getName() + ">"; } @Override @@ -191,12 +191,12 @@ public boolean isAnnotatedWith(Class annotationType) { @Override public boolean isAnnotatedWith(String annotationTypeName) { - return annotations.containsKey(annotationTypeName); + return annotations.get().containsKey(annotationTypeName); } @Override public boolean isAnnotatedWith(DescribedPredicate predicate) { - return CanBeAnnotated.Utils.isAnnotatedWith(annotations.values(), predicate); + return CanBeAnnotated.Utils.isAnnotatedWith(annotations.get().values(), predicate); } @Override @@ -211,7 +211,7 @@ public boolean isMetaAnnotatedWith(String typeName) { @Override public boolean isMetaAnnotatedWith(DescribedPredicate predicate) { - return CanBeAnnotated.Utils.isMetaAnnotatedWith(annotations.values(), predicate); + return CanBeAnnotated.Utils.isMetaAnnotatedWith(annotations.get().values(), predicate); } /** @@ -234,7 +234,7 @@ public JavaAnnotation getAnnotationOfType(String typeName) { @Override public Set getAnnotations() { - return ImmutableSet.copyOf(annotations.values()); + return ImmutableSet.copyOf(annotations.get().values()); } /** @@ -254,7 +254,7 @@ public Optional tryGetAnnotationOfType(Class type) */ @Override public Optional tryGetAnnotationOfType(String typeName) { - return Optional.fromNullable(annotations.get(typeName)); + return Optional.fromNullable(annotations.get().get(typeName)); } @PublicAPI(usage = ACCESS) @@ -805,7 +805,12 @@ void completeMembers(final ImportContext context) { .addAll(methods) .addAll(constructors) .build(); - annotations = context.createAnnotations(this); + this.annotations = Suppliers.memoize(new Supplier>() { + @Override + public Map get() { + return context.createAnnotations(JavaClass.this); + } + }); } CompletionProcess completeFrom(ImportContext context) { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java index 5eed8d103a..5c4cd02f80 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; +import com.google.common.base.Supplier; import com.google.common.collect.ImmutableSet; import com.tngtech.archunit.Internal; import com.tngtech.archunit.PublicAPI; @@ -31,9 +32,9 @@ import com.tngtech.archunit.core.domain.properties.HasDescriptor; import com.tngtech.archunit.core.domain.properties.HasModifiers; import com.tngtech.archunit.core.domain.properties.HasName; -import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.domain.properties.HasOwner; import com.tngtech.archunit.core.domain.properties.HasOwner.Functions.Get; +import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.importer.DomainBuilders.JavaMemberBuilder; import static com.google.common.base.Preconditions.checkNotNull; @@ -48,7 +49,7 @@ public abstract class JavaMember implements private final String name; private final String descriptor; - private final Map annotations; + private final Supplier> annotations; private final JavaClass owner; private final SourceCodeLocation sourceCodeLocation; private final Set modifiers; @@ -64,7 +65,7 @@ public abstract class JavaMember implements @Override public Set getAnnotations() { - return ImmutableSet.copyOf(annotations.values()); + return ImmutableSet.copyOf(annotations.get().values()); } /** @@ -91,7 +92,7 @@ public Optional tryGetAnnotationOfType(Class type) @Override public Optional tryGetAnnotationOfType(String typeName) { - return Optional.fromNullable(annotations.get(typeName)); + return Optional.fromNullable(annotations.get().get(typeName)); } @Override @@ -101,12 +102,12 @@ public boolean isAnnotatedWith(Class type) { @Override public boolean isAnnotatedWith(String typeName) { - return annotations.containsKey(typeName); + return annotations.get().containsKey(typeName); } @Override public boolean isAnnotatedWith(DescribedPredicate predicate) { - return CanBeAnnotated.Utils.isAnnotatedWith(annotations.values(), predicate); + return CanBeAnnotated.Utils.isAnnotatedWith(annotations.get().values(), predicate); } @Override @@ -121,7 +122,7 @@ public boolean isMetaAnnotatedWith(String typeName) { @Override public boolean isMetaAnnotatedWith(DescribedPredicate predicate) { - return CanBeAnnotated.Utils.isMetaAnnotatedWith(annotations.values(), predicate); + return CanBeAnnotated.Utils.isMetaAnnotatedWith(annotations.get().values(), predicate); } @Override diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java index d72e9601e9..9b2687360b 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java @@ -95,6 +95,7 @@ JavaClasses complete() { ensureCallTargetsArePresent(); ensureClassHierarchies(); completeMembers(); + completeAnnotations(); for (RawAccessRecord.ForField fieldAccessRecord : importRecord.getRawFieldAccessRecords()) { tryProcess(fieldAccessRecord, AccessRecord.Factory.forFieldAccessRecord(), processedFieldAccessRecords); } @@ -142,6 +143,12 @@ private void completeMembers() { } } + private void completeAnnotations() { + for (JavaClass javaClass : classes.getAll().values()) { + javaClass.getAnnotations(); + } + } + private , B extends RawAccessRecord> void tryProcess( B rawRecord, AccessRecord.Factory factory, diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java index c40dfd8976..d014c6464e 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java @@ -154,8 +154,13 @@ public String getName() { return name; } - public Map getAnnotations() { - return buildAnnotations(owner, annotations, importedClasses); + public Supplier> getAnnotations() { + return Suppliers.memoize(new Supplier>() { + @Override + public Map get() { + return buildAnnotations(owner, annotations, importedClasses); + } + }); } public String getDescriptor() { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java index d9e72e0550..b6da1a1bbf 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java @@ -77,7 +77,7 @@ public void Dependency_from_annotation_on_class() { assertThat(dependency.getOriginClass()).matches(ClassWithDependencyOnAnnotation.class); assertThat(dependency.getTargetClass()).matches(annotationClass); assertThat(dependency.getDescription()).as("description") - .contains("Class <" + origin.getName() + "> has annotation <" + annotationClass.getName() + ">"); + .contains("Class <" + origin.getName() + "> is annotated with <" + annotationClass.getName() + ">"); origin = importClassesWithContext(InterfaceWithDependencyOnAnnotation.class, SomeAnnotation.class) .get(InterfaceWithDependencyOnAnnotation.class); @@ -86,7 +86,7 @@ public void Dependency_from_annotation_on_class() { assertThat(dependency.getOriginClass()).matches(InterfaceWithDependencyOnAnnotation.class); assertThat(dependency.getTargetClass()).matches(annotationClass); assertThat(dependency.getDescription()).as("description") - .contains("Interface <" + origin.getName() + "> has annotation <" + annotationClass.getName() + ">"); + .contains("Class <" + origin.getName() + "> is annotated with <" + annotationClass.getName() + ">"); } @Test @@ -102,7 +102,7 @@ public void Dependency_from_annotation_on_member() { assertThat(dependency.getOriginClass()).matches(ClassWithAnnotatedField.class); assertThat(dependency.getTargetClass()).matches(annotationClass); assertThat(dependency.getDescription()).as("description") - .contains(origin.getDescription() + " has annotation <" + annotationClass.getName() + ">"); + .contains(origin.getDescription() + " is annotated with <" + annotationClass.getName() + ">"); } @Test