|
2 | 2 |
|
3 | 3 | import com.devonfw.sample.archunit.general.common.AbstractCto; |
4 | 4 | import com.devonfw.sample.archunit.general.common.AbstractEto; |
5 | | -import com.devonfw.sample.archunit.general.dataaccess.ApplicationPersistenceEntity; |
6 | 5 | import com.devonfw.sample.archunit.general.logic.AbstractUc; |
| 6 | + |
| 7 | +import javax.ws.rs.Path; |
| 8 | +import org.mapstruct.Mapper; |
| 9 | +import org.springframework.data.jpa.repository.JpaRepository; |
| 10 | + |
| 11 | +import com.devonfw.sample.archunit.general.dataaccess.ApplicationPersistenceEntity; |
7 | 12 | import com.tngtech.archunit.core.importer.ImportOption; |
8 | 13 | import com.tngtech.archunit.junit.AnalyzeClasses; |
9 | 14 | import com.tngtech.archunit.junit.ArchTest; |
| 15 | +import com.tngtech.archunit.lang.ArchCondition; |
10 | 16 | import com.tngtech.archunit.lang.ArchRule; |
11 | | - |
| 17 | +import com.tngtech.archunit.core.domain.JavaClass; |
| 18 | +import com.tngtech.archunit.core.domain.JavaModifier; |
| 19 | +import com.tngtech.archunit.lang.ConditionEvents; |
| 20 | +import com.tngtech.archunit.lang.SimpleConditionEvent; |
12 | 21 | import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; |
13 | 22 |
|
| 23 | +import java.lang.reflect.ParameterizedType; |
| 24 | +import java.lang.reflect.Type; |
| 25 | + |
14 | 26 | /** |
15 | 27 | * JUnit test that validates the naming convention rules of this application. |
16 | 28 | */ |
17 | 29 | @AnalyzeClasses(packages = "com.devonfw.sample.archunit", importOptions = ImportOption.DoNotIncludeTests.class) |
18 | 30 | public class NamingConventionTest { |
19 | 31 |
|
20 | | - /** |
21 | | - * DevonNamingConventionCheck N1 verifying that classes extending AbstractCto are following the |
22 | | - * naming convention by ending with 'Cto'. |
23 | | - */ |
24 | | - @ArchTest |
25 | | - private static final ArchRule N1DevonNamingConventionCtoCheck = |
26 | | - classes() |
27 | | - .that().areAssignableTo(AbstractCto.class) |
28 | | - .should().haveSimpleNameEndingWith("Cto") |
29 | | - .because("Classes extending AbstractCto must follow the naming convention by" + |
30 | | - " ending with 'Cto'."); |
31 | | - |
32 | | - /** |
33 | | - * DevonNamingConventionCheck N3 verifying that classes extending ApplicationPersistenceEntity are following the |
34 | | - * naming convention by ending with 'Entity'. |
35 | | - */ |
36 | | - @ArchTest |
37 | | - private static final ArchRule N3DevonNamingConventionEntityCheck = |
38 | | - classes() |
39 | | - .that().areAssignableTo(ApplicationPersistenceEntity.class) |
40 | | - .should().haveSimpleNameEndingWith("Entity") |
41 | | - .because("Classes extending ApplicationPersistenceEntity must follow the naming convention by" + |
42 | | - " ending with 'Entity'."); |
43 | | - |
44 | | - /** |
45 | | - * DevonNamingConventionCheck N4 verifying that classes extending AbstractEto are following the naming convention by |
46 | | - * ending with 'Eto'. |
47 | | - */ |
48 | | - @ArchTest |
49 | | - private static final ArchRule N4DevonNamingConventionEtoCheck = |
50 | | - classes() |
51 | | - .that().areAssignableTo(AbstractEto.class) |
52 | | - .should().haveSimpleNameEndingWith("Eto") |
53 | | - .because("Classes extending AbstractEto must follow the naming convention by ending with 'Eto'."); |
54 | | - |
55 | | - /** |
56 | | - * DevonNamingConventionCheck N5 verifying that non-abstract classes inherited from AbstractUc are following the |
57 | | - * devonfw naming convention by beginning with 'Uc' and ending with 'Impl'. They must also implement an interface |
58 | | - * with the same name except for the suffix 'Impl'. |
59 | | - */ |
60 | | - @ArchTest |
61 | | - private static final ArchRule N5DevonNamingConventionUcCheck = |
62 | | - classes() |
63 | | - .that().areAssignableTo(AbstractUc.class) |
64 | | - .and().doNotHaveSimpleName("AbstractUc") |
65 | | - .should().haveSimpleNameStartingWith("Uc") |
66 | | - .because("Classes extending AbstractUc must follow the naming convention by starting with 'Uc'."); |
| 32 | + /** |
| 33 | + * DevonNamingConventionCheck N1 verifying that classes extending AbstractCto are following the naming convention by |
| 34 | + * ending with 'Cto'. |
| 35 | + */ |
| 36 | + @ArchTest |
| 37 | + private static final ArchRule N1DevonNamingConventionCtoCheck = classes().that().areAssignableTo(AbstractCto.class) |
| 38 | + .should().haveSimpleNameEndingWith("Cto") |
| 39 | + .because("Classes extending AbstractCto must follow the naming convention by" + " ending with 'Cto'."); |
| 40 | + |
| 41 | + /** |
| 42 | + * DevonNamingConventionCheck N3 verifying that classes extending ApplicationPersistenceEntity are following the |
| 43 | + * naming convention by ending with 'Entity' and have to be in layer dataaccess. |
| 44 | + */ |
| 45 | + @ArchTest |
| 46 | + private static final ArchRule N3DevonNamingConventionEntityCheck = classes().that() |
| 47 | + .areAssignableTo(ApplicationPersistenceEntity.class).should().haveSimpleNameEndingWith("Entity").andShould() |
| 48 | + .resideInAnyPackage("..dataaccess..") |
| 49 | + .because("Classes extending ApplicationPersistenceEntity must follow the naming convention by" |
| 50 | + + "ending with 'Entity' and must be located in the package dataaccess."); |
| 51 | + |
| 52 | + /** |
| 53 | + * DevonNamingConventionCheck N4 verifying that classes extending AbstractEto are following the naming convention by |
| 54 | + * ending with 'Eto'n reside in package "common" and implement an interface with the same simple name. |
| 55 | + */ |
| 56 | + @ArchTest |
| 57 | + private static final ArchRule N4DevonNamingConventionEtoCheck = classes().that().areAssignableTo(AbstractEto.class) |
| 58 | + .and().doNotHaveSimpleName("AbstractEto").should().haveSimpleNameEndingWith("Eto").andShould() |
| 59 | + .resideInAnyPackage("..common..") |
| 60 | + .andShould(new ArchCondition<JavaClass>("implemted an interface with same simple name", new Object() { |
| 61 | + }) { |
| 62 | + @Override |
| 63 | + public void check(JavaClass javaClass, ConditionEvents events) { |
| 64 | + |
| 65 | + String supposedInterfaceName = javaClass.getPackageName() + "." |
| 66 | + + javaClass.getSimpleName().replace("Eto", ""); |
| 67 | + boolean hasCorrectInterface = javaClass.getInterfaces().stream() |
| 68 | + .anyMatch(i -> i.getName().equals(supposedInterfaceName)); |
| 69 | + String message = "The Testresult of " + javaClass.getSimpleName() + " was " + hasCorrectInterface; |
| 70 | + events.add(new SimpleConditionEvent(javaClass, hasCorrectInterface, message)); |
| 71 | + } |
| 72 | + }).because( |
| 73 | + "Classes extending AbstractEto must follow the naming convention by ending with 'Eto', reside in package common and implent an interface with the same simple name."); |
| 74 | + |
| 75 | + /** |
| 76 | + * DevonAbstractUcCheck verifying that classes extending AbstractUc have to have be in layer logic |
| 77 | + */ |
| 78 | + @ArchTest |
| 79 | + private static final ArchRule DevonAbstractUcCheck = classes().that().areAssignableTo(AbstractUc.class).should() |
| 80 | + .resideInAnyPackage("..logic..").because("Classes extending AbstractUc must be located in the package logic"); |
| 81 | + |
| 82 | + /** |
| 83 | + * DevonMapperCheck verifying that classes extending Mapper have to have be in layer logic and end with the suffix |
| 84 | + * Mapper |
| 85 | + */ |
| 86 | + @ArchTest |
| 87 | + private static final ArchRule DevonMapperCheck = classes().that().areAnnotatedWith(Mapper.class).should() |
| 88 | + .resideInAnyPackage("..logic..").andShould().haveSimpleNameEndingWith("Mapper") |
| 89 | + .because("Types annotated with @Mapper must be located in the package logic and end with Mapper"); |
| 90 | + |
| 91 | + /** |
| 92 | + * DevonPathCheck verifying that classes extending Path have to have be in layer service and end with the suffix |
| 93 | + * Service |
| 94 | + */ |
| 95 | + @ArchTest |
| 96 | + private static final ArchRule DevonPathCheck = classes().that().areAnnotatedWith(Path.class).should() |
| 97 | + .resideInAnyPackage("..service..").andShould().haveSimpleNameEndingWith("Service") |
| 98 | + .because("Types annotated with @Path must be located in the package service and end with Service"); |
| 99 | + |
| 100 | + /** |
| 101 | + * DevonJpaRepositoryCheck verifying that classes implementing JpaRepository have to have be in layer dataaccess and |
| 102 | + * have to be named «EntityName»Repository where «EntityName» is the name of the entity filled in the generic argument |
| 103 | + * of JpaRepository excluding the Entity suffix. Further they should be in the same package as the entity. |
| 104 | + */ |
| 105 | + @ArchTest |
| 106 | + private static final ArchRule DevonJpaRepositoryCheck = classes().that().areAssignableTo(JpaRepository.class).should() |
| 107 | + .resideInAnyPackage("..dataaccess..").andShould().haveSimpleNameEndingWith("Repository") |
| 108 | + .andShould(new ArchCondition<JavaClass>("check for the jpa naming structure to be valid", new Object() { |
| 109 | + }) { |
| 110 | + @Override |
| 111 | + public void check(JavaClass javaClass, ConditionEvents events) { |
| 112 | + |
| 113 | + Boolean hasCorrectName = false; |
| 114 | + Type[] genericInterfaces = javaClass.reflect().getGenericInterfaces(); |
| 115 | + for (Type genericInterface : genericInterfaces) { |
| 116 | + if (genericInterface instanceof ParameterizedType) { |
| 117 | + ParameterizedType parameterizedType = (ParameterizedType) genericInterface; |
| 118 | + Type[] typeArguments = parameterizedType.getActualTypeArguments(); |
| 119 | + String enitiyName = typeArguments[0].getTypeName().replace("Entity", ""); |
| 120 | + hasCorrectName = javaClass.getFullName().equals(enitiyName + "Repository"); |
| 121 | + } |
| 122 | + } |
| 123 | + events.add(new SimpleConditionEvent(javaClass, hasCorrectName, "message")); |
| 124 | + } |
| 125 | + }); |
| 126 | + |
| 127 | + /** |
| 128 | + * DevonNamingConventionCheck N5 verifying that non-abstract classes inherited from AbstractUc are following the |
| 129 | + * devonfw naming convention by beginning with 'Uc' and ending with 'Impl'. They must also implement an interface with |
| 130 | + * the same name except for the suffix 'Impl'. |
| 131 | + */ |
| 132 | + @ArchTest |
| 133 | + private static final ArchRule N5DevonNamingConventionUcCheck = classes().that().areAssignableTo(AbstractUc.class) |
| 134 | + .and().doNotHaveModifier(JavaModifier.ABSTRACT).should().haveSimpleNameStartingWith("Uc") |
| 135 | + .because("Classes extending AbstractUc must follow the naming convention by starting with 'Uc'."); |
67 | 136 |
|
68 | 137 | } |
0 commit comments