1+ <?xml version =" 1.0" encoding =" UTF-8" ?>
2+ <jqassistant-rules
3+ xmlns =" http://schema.jqassistant.org/rule/v2.8"
4+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
5+ xsi : schemaLocation =" http://schema.jqassistant.org/rule/v2.8 https://jqassistant.github.io/jqassistant/current/schema/jqassistant-rule-v2.8.xsd" >
6+
7+ <group id =" default" >
8+ <includeConcept refId =" layer-*" />
9+ <includeConstraint refId =" *" />
10+ </group >
11+
12+ <!-- ========================================================= -->
13+ <!-- Concepts -->
14+ <!-- ========================================================= -->
15+
16+ <concept id =" layer-resource" >
17+ <description >Marks REST resource classes</description >
18+ <cypher ><![CDATA[
19+ MATCH (t:Type)
20+ WHERE t.fqn =~ '.*\\.resource\\..*'
21+ SET t:Resource
22+ RETURN t.fqn
23+ ]]> </cypher >
24+ </concept >
25+
26+ <concept id =" layer-service" >
27+ <description >Marks service classes</description >
28+ <cypher ><![CDATA[
29+ MATCH (t:Type)
30+ WHERE t.fqn =~ '.*\\.service\\..*'
31+ SET t:Service
32+ RETURN t.fqn
33+ ]]> </cypher >
34+ </concept >
35+
36+ <concept id =" layer-repository" >
37+ <description >Marks repository classes</description >
38+ <cypher ><![CDATA[
39+ MATCH (t:Type)
40+ WHERE t.fqn =~ '.*\\.repository\\..*'
41+ SET t:Repository
42+ RETURN t.fqn
43+ ]]> </cypher >
44+ </concept >
45+
46+ <concept id =" layer-domain" >
47+ <description >Marks domain classes</description >
48+ <cypher ><![CDATA[
49+ MATCH (t:Type)
50+ WHERE t.fqn =~ '.*\\.domain\\..*'
51+ SET t:Domain
52+ RETURN t.fqn
53+ ]]> </cypher >
54+ </concept >
55+
56+ <!-- ========================================================= -->
57+ <!-- Architecture Constraints -->
58+ <!-- ========================================================= -->
59+
60+ <constraint id =" resource-depends-on-service"
61+ severity =" major" >
62+ <requiresConcept refId =" layer-resource" />
63+ <requiresConcept refId =" layer-service" />
64+ <requiresConcept refId =" layer-domain" />
65+ <description >
66+ REST resources must only depend on services or domain classes
67+ </description >
68+ <cypher ><![CDATA[
69+ MATCH (r:Resource)-[:DEPENDS_ON]->(d:Type)
70+ WHERE NOT d:Service
71+ AND NOT d:Domain
72+ AND NOT d.fqn STARTS WITH 'java.'
73+ AND NOT d.fqn STARTS WITH 'jakarta.'
74+ RETURN r.fqn AS Resource, d.fqn AS IllegalDependency
75+ ]]> </cypher >
76+ </constraint >
77+
78+ <constraint id =" service-depends-on-repository-or-domain"
79+ severity =" major" >
80+ <requiresConcept refId =" layer-service" />
81+ <requiresConcept refId =" layer-repository" />
82+ <requiresConcept refId =" layer-domain" />
83+ <description >
84+ Services must only depend on repositories or domain classes
85+ </description >
86+ <cypher ><![CDATA[
87+ MATCH (s:Service)-[:DEPENDS_ON]->(d:Type)
88+ WHERE NOT d:Repository
89+ AND NOT d:Domain
90+ AND NOT d.fqn STARTS WITH 'java.'
91+ AND NOT d.fqn STARTS WITH 'jakarta.'
92+ RETURN s.fqn AS Service, d.fqn AS IllegalDependency
93+ ]]> </cypher >
94+ </constraint >
95+
96+ <!-- ========================================================= -->
97+ <!-- Naming Conventions -->
98+ <!-- ========================================================= -->
99+
100+ <constraint id =" repository-naming"
101+ severity =" minor" >
102+ <requiresConcept refId =" layer-repository" />
103+ <description >
104+ Repository classes must end with 'Repository'
105+ </description >
106+ <cypher ><![CDATA[
107+ MATCH (r:Repository)
108+ WHERE NOT r.name ENDS WITH 'Repository'
109+ RETURN r.fqn
110+ ]]> </cypher >
111+ </constraint >
112+
113+ <constraint id =" service-naming"
114+ severity =" minor" >
115+ <requiresConcept refId =" layer-service" />
116+ <description >
117+ Service classes must end with 'Service'
118+ </description >
119+ <cypher ><![CDATA[
120+ MATCH (s:Service)
121+ WHERE NOT s.name ENDS WITH 'Service'
122+ RETURN s.fqn
123+ ]]> </cypher >
124+ </constraint >
125+
126+ <!-- ========================================================= -->
127+ <!-- CDI Rules -->
128+ <!-- ========================================================= -->
129+
130+ <constraint id =" service-must-be-applicationscoped"
131+ severity =" major" >
132+ <requiresConcept refId =" layer-service" />
133+ <description >
134+ Services must be annotated with @ApplicationScoped
135+ </description >
136+ <cypher ><![CDATA[
137+ MATCH (s:Service)
138+ WHERE NOT EXISTS {
139+ MATCH (s)-[:ANNOTATED_BY]->(ann:Type)
140+ WHERE ann.fqn = 'jakarta.enterprise.context.ApplicationScoped'
141+ }
142+ RETURN s.fqn
143+ ]]> </cypher >
144+ </constraint >
145+
146+ <!-- ========================================================= -->
147+ <!-- Code Quality Rules -->
148+ <!-- ========================================================= -->
149+
150+ <constraint id =" unused-private-methods"
151+ severity =" minor" >
152+ <description >
153+ Private methods should be invoked at least once
154+ </description >
155+ <cypher ><![CDATA[
156+ MATCH (t:Type)-[:DECLARES]->(m:Method)
157+ WHERE m.visibility = 'private'
158+ AND NOT EXISTS {
159+ MATCH (m)<-[:INVOKES]-()
160+ }
161+ RETURN t.fqn AS Type, m.name AS Method
162+ ]]> </cypher >
163+ </constraint >
164+
165+ <constraint id =" long-methods"
166+ severity =" minor" >
167+ <description >
168+ Methods should not exceed 50 effective lines
169+ </description >
170+ <cypher ><![CDATA[
171+ MATCH (t:Type)-[:DECLARES]->(m:Method)
172+ WHERE m.effectiveLineCount > 50
173+ RETURN t.fqn AS Type, m.name AS Method, m.effectiveLineCount AS Lines
174+ ]]> </cypher >
175+ </constraint >
176+
177+ </jqassistant-rules >
0 commit comments