Skip to content

Commit

Permalink
mark new modules API as EXPERIMENTAL
Browse files Browse the repository at this point in the history
This gives us the chance to easier break it if necessary, in case we find some really bad oversight somewhere.

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
  • Loading branch information
codecholeric committed Aug 25, 2023
1 parent 2a4e015 commit 794d4f2
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,31 @@
import com.tngtech.archunit.PublicAPI;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.tngtech.archunit.PublicAPI.State.EXPERIMENTAL;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;

/**
* An {@link ArchModule.Descriptor} that carries along a specific {@link Annotation}.
* @param <A> The type of {@link Annotation} this {@link ArchModule.Descriptor} contains
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public final class AnnotationDescriptor<A extends Annotation> implements ArchModule.Descriptor {
private final String name;
private final A annotation;

@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public AnnotationDescriptor(String moduleName, A annotation) {
this.name = checkNotNull(moduleName);
this.annotation = checkNotNull(annotation);
}

@Override
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public String getName() {
return name;
}

@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public A getAnnotation() {
return annotation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.tngtech.archunit.PublicAPI.State.EXPERIMENTAL;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
import static com.tngtech.archunit.PublicAPI.Usage.INHERITANCE;
import static java.util.Collections.emptyList;
Expand All @@ -53,7 +54,7 @@
* <br><br>
* To create {@link ArchModule}s please refer to {@link ArchModules}.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public final class ArchModule<DESCRIPTOR extends ArchModule.Descriptor> extends ForwardingSet<JavaClass> implements HasName {
private final Identifier identifier;
private final DESCRIPTOR descriptor;
Expand Down Expand Up @@ -98,7 +99,7 @@ protected Set<JavaClass> delegate() {
/**
* @return The {@link Identifier} of this module
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Identifier getIdentifier() {
return identifier;
}
Expand All @@ -107,15 +108,15 @@ public Identifier getIdentifier() {
* @return The name of this module, i.e. a human-readable string representing this module
*/
@Override
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public String getName() {
return descriptor.getName();
}

