0

To externalize UI strings we use the "Messages-class" approach as supported e.g. in Eclipse and other IDEs. This approach requires that in each package where one needs some UI strings there has to be a class "Messages" that offers a static method String getString(key) via which one obtains the actual String to display to the user. The Strings are internally accessed/fetched using Java's Resources mechanism for i18n.

Esp. after some refactoring - we again and again have accidental imports from a class Messages from a different package.

Thus I would like to create an archunit rule checking whether we only access classes called "Messages" from the very same package. I.e. each import of a class x.y.z.Messages is an error if the package x.y.z is not the same package as the current class (i.e. the class that contains the import)

I got as far as this:

@ArchTest
void preventReferencesToMessagesOutsideCurrentPackage(JavaClasses classes) {
    ArchRule rule;
    rule = ArchRuleDefinition.noClasses()
        .should().accessClassesThat().haveNameMatching("Messages")
        .???
        ;
    rule.check(classes);
}

but now I got stuck at the ???. How can one phrase a condition "and the referenced/imported class "Messages" is not in the same package as this class"?

I somehow got lost with all these archunit methods of which none seems to fit here nor lend itself to compose said condition. Probably I just can't see the forest for the many trees. Any suggestion or guidance anyone?

4

1 回答 1

1

您需要对实例进行操作JavaAccess以验证依赖关系。JavaAccess提供有关调用者和目标的信息,以便您可以根据两个类的包名称动态验证访问。

DescribedPredicate<JavaAccess<?>> isForeignMessageClassPredicate = 
        new DescribedPredicate<JavaAccess<?>>("target is a foreign message class") {

    @Override
    public boolean apply(JavaAccess<?> access) {
        JavaClass targetClass = access.getTarget().getOwner();
        if ("Message".equals(targetClass.getSimpleName())) {
            JavaClass callerClass = access.getOwner().getOwner();
            return !targetClass.getPackageName().equals(callerClass.getPackageName());
        }

        return false;
    }
};

ArchRule rule =
    noClasses().should().accessTargetWhere(isForeignMessageClassPredicate);
于 2020-12-22T20:45:49.677 回答