0
# Enum and Generic Utilities
1
2
Utilities for flexible enum conversion with fuzzy matching and generic type parameter reflection capabilities.
3
4
## Enums Class
5
6
The `Enums` utility class provides helper methods for enum types with more permissive conversion rules than the standard `Enum.valueOf()` method.
7
8
### Fuzzy String Conversion
9
10
```java { .api }
11
public static Enum<?> fromStringFuzzy(String value, Enum<?>[] constants);
12
```
13
14
Convert a string to an enum with more permissive rules than standard `Enum.valueOf()`.
15
16
**Parameters:**
17
- `value` - The string to convert to an enum constant
18
- `constants` - Array of enum constants (typically obtained via `EnumClass.values()`)
19
20
**Returns:** The matching enum constant, or `null` if no match found
21
22
**Permissive Matching Rules:**
23
1. **Whitespace removal**: Strips all whitespace (spaces, tabs, newlines, carriage returns)
24
2. **Character normalization**: Converts dashes (`-`) and periods (`.`) to underscores (`_`)
25
3. **Case insensitive**: Matching is case-insensitive
26
4. **toString() fallback**: If name-based matching fails, tries matching against `toString()` output
27
28
### Usage Examples
29
30
#### Basic Enum Conversion
31
32
```java
33
// Define an enum
34
public enum Color {
35
RED, GREEN, BLUE, DARK_BLUE
36
}
37
38
// Standard conversion (would throw exception for many inputs)
39
Color standard = Color.valueOf("RED"); // Works
40
// Color.valueOf("red"); // Would throw IllegalArgumentException
41
42
// Fuzzy conversion (more flexible)
43
Color fuzzy1 = (Color) Enums.fromStringFuzzy("red", Color.values()); // RED
44
Color fuzzy2 = (Color) Enums.fromStringFuzzy("RED", Color.values()); // RED
45
Color fuzzy3 = (Color) Enums.fromStringFuzzy("dark-blue", Color.values()); // DARK_BLUE
46
Color fuzzy4 = (Color) Enums.fromStringFuzzy("dark.blue", Color.values()); // DARK_BLUE
47
Color fuzzy5 = (Color) Enums.fromStringFuzzy("DARK_BLUE", Color.values()); // DARK_BLUE
48
```
49
50
#### Whitespace Handling
51
52
```java
53
public enum Status {
54
ACTIVE, INACTIVE, PENDING_APPROVAL
55
}
56
57
// Handles various whitespace scenarios
58
Status status1 = (Status) Enums.fromStringFuzzy("active", Status.values());
59
Status status2 = (Status) Enums.fromStringFuzzy(" ACTIVE ", Status.values());
60
Status status3 = (Status) Enums.fromStringFuzzy("pending\napproval", Status.values());
61
Status status4 = (Status) Enums.fromStringFuzzy("pending\t approval", Status.values());
62
// All return Status.ACTIVE or Status.PENDING_APPROVAL respectively
63
```
64
65
#### toString() Fallback Support
66
67
```java
68
public enum HttpMethod {
69
GET("get"),
70
POST("post"),
71
PUT("put"),
72
DELETE("delete");
73
74
private final String value;
75
76
HttpMethod(String value) {
77
this.value = value;
78
}
79
80
@Override
81
public String toString() {
82
return value;
83
}
84
}
85
86
// First tries name matching, then toString() matching
87
HttpMethod method1 = (HttpMethod) Enums.fromStringFuzzy("GET", HttpMethod.values()); // Matches name
88
HttpMethod method2 = (HttpMethod) Enums.fromStringFuzzy("get", HttpMethod.values()); // Matches toString()
89
HttpMethod method3 = (HttpMethod) Enums.fromStringFuzzy("post", HttpMethod.values()); // Matches toString()
90
```
91
92
#### Configuration Parsing
93
94
```java
95
public enum LogLevel {
96
TRACE, DEBUG, INFO, WARN, ERROR
97
}
98
99
public class Configuration {
100
public LogLevel parseLogLevel(String configValue) {
101
LogLevel level = (LogLevel) Enums.fromStringFuzzy(configValue, LogLevel.values());
102
if (level == null) {
103
throw new IllegalArgumentException("Invalid log level: " + configValue);
104
}
105
return level;
106
}
107
}
108
109
// Usage
110
Configuration config = new Configuration();
111
LogLevel level1 = config.parseLogLevel("info"); // INFO
112
LogLevel level2 = config.parseLogLevel("DEBUG"); // DEBUG
113
LogLevel level3 = config.parseLogLevel("warn"); // WARN
114
```
115
116
## Generics Class
117
118
The `Generics` utility class provides helper methods for class type parameters and reflection operations, particularly useful for retrieving generic type information at runtime.
119
120
### Type Parameter Extraction
121
122
```java { .api }
123
public static Class<?> getTypeParameter(Class<?> klass);
124
public static <T> Class<T> getTypeParameter(Class<?> klass, Class<? super T> bound);
125
```
126
127
Find the type parameter for a given parameterized class.
128
129
**Parameters:**
130
- `klass` - A parameterized class
131
- `bound` - The type bound for the second overload
132
133
**Returns:** The class's type parameter
134
135
**Throws:**
136
- `IllegalStateException` - If type parameterization cannot be determined
137
138
### Usage Examples
139
140
#### Basic Type Parameter Extraction
141
142
```java
143
// Define a generic base class
144
public abstract class BaseRepository<T> {
145
private final Class<T> entityClass;
146
147
public BaseRepository() {
148
this.entityClass = Generics.getTypeParameter(getClass());
149
}
150
151
public Class<T> getEntityClass() {
152
return entityClass;
153
}
154
}
155
156
// Concrete implementation
157
public class UserRepository extends BaseRepository<User> {
158
// Constructor automatically determines T = User
159
}
160
161
// Usage
162
UserRepository userRepo = new UserRepository();
163
Class<?> entityClass = userRepo.getEntityClass(); // Returns User.class
164
```
165
166
#### Bounded Type Parameter Extraction
167
168
```java
169
// Define classes with inheritance hierarchy
170
public abstract class Entity {
171
// Base entity class
172
}
173
174
public class User extends Entity {
175
// User entity
176
}
177
178
public class Product extends Entity {
179
// Product entity
180
}
181
182
// Generic service with bounded type parameter
183
public abstract class EntityService<T extends Entity> {
184
private final Class<T> entityClass;
185
186
public EntityService() {
187
this.entityClass = Generics.getTypeParameter(getClass(), Entity.class);
188
}
189
190
public Class<T> getEntityClass() {
191
return entityClass;
192
}
193
}
194
195
// Concrete implementations
196
public class UserService extends EntityService<User> {
197
// Constructor automatically determines T = User (bounded by Entity)
198
}
199
200
public class ProductService extends EntityService<Product> {
201
// Constructor automatically determines T = Product (bounded by Entity)
202
}
203
204
// Usage
205
UserService userService = new UserService();
206
Class<User> userClass = userService.getEntityClass(); // Returns User.class
207
208
ProductService productService = new ProductService();
209
Class<Product> productClass = productService.getEntityClass(); // Returns Product.class
210
```
211
212
#### Repository Pattern with Type Safety
213
214
```java
215
public abstract class GenericDao<T> {
216
private final Class<T> entityClass;
217
218
public GenericDao() {
219
this.entityClass = Generics.getTypeParameter(getClass());
220
}
221
222
public T findById(Long id) {
223
// Use entityClass for database operations
224
return entityManager.find(entityClass, id);
225
}
226
227
public List<T> findAll() {
228
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
229
CriteriaQuery<T> query = cb.createQuery(entityClass);
230
query.select(query.from(entityClass));
231
return entityManager.createQuery(query).getResultList();
232
}
233
234
public void save(T entity) {
235
entityManager.persist(entity);
236
}
237
}
238
239
// Concrete DAOs
240
public class UserDao extends GenericDao<User> {
241
// Inherits all generic operations typed for User
242
}
243
244
public class OrderDao extends GenericDao<Order> {
245
// Inherits all generic operations typed for Order
246
}
247
```
248
249
#### Jackson/JSON Serialization Support
250
251
```java
252
public abstract class JsonHandler<T> {
253
private final Class<T> typeClass;
254
private final ObjectMapper objectMapper;
255
256
public JsonHandler(ObjectMapper objectMapper) {
257
this.typeClass = Generics.getTypeParameter(getClass());
258
this.objectMapper = objectMapper;
259
}
260
261
public T deserialize(String json) throws IOException {
262
return objectMapper.readValue(json, typeClass);
263
}
264
265
public String serialize(T object) throws IOException {
266
return objectMapper.writeValueAsString(object);
267
}
268
269
public Class<T> getTypeClass() {
270
return typeClass;
271
}
272
}
273
274
// Concrete handlers
275
public class UserJsonHandler extends JsonHandler<User> {
276
public UserJsonHandler(ObjectMapper objectMapper) {
277
super(objectMapper);
278
}
279
}
280
281
// Usage
282
ObjectMapper mapper = new ObjectMapper();
283
UserJsonHandler userHandler = new UserJsonHandler(mapper);
284
285
String userJson = "{\"name\":\"John\",\"email\":\"john@example.com\"}";
286
User user = userHandler.deserialize(userJson);
287
String serialized = userHandler.serialize(user);
288
```
289
290
## Error Handling
291
292
### Enums Error Handling
293
294
```java
295
public enum Color {
296
RED, GREEN, BLUE
297
}
298
299
// fromStringFuzzy returns null for no match (doesn't throw exception)
300
Enum<?> result = Enums.fromStringFuzzy("yellow", Color.values());
301
if (result == null) {
302
// Handle unknown enum value
303
throw new IllegalArgumentException("Unknown color: yellow");
304
}
305
```
306
307
### Generics Error Handling
308
309
```java
310
// Generics throws IllegalStateException for complex type scenarios
311
try {
312
Class<?> typeParam = Generics.getTypeParameter(SomeComplexClass.class);
313
} catch (IllegalStateException e) {
314
// Handle cases where type parameterization cannot be determined
315
// This typically happens with complex type hierarchies or runtime type erasure issues
316
}
317
```
318
319
## Advanced Patterns
320
321
### Configuration with Enum Defaults
322
323
```java
324
public class ServiceConfiguration {
325
public enum Environment {
326
DEVELOPMENT, STAGING, PRODUCTION
327
}
328
329
public Environment parseEnvironment(String envString, Environment defaultEnv) {
330
if (envString == null || envString.trim().isEmpty()) {
331
return defaultEnv;
332
}
333
334
Environment env = (Environment) Enums.fromStringFuzzy(envString, Environment.values());
335
return env != null ? env : defaultEnv;
336
}
337
}
338
```
339
340
### Generic Factory Pattern
341
342
```java
343
public abstract class EntityFactory<T> {
344
private final Class<T> entityClass;
345
346
public EntityFactory() {
347
this.entityClass = Generics.getTypeParameter(getClass());
348
}
349
350
public T createEntity() {
351
try {
352
return entityClass.getDeclaredConstructor().newInstance();
353
} catch (Exception e) {
354
throw new RuntimeException("Cannot create entity of type: " + entityClass, e);
355
}
356
}
357
358
public Class<T> getEntityType() {
359
return entityClass;
360
}
361
}
362
```