/*
* Copyright 2017 TNG Technology Consulting GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tngtech.archunit.lang.syntax.elements;
import java.lang.annotation.Annotation;
import com.tngtech.archunit.PublicAPI;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.base.PackageMatcher;
import com.tngtech.archunit.core.domain.AccessTarget;
import com.tngtech.archunit.core.domain.JavaAccess;
import com.tngtech.archunit.core.domain.JavaAnnotation;
import com.tngtech.archunit.core.domain.JavaCall;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaCodeUnit;
import com.tngtech.archunit.core.domain.JavaConstructorCall;
import com.tngtech.archunit.core.domain.JavaFieldAccess;
import com.tngtech.archunit.core.domain.JavaMethodCall;
import com.tngtech.archunit.core.domain.JavaModifier;
import com.tngtech.archunit.core.domain.properties.HasName.Predicates;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
public interface ClassesShould {
/**
* Asserts that classes have a certain fully qualified class name.
*
* @param name The fully qualified class name
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction haveFullyQualifiedName(String name);
/**
* Asserts that classes don't have a certain fully qualified class name.
*
* @param name The fully qualified class name
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notHaveFullyQualifiedName(String name);
/**
* Asserts that classes have a certain simple class name.
*
* @param name The simple class name
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction haveSimpleName(String name);
/**
* Asserts that classes don't have a certain simple class name.
*
* @param name The simple class name
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notHaveSimpleName(String name);
/**
* Asserts that classes have a fully qualified class name matching a given regular expression.
*
* @param regex A regular expression
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction haveNameMatching(String regex);
/**
* Asserts that classes have a fully qualified class name not matching a given regular expression.
*
* @param regex A regular expression
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction haveNameNotMatching(String regex);
/**
* Asserts that classes reside in a package matching the supplied package identifier.
*
* @param packageIdentifier A string identifying packages, for details see {@link PackageMatcher}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction resideInAPackage(String packageIdentifier);
/**
* Asserts that classes reside in a package matching any of the supplied package identifiers.
*
* @param packageIdentifiers Strings identifying packages, for details see {@link PackageMatcher}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction resideInAnyPackage(String... packageIdentifiers);
/**
* Asserts that classes don't reside in a package matching the supplied package identifier.
*
* @param packageIdentifier A string identifying packages, for details see {@link PackageMatcher}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction resideOutsideOfPackage(String packageIdentifier);
/**
* Asserts that classes don't reside in a package matching any of the supplied package identifiers.
*
* @param packageIdentifiers Strings identifying packages, for details see {@link PackageMatcher}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction resideOutsideOfPackages(String... packageIdentifiers);
/**
* Asserts that classes are public.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction bePublic();
/**
* Asserts that classes are non-public.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBePublic();
/**
* Asserts that classes are protected.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beProtected();
/**
* Asserts that classes are non-protected.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeProtected();
/**
* Asserts that classes are package private.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction bePackagePrivate();
/**
* Asserts that classes are non-package private.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBePackagePrivate();
/**
* Asserts that classes are private.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction bePrivate();
/**
* Asserts that classes are non-private.
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBePrivate();
/**
* Asserts that classes have a certain {@link JavaModifier} (e.g. {@link JavaModifier#ABSTRACT}).
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction haveModifier(JavaModifier modifier);
/**
* Asserts that classes don't have a certain {@link JavaModifier} (e.g. {@link JavaModifier#ABSTRACT}).
*
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notHaveModifier(JavaModifier modifier);
/**
* Asserts that classes are annotated with a certain type of annotation.
*
* @param annotationType Specific type of {@link Annotation}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAnnotatedWith(Class<? extends Annotation> annotationType);
/**
* Asserts that classes are not annotated with a certain type of annotation.
*
* @param annotationType Specific type of {@link Annotation}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAnnotatedWith(Class<? extends Annotation> annotationType);
/**
* Asserts that classes are annotated with a certain type of annotation.
*
* @param annotationTypeName Fully qualified class name of a specific type of {@link Annotation}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAnnotatedWith(String annotationTypeName);
/**
* Asserts that classes are not annotated with a certain type of annotation.
*
* @param annotationTypeName Fully qualified class name of a specific type of {@link Annotation}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAnnotatedWith(String annotationTypeName);
/**
* Asserts that classes are annotated with a certain annotation, where matching annotations are
* determined by the supplied predicate.
*
* @param predicate A predicate defining matching {@link JavaAnnotation JavaAnnotations}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAnnotatedWith(DescribedPredicate<? super JavaAnnotation> predicate);
/**
* Asserts that classes are not annotated with a certain annotation, where matching annotations are
* determined by the supplied predicate.
*
* @param predicate A predicate defining matching {@link JavaAnnotation JavaAnnotations}
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAnnotatedWith(DescribedPredicate<? super JavaAnnotation> predicate);
/**
* Asserts that classes implement a certain interface.
*
* @param type An interface imported classes should implement
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction implement(Class<?> type);
/**
* Asserts that classes don't implement a certain interface. This is the negation of {@link #implement(Class)}.
*
* @param type An interface imported classes should NOT implement
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notImplement(Class<?> type);
/**
* Asserts that classes implement a certain interface with the given type name. This is equivalent to
* {@link #implement(Class)}, but doesn't depend on having a certain type on the classpath.
*
* @param typeName Name of an interface imported classes should implement
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction implement(String typeName);
/**
* Asserts that classes don't implement a certain interface with the given type name.
* This is equivalent to {@link #notImplement(Class)}, but doesn't depend on having a certain
* type on the classpath.
*
* @param typeName Name of an interface imported classes should NOT implement
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notImplement(String typeName);
/**
* Asserts that classes implement a certain interface matching the given predicate. For example, a call with
* {@link Predicates#name(String)} would be equivalent to
* {@link #implement(String)}, but the approach is a lot more generic.
*
* @param predicate A predicate identifying an interface imported classes should implement
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction implement(DescribedPredicate<? super JavaClass> predicate);
/**
* Asserts that classes don't implement a certain interface matching the given predicate.
* This is the negation of {@link #implement(DescribedPredicate)}.
*
* @param predicate A predicate identifying an interface imported classes should NOT implement
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notImplement(DescribedPredicate<? super JavaClass> predicate);
/**
* Asserts that classes are assignable to a certain type (compare {@link Class#isAssignableFrom(Class)} to terminology).
* A simple example for this predicate would be
* <pre><code>
* assignableTo(Object.class).apply(importedStringClass); // --> returns true
* assignableTo(String.class).apply(importedStringClass); // --> returns true
* assignableTo(List.class).apply(importedStringClass); // --> returns false
* </code></pre>
*
* @param type An upper type bound to match imported classes against (imported subtypes will match)
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAssignableTo(Class<?> type);
/**
* Asserts that classes are not assignable to a certain type. This is the negation of {@link #beAssignableTo(Class)}.
*
* @param type An upper type bound imported classes should NOT have
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAssignableTo(Class<?> type);
/**
* Asserts that classes are assignable to a certain type with the given type name. This is equivalent to
* {@link #beAssignableTo(Class)}, but doesn't depend on having a certain type on the classpath.
*
* @param typeName Name of an upper type bound to match imported classes against (imported subtypes will match)
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAssignableTo(String typeName);
/**
* Asserts that classes are not assignable to a certain type with the given type name.
* This is equivalent to {@link #notBeAssignableTo(Class)}, but doesn't depend on having a certain
* type on the classpath.
*
* @param typeName Name of an upper type bound imported classes should NOT have
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAssignableTo(String typeName);
/**
* Asserts that classes are assignable to a certain type matching the given predicate. For example, a call with
* {@link Predicates#name(String)} would be equivalent to
* {@link #beAssignableTo(String)}, but the approach is a lot more generic.
*
* @param predicate A predicate identifying an upper type bound to match imported classes against
* (imported subtypes will match)
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAssignableTo(DescribedPredicate<? super JavaClass> predicate);
/**
* Asserts that classes are not assignable to a certain type matching the given predicate.
* This is the negation of {@link #beAssignableTo(DescribedPredicate)}.
*
* @param predicate A predicate identifying an upper type bound imported classes should NOT have
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAssignableTo(DescribedPredicate<? super JavaClass> predicate);
/**
* Asserts that classes are assignable from a certain type (compare {@link Class#isAssignableFrom(Class)} to terminology).
* This is roughly equivalent to the use of reflection:
* <pre><code>
* someClass.class.isAssignableFrom(type);
* </code></pre>
* A simple example for this predicate would be
* <pre><code>
* assignableFrom(ArrayList.class).apply(importedArrayListClass); // --> returns true
* assignableFrom(ArrayList.class).apply(importedListClass); // --> returns true
* assignableFrom(ArrayList.class).apply(importedStringClass); // --> returns false
* </code></pre>
*
* @param type A lower type bound to match imported classes against (imported supertypes will match)
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAssignableFrom(Class<?> type);
/**
* Asserts that classes are not assignable from a certain type. This is the negation of {@link #beAssignableFrom(Class)}.
*
* @param type A lower type bound imported classes should NOT have
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAssignableFrom(Class<?> type);
/**
* Asserts that classes are assignable from a certain type with the given type name. This is equivalent to
* {@link #beAssignableFrom(Class)}, but doesn't depend on having a certain type on the classpath.
*
* @param typeName Name of a lower type bound to match imported classes against (imported supertypes will match)
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAssignableFrom(String typeName);
/**
* Asserts that classes are not assignable from a certain type with the given type name.
* This is equivalent to {@link #notBeAssignableFrom(Class)}, but doesn't depend on having a certain
* type on the classpath.
*
* @param typeName Name of a lower type bound imported classes should NOT have
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAssignableFrom(String typeName);
/**
* Asserts that classes are assignable from a certain type matching the given predicate. For example, a call with
* {@link Predicates#name(String)} would be equivalent to
* {@link #beAssignableFrom(String)}, but the approach is a lot more generic.
*
* @param predicate A predicate identifying a lower type bound to match imported classes against
* (imported supertypes will match)
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction beAssignableFrom(DescribedPredicate<? super JavaClass> predicate);
/**
* Asserts that classes are not assignable from a certain type matching the given predicate.
* This is the negation of {@link #beAssignableFrom(DescribedPredicate)}.
*
* @param predicate A predicate identifying a lower type bound imported classes should NOT have
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction notBeAssignableFrom(DescribedPredicate<? super JavaClass> predicate);
/**
* Matches against all accesses (setting or getting) of a specific field.
*
* @param owner The class declaring the field
* @param fieldName The name of the field to match
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction accessField(Class<?> owner, String fieldName);
/**
* Matches against all accesses (setting or getting) of a specific field.
*
* @param ownerName The fully qualified class name of the class declaring the field
* @param fieldName The name of the field to match
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction accessField(String ownerName, String fieldName);
/**
* Matches against accessing fields, where origin (a method or constructor) and target (a field)
* can be freely restricted by the supplied predicate.
*
* @param predicate Determines which {@link JavaFieldAccess JavaFieldAccesses} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction accessFieldWhere(DescribedPredicate<? super JavaFieldAccess> predicate);
/**
* Matches against getting of a specific field (e.g. <code>return someClass.<b>someField</b>;</code>).
*
* @param owner The class declaring the field
* @param fieldName The name of the field to match
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction getField(Class<?> owner, String fieldName);
/**
* Matches against getting a specific field (e.g. <code>return someClass.<b>someField</b>;</code>).
*
* @param ownerName The fully qualified class name of the class declaring the field
* @param fieldName The name of the field to match
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction getField(String ownerName, String fieldName);
/**
* Matches against getting of fields, where origin (a method or constructor) and target (a field)
* can be freely restricted by the supplied predicate.
*
* @param predicate Determines which {@link JavaFieldAccess JavaFieldAccesses} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction getFieldWhere(DescribedPredicate<? super JavaFieldAccess> predicate);
/**
* Matches against setting a specific field (e.g. <code>someClass.<b>someField</b> = newValue;</code>).
*
* @param owner The class declaring the field
* @param fieldName The name of the field to match
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction setField(Class<?> owner, String fieldName);
/**
* Matches against setting a specific field (e.g. <code>someClass.<b>someField</b> = newValue;</code>).
*
* @param ownerName The fully qualified class name of the class declaring the field
* @param fieldName The name of the field to match
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction setField(String ownerName, String fieldName);
/**
* Matches against setting of fields, where origin (a method or constructor) and target (a field)
* can be freely restricted by the supplied predicate.
*
* @param predicate Determines which {@link JavaFieldAccess JavaFieldAccesses} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction setFieldWhere(DescribedPredicate<? super JavaFieldAccess> predicate);
/**
* Matches against a method call to a specific method (e.g. <code>someClass.<b>call()</b>;</code>).
*
* @param owner Class declaring the method
* @param methodName The method name to match against
* @param parameterTypes The parameter types of the respective method
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callMethod(Class<?> owner, String methodName, Class<?>... parameterTypes);
/**
* Matches against method call to a specific method (e.g. <code>someClass.<b>call()</b>;</code>).
*
* @param ownerName The fully qualified class name declaring the method
* @param methodName The method name to match against
* @param parameterTypeNames The fully qualified parameter type names
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callMethod(String ownerName, String methodName, String... parameterTypeNames);
/**
* Matches against method calls where origin (a method or constructor) and target (a method)
* can be freely restricted by the supplied predicate.
*
* @param predicate Determines which {@link JavaMethodCall JavaMethodCalls} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callMethodWhere(DescribedPredicate<? super JavaMethodCall> predicate);
/**
* Matches against a constructor call to a specific constructor (e.g. <code><b>new SomeClass()</b>;</code>).
*
* @param owner Class declaring the constructor
* @param parameterTypes The parameter types of the respective constructor
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callConstructor(Class<?> owner, Class<?>... parameterTypes);
/**
* Matches against constructor call to a specific constructor (e.g. <code><b>new SomeClass()</b>;</code>).
*
* @param ownerName The fully qualified class name declaring the constructor
* @param parameterTypeNames The fully qualified parameter type names
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callConstructor(String ownerName, String... parameterTypeNames);
/**
* Matches against constructor calls where origin (a method or constructor) and target (a constructor)
* can be freely restricted by the supplied predicate.
*
* @param predicate Determines which {@link JavaConstructorCall JavaConstructorCalls} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callConstructorWhere(DescribedPredicate<? super JavaConstructorCall> predicate);
/**
* Matches against access of arbitrary targets (compare {@link AccessTarget})
* where origin (a method or constructor) and target (a field, method or constructor) can be freely restricted
* by the supplied predicate.
*
* @param predicate Determines which {@link JavaAccess JavaAccesses} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction accessTargetWhere(DescribedPredicate<? super JavaAccess<?>> predicate);
/**
* Matches against code unit calls (compare {@link JavaCodeUnit}) where origin (a code unit)
* and target (a code unit) can be freely restricted by the supplied predicate.
*
* @param predicate Determines which {@link JavaCall JavaCalls} match the rule
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction callCodeUnitWhere(DescribedPredicate<? super JavaCall<?>> predicate);
/**
* Asserts that all classes selected by this rule access certain classes.<br>
* NOTE: This usually makes more sense the negated way, e.g.
* <p>
* <pre><code>
* {@link ArchRuleDefinition#noClasses() noClasses()}.{@link GivenClasses#should() should()}.{@link #accessClassesThat()}.{@link ClassesShouldThat#haveFullyQualifiedName(String) haveFullyQualifiedName(String)}
* </code></pre>
*
* @return A syntax element that allows choosing which classes should be accessed
*/
@PublicAPI(usage = ACCESS)
ClassesShouldThat accessClassesThat();
/**
* Asserts that all classes selected by this rule access certain classes.<br>
* NOTE: This usually makes more sense the negated way, e.g.
* <p>
* <pre><code>
* {@link ArchRuleDefinition#noClasses() noClasses()}.{@link GivenClasses#should() should()}.{@link #accessClassesThat(DescribedPredicate) accessClassesThat(myPredicate)}
* </code></pre>
*
* @param predicate Determines which {@link JavaClass JavaClasses} match the access target
* @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule
*/
@PublicAPI(usage = ACCESS)
ClassesShouldConjunction accessClassesThat(DescribedPredicate<? super JavaClass> predicate);
/**
* @return A syntax element that allows restricting how classes should be accessed
* <br>E.g.
* <pre><code>
* {@link #onlyBeAccessed()}.{@link OnlyBeAccessedSpecification#byAnyPackage(String...) byAnyPackage(String...)}
* </code></pre>
*/
@PublicAPI(usage = ACCESS)
OnlyBeAccessedSpecification<ClassesShouldConjunction> onlyBeAccessed();
}