/**
* @return The {@link ArchModule.Descriptor} of this {@link ArchModule}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public DESCRIPTOR getDescriptor() {
return descriptor;
}
Expand All @@ -124,7 +125,7 @@ public DESCRIPTOR getDescriptor() {
* @return All {@link Dependency dependencies} where the {@link Dependency#getOriginClass() origin class}
* is contained within this {@link ArchModule}.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Set<Dependency> getClassDependenciesFromSelf() {
return classDependenciesFromSelf;
}
Expand All @@ -133,7 +134,7 @@ public Set<Dependency> getClassDependenciesFromSelf() {
* @return All {@link Dependency dependencies} where the {@link Dependency#getTargetClass() target class}
* is contained within this {@link ArchModule}.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Set<Dependency> getClassDependenciesToSelf() {
return classDependenciesToSelf.get();
}
Expand All @@ -142,7 +143,7 @@ public Set<Dependency> getClassDependenciesToSelf() {
* @return All {@link ModuleDependency module dependencies} where the {@link ModuleDependency#getOrigin() origin}
* equals this {@link ArchModule}.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Set<ModuleDependency<DESCRIPTOR>> getModuleDependenciesFromSelf() {
return moduleDependenciesFromSelf;
}
Expand All @@ -151,12 +152,12 @@ public Set<ModuleDependency<DESCRIPTOR>> getModuleDependenciesFromSelf() {
* @return All {@link ModuleDependency module dependencies} where the {@link ModuleDependency#getTarget() target}
* equals this {@link ArchModule}.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Set<ModuleDependency<DESCRIPTOR>> getModuleDependenciesToSelf() {
return moduleDependenciesToSelf;
}

@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Set<Dependency> getUndefinedDependencies() {
return undefinedDependencies;
}
Expand Down Expand Up @@ -191,7 +192,7 @@ public String toString() {
* uniquely identifies an {@link ArchModule}, i.e. two {@link ArchModule modules} are equal, if and only if
* their identifier is equal (i.e. all the textual parts of the identifier match in order).
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static final class Identifier implements Iterable<String> {
private final List<String> parts;

Expand All @@ -202,7 +203,7 @@ private Identifier(List<String> parts) {
/**
* @see #from(List)
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static Identifier from(String... parts) {
return from(ImmutableList.copyOf(parts));
}
Expand All @@ -211,7 +212,7 @@ public static Identifier from(String... parts) {
* @param parts The textual parts of the {@link Identifier}, must not be empty
* @return An {@link Identifier} consisting of the passed {@code parts}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static Identifier from(List<String> parts) {
checkArgument(!parts.isEmpty(), "Parts may not be empty");
return new Identifier(parts);
Expand All @@ -224,15 +225,15 @@ public static Identifier from(List<String> parts) {
*
* @return An {@link Identifier} that signals that this {@link ArchModule} is irrelevant and should be ignored.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static Identifier ignore() {
return new Identifier(emptyList());
}

/**
* @return The number of (textual) parts this identifier consists of.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public int getNumberOfParts() {
return parts.size();
}
Expand All @@ -241,7 +242,7 @@ public int getNumberOfParts() {
* @param index Index of the requested (textual) part
* @return Part with the given index; indices are 1-based (i.e. {@link #getPart(int) getPart(1)}) returns the first part.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public String getPart(int index) {
checkArgument(index >= 1 && index <= parts.size(), "Index %d is out of bounds", index);
return parts.get(index - 1);
Expand All @@ -252,7 +253,7 @@ boolean shouldBeConsidered() {
}

@Override
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Iterator<String> iterator() {
return parts.iterator();
}
Expand Down Expand Up @@ -299,7 +300,7 @@ public interface Descriptor {
* @param name The name of the described {@link ArchModule}
* @return A {@link Descriptor} carrying the passed {@code name}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
static Descriptor create(final String name) {
return () -> name;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Multimaps.asMap;
import static com.google.common.collect.Multimaps.toMultimap;
import static com.tngtech.archunit.PublicAPI.State.EXPERIMENTAL;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
import static com.tngtech.archunit.PublicAPI.Usage.INHERITANCE;
import static com.tngtech.archunit.core.domain.PackageMatcher.TO_GROUPS;
Expand All @@ -70,7 +71,7 @@
* that picks the relevant classes by looking for an annotation</li>
* </ul>
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public final class ArchModules<DESCRIPTOR extends ArchModule.Descriptor> extends ForwardingCollection<ArchModule<DESCRIPTOR>> {
private final Map<Identifier, ArchModule<DESCRIPTOR>> modulesByIdentifier;
private final Map<String, ArchModule<DESCRIPTOR>> modulesByName;
Expand Down Expand Up @@ -125,7 +126,7 @@ protected Collection<ArchModule<DESCRIPTOR>> delegate() {
* @return The contained {@link ArchModule} having an {@link ArchModule.Identifier} comprised of the passed {@code identifier} parts.
* This method will throw an exception if no matching {@link ArchModule} is contained.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public ArchModule<DESCRIPTOR> getByIdentifier(String... identifier) {
return tryGetByIdentifier(identifier).orElseThrow(() ->
new IllegalArgumentException(String.format("There is no %s with identifier %s", ArchModule.class.getSimpleName(), Arrays.toString(identifier))));
Expand All @@ -136,7 +137,7 @@ public ArchModule<DESCRIPTOR> getByIdentifier(String... identifier) {
* @return The contained {@link ArchModule} having an {@link ArchModule.Identifier} comprised of the passed {@code identifier} parts,
* or {@link Optional#empty()} if no matching {@link ArchModule} is contained.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Optional<ArchModule<DESCRIPTOR>> tryGetByIdentifier(String... identifier) {
return Optional.ofNullable(modulesByIdentifier.get(Identifier.from(identifier)));
}
Expand All @@ -147,7 +148,7 @@ public Optional<ArchModule<DESCRIPTOR>> tryGetByIdentifier(String... identifier)
* This method will throw an exception if no matching {@link ArchModule} is contained.
* @see #tryGetByName(String)
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public ArchModule<DESCRIPTOR> getByName(String name) {
return tryGetByName(name).orElseThrow(() ->
new IllegalArgumentException(String.format("There is no %s with name %s", ArchModule.class.getSimpleName(), name)));
Expand All @@ -159,15 +160,15 @@ public ArchModule<DESCRIPTOR> getByName(String name) {
* or {@link Optional#empty()} if no matching {@link ArchModule} is contained.
* @see #getByName(String)
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Optional<ArchModule<DESCRIPTOR>> tryGetByName(String name) {
return Optional.ofNullable(modulesByName.get(name));
}

/**
* @return The names of all {@link ArchModule modules} contained within these {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Set<String> getNames() {
return modulesByName.keySet().stream().map(toStringFunction()).collect(toImmutableSet());
}
Expand Down Expand Up @@ -195,7 +196,7 @@ public Set<String> getNames() {
* @param packageIdentifier A {@link PackageMatcher package identifier}
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static Creator defineByPackages(String packageIdentifier) {
return defineBy(identifierByPackage(packageIdentifier));
}
Expand Down Expand Up @@ -234,7 +235,7 @@ private static IdentifierAssociation identifierByPackage(String packageIdentifie
* {@link ArchModule} by its package
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static CreatorByRootClass defineByRootClasses(Predicate<? super JavaClass> rootClassPredicate) {
return CreatorByRootClass.from(rootClassPredicate);
}
Expand All @@ -248,7 +249,7 @@ public static CreatorByRootClass defineByRootClasses(Predicate<? super JavaClass
* </code></pre>
* In case the respective {@code annotationType} doesn't offer a name attribute like this please refer to {@link #defineByAnnotation(Class, Function)} instead.
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static <A extends Annotation> WithGenericDescriptor<AnnotationDescriptor<A>> defineByAnnotation(Class<A> annotationType) {
return defineByAnnotation(annotationType, input -> {
try {
Expand Down Expand Up @@ -290,7 +291,7 @@ public static <A extends Annotation> WithGenericDescriptor<AnnotationDescriptor<
* @param nameFunction A function determining how to derive the {@link ArchModule#getName() module name} from the respective annotation
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static <A extends Annotation> WithGenericDescriptor<AnnotationDescriptor<A>> defineByAnnotation(Class<A> annotationType, Function<A, String> nameFunction) {
return defineByRootClasses(it -> it.isAnnotatedWith(annotationType))
.describeModuleByRootClass((__, rootClass) -> {
Expand All @@ -315,7 +316,7 @@ public static <A extends Annotation> WithGenericDescriptor<AnnotationDescriptor<
* @param identifierFunction A function defining how each {@link JavaClass} is mapped to the respective {@link ArchModule.Identifier}
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static Creator defineBy(IdentifierAssociation identifierFunction) {
return new Creator(checkNotNull(identifierFunction));
}
Expand Down Expand Up @@ -384,7 +385,7 @@ public interface RootClassDescriptorCreator<DESCRIPTOR extends ArchModule.Descri
/**
* An element of the fluent API to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static class CreatorByRootClass extends Creator {
private final RootClassIdentifierAssociation identifierAssociation;

Expand All @@ -401,7 +402,7 @@ private CreatorByRootClass(RootClassIdentifierAssociation identifierAssociation)
* @param <D> The specific subtype of {@link ArchModule.Descriptor}
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public <D extends ArchModule.Descriptor> WithGenericDescriptor<D> describeModuleByRootClass(RootClassDescriptorCreator<D> descriptorCreator) {
return describeBy((identifier, __) -> descriptorCreator.create(identifier, identifierAssociation.getRootClassOf(identifier)));
}
Expand Down Expand Up @@ -460,7 +461,7 @@ JavaClass getRootClassOf(Identifier identifier) {
/**
* An element of the fluent API to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static class Creator {
private final IdentifierAssociation identifierAssociation;
private final Function<Identifier, String> deriveNameFunction;
Expand Down Expand Up @@ -491,7 +492,7 @@ private Creator(IdentifierAssociation identifierAssociation, Function<Identifier
* the {@link ArchModule.Identifier}
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public Creator deriveNameFromPattern(String namingPattern) {
return new Creator(identifierAssociation, identifier -> {
String result = namingPattern.replace("$@", joinIdentifier(identifier));
Expand All @@ -512,15 +513,15 @@ public Creator deriveNameFromPattern(String namingPattern) {
* @param <D> The specific subtype of the {@link ArchModule.Descriptor} to create
* @return A fluent API to further customize how to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public <D extends ArchModule.Descriptor> WithGenericDescriptor<D> describeBy(DescriptorCreator<D> descriptorCreator) {
return new WithGenericDescriptor<>(identifierAssociation, descriptorCreator);
}

/**
* @see WithGenericDescriptor#modularize(JavaClasses)
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public ArchModules<?> modularize(JavaClasses classes) {
return describeBy((identifier, __) -> ArchModule.Descriptor.create(deriveNameFunction.apply(identifier)))
.modularize(classes);
Expand All @@ -535,7 +536,7 @@ private static String joinIdentifier(Identifier identifier) {
/**
* An element of the fluent API to create {@link ArchModules}
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public static final class WithGenericDescriptor<DESCRIPTOR extends ArchModule.Descriptor> {
private final IdentifierAssociation identifierAssociation;
private final DescriptorCreator<DESCRIPTOR> descriptorCreator;
Expand All @@ -553,7 +554,7 @@ private WithGenericDescriptor(IdentifierAssociation identifierAssociation, Descr
* @param classes The classes to modularize
* @return An instance of {@link ArchModules} containing individual {@link ArchModule}s which in turn contain the partitioned classes
*/
@PublicAPI(usage = ACCESS)
@PublicAPI(usage = ACCESS, state = EXPERIMENTAL)
public ArchModules<DESCRIPTOR> modularize(JavaClasses classes) {
SetMultimap<Identifier, JavaClass> classesByIdentifier = groupClassesByIdentifier(classes);

Expand Down
Loading

0 comments on commit 794d4f2

Please sign in to comment.