Skip to content

Commit c53e411

Browse files
authored
#25: Implement additional Package/NamingRule (#27)
1 parent c517485 commit c53e411

File tree

2 files changed

+118
-50
lines changed

2 files changed

+118
-50
lines changed

src/test/java/com/devonfw/sample/archunit/NamingConventionTest.java

Lines changed: 118 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,67 +2,136 @@
22

33
import com.devonfw.sample.archunit.general.common.AbstractCto;
44
import com.devonfw.sample.archunit.general.common.AbstractEto;
5-
import com.devonfw.sample.archunit.general.dataaccess.ApplicationPersistenceEntity;
65
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;
712
import com.tngtech.archunit.core.importer.ImportOption;
813
import com.tngtech.archunit.junit.AnalyzeClasses;
914
import com.tngtech.archunit.junit.ArchTest;
15+
import com.tngtech.archunit.lang.ArchCondition;
1016
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;
1221
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
1322

23+
import java.lang.reflect.ParameterizedType;
24+
import java.lang.reflect.Type;
25+
1426
/**
1527
* JUnit test that validates the naming convention rules of this application.
1628
*/
1729
@AnalyzeClasses(packages = "com.devonfw.sample.archunit", importOptions = ImportOption.DoNotIncludeTests.class)
1830
public class NamingConventionTest {
1931

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'.");
67136

68137
}

src/test/java/com/devonfw/sample/archunit/PackageRuleTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
package com.devonfw.sample.archunit;
2-
32
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
43

54
import com.tngtech.archunit.core.domain.JavaClass;

0 commit comments

Comments
 (0)