Class ArchModules<DESCRIPTOR extends ArchModule.Descriptor>
- All Implemented Interfaces:
Iterable<ArchModule<DESCRIPTOR>>,Collection<ArchModule<DESCRIPTOR>>
"architectural modules". This class provides a convenient API to partition the classes
of a code base into (cohesive) modules and assert properties of these modules, e.g. their dependencies to each other or dependencies
not contained in any of the constructed modules.This class provides several entry points to create
modules from a set of classes:defineBy(IdentifierAssociation)- the most generic/flexible APIdefineByPackages(String)- an API similar toSlices.matching(String)defineByRootClasses(Predicate)- an API that derives modules from the packages of some specific classesdefineByAnnotation(Class)- a convenience API fordefineByRootClasses(Predicate)that picks the relevant classes by looking for an annotation
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classAn element of the fluent API to createArchModulesstatic classAn element of the fluent API to createArchModulesstatic interfaceA generic interface to be extended by users for providing custom implementations ofArchModule.Descriptorthat can carry along more meta-information from the modularizedJavaClasses.static interfaceDefines whichclassesbelong to the sameArchModule.Identifierand thus will eventually end up in the sameArchModule.static interfaceA more convenientArchModules.DescriptorCreatortailored to the case that wedefine our modules by root classes. -
Method Summary
Modifier and TypeMethodDescriptionstatic ArchModules.CreatordefineBy(ArchModules.IdentifierAssociation identifierFunction) static <A extends Annotation>
ArchModules.Creator.WithGenericDescriptor<AnnotationDescriptor<A>>defineByAnnotation(Class<A> annotationType) Same asdefineByAnnotation(Class, Function), but the name will be automatically derived from thenameattribute of the respective annotation.static <A extends Annotation>
ArchModules.Creator.WithGenericDescriptor<AnnotationDescriptor<A>>defineByAnnotation(Class<A> annotationType, Function<A, String> nameFunction) Entrypoint to createArchModulesby partitioning a set ofclassesinto packages defined by "root classes" containing annotations of the givenannotationType.static ArchModules.CreatordefineByPackages(String packageIdentifier) Entrypoint to createArchModulesby partitioning a set ofclassesinto specific packages matching the suppliedpackageIdentifierinterpreted asPackageMatcher.
Partitioning is done according to capturing groups.defineByRootClasses(Predicate<? super JavaClass> rootClassPredicate) Entrypoint to createArchModulesby partitioning a set ofclassesinto packages defined by specific "root classes".protected Collection<ArchModule<DESCRIPTOR>>delegate()getByIdentifier(String... identifier) getNames()tryGetByIdentifier(String... identifier) tryGetByName(String name) Methods inherited from class com.tngtech.archunit.base.ForwardingCollection
add, addAll, clear, contains, containsAll, equals, hashCode, isEmpty, iterator, remove, removeAll, retainAll, size, toArray, toArray, toStringMethods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, waitMethods inherited from interface java.util.Collection
parallelStream, removeIf, spliterator, stream, toArray
-
Method Details
-
delegate
- Specified by:
delegatein classForwardingCollection<ArchModule<DESCRIPTOR extends ArchModule.Descriptor>>
-
getByIdentifier
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public ArchModule<DESCRIPTOR> getByIdentifier(String... identifier) - Parameters:
identifier- The (textual) parts of anArchModule.Identifier.- Returns:
- The contained
ArchModulehaving anArchModule.Identifiercomprised of the passedidentifierparts. This method will throw an exception if no matchingArchModuleis contained.
-
tryGetByIdentifier
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public Optional<ArchModule<DESCRIPTOR>> tryGetByIdentifier(String... identifier) - Parameters:
identifier- The (textual) parts of anArchModule.Identifier.- Returns:
- The contained
ArchModulehaving anArchModule.Identifiercomprised of the passedidentifierparts, orOptional.empty()if no matchingArchModuleis contained.
-
getByName
- Parameters:
name- The name of anArchModule- Returns:
- A contained
ArchModulewith the passedname. This method will throw an exception if no matchingArchModuleis contained. - See Also:
-
tryGetByName
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public Optional<ArchModule<DESCRIPTOR>> tryGetByName(String name) - Parameters:
name- The name of anArchModule- Returns:
- A contained
ArchModulewith the passedname, orOptional.empty()if no matchingArchModuleis contained. - See Also:
-
getNames
- Returns:
- The names of all
modulescontained within theseArchModules
-
defineByPackages
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public static ArchModules.Creator defineByPackages(String packageIdentifier) Entrypoint to createArchModulesby partitioning a set ofclassesinto specific packages matching the suppliedpackageIdentifierinterpreted asPackageMatcher.
Partitioning is done according to capturing groups. For exampleSuppose there are three classes:
com.example.module.one.SomeClass
com.example.module.one.AnotherClass
com.example.module.two.YetAnotherClass
If modules are created by specifying
ArchModules.defineByPackages("..module.(*)..").modularize(javaClasses)
then the result will be twomodules, themodulewhere the capturing group is 'one' and themodulewhere the capturing group is 'two'. The firstmodulewill have anArchModule.Identifierconsisting of the single string"one", while the latter will have anArchModule.Identifierconsisting of the single string"two". If multiple packages would be matched, e.g. by"..module.(*).(*)..", the respectiveArchModule.Identifierwould contain the two matched (sub-)package names as itsparts.- Parameters:
packageIdentifier- Apackage identifier- Returns:
- A fluent API to further customize how to create
ArchModules
-
defineByRootClasses
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public static ArchModules.CreatorByRootClass defineByRootClasses(Predicate<? super JavaClass> rootClassPredicate) Entrypoint to createArchModulesby partitioning a set ofclassesinto packages defined by specific "root classes". TherootClassPredicatewill determine whichclassesare root classes.ArchModulesare formed by grouping together all classes that reside in the same package or a subpackage of the respective root class. Thus, the packages of the defined root classes may not overlap, i.e. no root class must reside in the same or a subpackage of another root class. Allclassesnot contained in any package induced by a root class will be ignored from the derivedArchModules.
Take for example the following three classes:
com.example.module.one.SomeClass
com.example.module.one.AnotherClass
com.example.module.two.SomeOtherClass
Then therootClassPredicate
would pick the classesjavaClass -> javaClass.getSimpleName().startsWith("Some")SomeClassandSomeOtherClassand derive theArchModulesfrom their packages, which in turn would putSomeClassandAnotherClassin the sameArchModulederived fromSomeClass.- Parameters:
rootClassPredicate- APredicatedetermining whichJavaClassis a "root class", thus defining aArchModuleby its package- Returns:
- A fluent API to further customize how to create
ArchModules
-
defineByAnnotation
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public static <A extends Annotation> ArchModules.Creator.WithGenericDescriptor<AnnotationDescriptor<A>> defineByAnnotation(Class<A> annotationType) Same asdefineByAnnotation(Class, Function), but the name will be automatically derived from thenameattribute of the respective annotation. I.e. to use this method the respective annotation must provide a name like in the following example:
In case the respective@SomeExample(name = "Example Module") class SomeClass {}annotationTypedoesn't offer a name attribute like this please refer todefineByAnnotation(Class, Function)instead. -
defineByAnnotation
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public static <A extends Annotation> ArchModules.Creator.WithGenericDescriptor<AnnotationDescriptor<A>> defineByAnnotation(Class<A> annotationType, Function<A, String> nameFunction) Entrypoint to createArchModulesby partitioning a set ofclassesinto packages defined by "root classes" containing annotations of the givenannotationType. This is basically a convenience function fordefineByRootClasses(Predicate)where thePredicateexactly identifies classes carrying the passedannotationTypeand the annotation will be carried forward into the derivedArchModules by the derivedAnnotationDescriptor.
Take for example the following three classes:
@SomeAnnotation com.example.module.one.SomeClass
com.example.module.one.AnotherClass
@SomeAnnotation com.example.module.two.YetAnotherClass
Then
would pick the classesArchModules.defineByAnnotation(SomeAnnotation.class).modularize(javaClasses)SomeClassandYetAnotherClass, since they are annotated withSomeAnnotation, and derive theArchModulesfrom their packages. This in turn would putSomeClassandAnotherClassin the sameArchModulederived fromSomeClass. The finalArchModulewould have adescriptorof typeAnnotationDescriptorfrom which the specificAnnotation(i.e. instance of@SomeAnnotation) onSomeClassorYetAnotherClasscould be obtained.
As withdefineByRootClasses(Predicate)users of this method must make sure that packages of the classes annotated with the givenannotationTypedon't overlap.- Parameters:
annotationType- The type ofAnnotationdefining whichJavaClassis a root classnameFunction- A function determining how to derive themodule namefrom the respective annotation- Returns:
- A fluent API to further customize how to create
ArchModules
-
defineBy
@PublicAPI(usage=ACCESS, state=EXPERIMENTAL) public static ArchModules.Creator defineBy(ArchModules.IdentifierAssociation identifierFunction) Entrypoint to createArchModulesby a generic mapping functionJavaClass->ArchModule.Identifier. Allclassesthat are mapped to the sameArchModule.Identifierwill end up in the sameArchModule.
A simple example would be theidentifierFunction
This would then create onejavaClass -> ArchModule.Identifier.from(javaClass.getPackageName())ArchModulefor each full package name and eachJavaClasswould be contained in theArchModulewhere theArchModule.Identifiercoincides with the class's full package name.- Parameters:
identifierFunction- A function defining how eachJavaClassis mapped to the respectiveArchModule.Identifier- Returns:
- A fluent API to further customize how to create
ArchModules
-