0
# General Predicates
1
2
Core predicates for analyzing Java classes and fields, providing powerful capabilities for annotation checking, field property validation, and class hierarchy inspection.
3
4
## Capabilities
5
6
### Annotation Analysis
7
8
Tests if a class is directly annotated with at least one of the specified annotations.
9
10
```java { .api }
11
/**
12
* Tests if a class is directly annotated with at least one of the given annotations
13
* @param annotations Variable number of annotation classes to check for
14
* @return DescribedPredicate that returns true if class has at least one of the annotations
15
*/
16
@SafeVarargs
17
public static DescribedPredicate<JavaClass> areDirectlyAnnotatedWithAtLeastOneOf(
18
Class<? extends Annotation>... annotations);
19
```
20
21
**Usage Example:**
22
23
```java
24
import org.apache.flink.architecture.common.Predicates;
25
import javax.annotation.Component;
26
import javax.annotation.Service;
27
28
// Check if classes are annotated with Component or Service
29
DescribedPredicate<JavaClass> isComponentOrService =
30
Predicates.areDirectlyAnnotatedWithAtLeastOneOf(Component.class, Service.class);
31
32
ArchRule rule = GivenJavaClasses.javaClassesThat(isComponentOrService)
33
.should()
34
.haveSimpleNameNotContaining("Impl");
35
```
36
37
### Field Hierarchy Analysis
38
39
Tests if any fields in the class hierarchy (including inherited fields) match the given predicate.
40
41
```java { .api }
42
/**
43
* Tests if any fields in the class hierarchy match the given predicate
44
* @param predicate Predicate to test against fields in the class hierarchy
45
* @return DescribedPredicate that returns true if any field in hierarchy matches
46
*/
47
public static DescribedPredicate<JavaClass> containAnyFieldsInClassHierarchyThat(
48
DescribedPredicate<? super JavaField> predicate);
49
```
50
51
**Usage Example:**
52
53
```java
54
import static org.apache.flink.architecture.common.Predicates.containAnyFieldsInClassHierarchyThat;
55
import static org.apache.flink.architecture.common.JavaFieldPredicates.isStatic;
56
import static org.apache.flink.architecture.common.JavaFieldPredicates.ofType;
57
58
// Check if classes contain static Logger fields
59
DescribedPredicate<JavaClass> hasStaticLogger = containAnyFieldsInClassHierarchyThat(
60
isStatic().and(ofType("org.slf4j.Logger"))
61
);
62
63
ArchRule loggerRule = GivenJavaClasses.javaClassesThat(hasStaticLogger)
64
.should()
65
.haveSimpleNameNotEndingWith("Test");
66
```
67
68
### Field Type and Modifier Validation
69
70
Tests field properties including visibility, mutability, and type constraints.
71
72
```java { .api }
73
/**
74
* Tests that field is public static and has the specified fully qualified type
75
* @param fqClassName Fully qualified class name to match
76
* @return DescribedPredicate for public static fields of the specified type
77
*/
78
public static DescribedPredicate<JavaField> arePublicStaticOfType(String fqClassName);
79
80
/**
81
* Tests that field has the specified type and modifiers
82
* @param fqClassName Fully qualified class name to match
83
* @param modifiers Variable number of JavaModifier values (PUBLIC, STATIC, FINAL, etc.)
84
* @return DescribedPredicate for fields matching type and modifiers
85
*/
86
public static DescribedPredicate<JavaField> areFieldOfType(
87
String fqClassName, JavaModifier... modifiers);
88
89
/**
90
* Tests that field is public final (non-static) of the specified type
91
* @param fqClassName Fully qualified class name to match
92
* @return DescribedPredicate for public final instance fields
93
*/
94
public static DescribedPredicate<JavaField> arePublicFinalOfType(String fqClassName);
95
96
/**
97
* Tests that field is public static final and assignable to the given class
98
* @param clazz Class type to check assignability against
99
* @return DescribedPredicate for public static final fields assignable to clazz
100
*/
101
public static DescribedPredicate<JavaField> arePublicStaticFinalAssignableTo(Class<?> clazz);
102
103
/**
104
* Tests that field is public static final of the specified type
105
* @param fqClassName Fully qualified class name to match
106
* @return DescribedPredicate for public static final fields of specified type
107
*/
108
public static DescribedPredicate<JavaField> arePublicStaticFinalOfType(String fqClassName);
109
```
110
111
**Usage Examples:**
112
113
```java
114
// Check for public static String constants
115
DescribedPredicate<JavaField> isPublicStaticString =
116
Predicates.arePublicStaticOfType("java.lang.String");
117
118
// Check for public final configuration fields
119
DescribedPredicate<JavaField> isConfigField =
120
Predicates.arePublicFinalOfType("org.apache.flink.configuration.Configuration");
121
122
// Check for constants assignable to Number
123
DescribedPredicate<JavaField> isNumericConstant =
124
Predicates.arePublicStaticFinalAssignableTo(Number.class);
125
```
126
127
### Annotated Field Validation
128
129
Tests field properties combined with annotation requirements.
130
131
```java { .api }
132
/**
133
* Tests that field is public final of specified type with given annotation
134
* @param fqClassName Fully qualified class name to match
135
* @param annotationType Annotation class that must be present
136
* @return DescribedPredicate for annotated public final fields
137
*/
138
public static DescribedPredicate<JavaField> arePublicFinalOfTypeWithAnnotation(
139
String fqClassName, Class<? extends Annotation> annotationType);
140
141
/**
142
* Tests that field is public static final of specified type with given annotation
143
* @param fqClassName Fully qualified class name to match
144
* @param annotationType Annotation class that must be present
145
* @return DescribedPredicate for annotated public static final fields
146
*/
147
public static DescribedPredicate<JavaField> arePublicStaticFinalOfTypeWithAnnotation(
148
String fqClassName, Class<? extends Annotation> annotationType);
149
150
/**
151
* Tests that field is static final of specified type with given annotation (any visibility)
152
* @param fqClassName Fully qualified class name to match
153
* @param annotationType Annotation class that must be present
154
* @return DescribedPredicate for annotated static final fields
155
*/
156
public static DescribedPredicate<JavaField> areStaticFinalOfTypeWithAnnotation(
157
String fqClassName, Class<? extends Annotation> annotationType);
158
```
159
160
### Predicate Logic
161
162
Utility method for creating exclusive-or logic between multiple predicates.
163
164
```java { .api }
165
/**
166
* Tests that exactly one of the given predicates matches
167
* @param other Variable number of predicates to test
168
* @return DescribedPredicate that returns true if exactly one predicate matches
169
*/
170
@SafeVarargs
171
public static <T> DescribedPredicate<T> exactlyOneOf(
172
final DescribedPredicate<? super T>... other);
173
```
174
175
**Usage Example:**
176
177
```java
178
// Ensure class has exactly one of these field types
179
DescribedPredicate<JavaClass> hasExactlyOneConfigType = containAnyFieldsInClassHierarchyThat(
180
Predicates.exactlyOneOf(
181
ofType("org.apache.flink.configuration.Configuration"),
182
ofType("java.util.Properties"),
183
ofType("java.util.Map")
184
)
185
);
186
```
187
188
### Utility Methods
189
190
Helper method for extracting simple class names from fully qualified names.
191
192
```java { .api }
193
/**
194
* Extracts the simple class name from a fully qualified class name
195
* @param fqClassName Fully qualified class name (e.g., "com.example.MyClass")
196
* @return Simple class name (e.g., "MyClass")
197
* @throws NullPointerException if fqClassName is null
198
* @throws IllegalArgumentException if fqClassName is empty or invalid
199
*/
200
public static String getClassSimpleNameFromFqName(String fqClassName);
201
```
202
203
**Usage Example:**
204
205
```java
206
String simpleName = Predicates.getClassSimpleNameFromFqName("org.apache.flink.streaming.api.StreamExecutionEnvironment");
207
// Returns: "StreamExecutionEnvironment"
208
209
String innerClassName = Predicates.getClassSimpleNameFromFqName("org.apache.flink.api.common.ExecutionConfig$GlobalJobParameters");
210
// Returns: "GlobalJobParameters"
211
```
212
213
## Design Principles
214
215
- **Fully Qualified Names**: All methods accepting class names recommend using fully qualified names instead of Class objects to avoid circular dependencies between project modules
216
- **Composability**: All predicates are designed to be combined using `.and()`, `.or()`, and `.negate()` for complex rules
217
- **Type Safety**: Strong typing ensures compile-time validation of predicate combinations
218
- **Performance**: Efficient implementations suitable for analyzing large codebases