0
# Type Strategy and Polymorphic Handling
1
2
Advanced type identification and polymorphic serialization strategies for handling inheritance hierarchies, collections, and complex object structures. The type strategy system allows protostuff-runtime to handle polymorphic types, custom serialization delegates, and complex object graphs.
3
4
## Capabilities
5
6
### IdStrategy Base Class
7
8
Abstract base class defining the interface for type identification strategies used in polymorphic serialization.
9
10
```java { .api }
11
/**
12
* Abstract base class for type identification strategies
13
*/
14
public abstract class IdStrategy {
15
16
/**
17
* Configuration flags for strategy behavior
18
*/
19
public final int flags;
20
public final IdStrategy primaryGroup;
21
public final int groupId;
22
23
/**
24
* Check if a delegate is registered for the specified type
25
* @param typeClass The class to check
26
* @return true if a delegate is registered
27
*/
28
public abstract boolean isDelegateRegistered(Class<?> typeClass);
29
30
/**
31
* Get delegate wrapper for polymorphic contexts
32
* @param typeClass The class to get delegate for
33
* @return HasDelegate wrapper or null if not found
34
*/
35
public abstract <T> HasDelegate<T> getDelegateWrapper(Class<? super T> typeClass);
36
37
/**
38
* Get delegate for the specified type
39
* @param typeClass The class to get delegate for
40
* @return Delegate instance or null if not found
41
*/
42
public abstract <T> Delegate<T> getDelegate(Class<? super T> typeClass);
43
44
/**
45
* Check if a type is registered with this strategy
46
* @param typeClass The class to check
47
* @return true if registered
48
*/
49
public abstract boolean isRegistered(Class<?> typeClass);
50
51
/**
52
* Get schema wrapper for the specified type
53
* @param typeClass The class to get schema for
54
* @param create Whether to create if not found
55
* @return HasSchema wrapper
56
*/
57
public abstract <T> HasSchema<T> getSchemaWrapper(Class<T> typeClass, boolean create);
58
}
59
```
60
61
### IdStrategy Configuration Flags
62
63
Configuration constants for controlling strategy behavior across various serialization scenarios.
64
65
```java { .api }
66
/**
67
* Serialize enums by name instead of ordinal value
68
*/
69
public static final int ENUMS_BY_NAME = 1;
70
71
/**
72
* Automatically load polymorphic classes when encountered
73
*/
74
public static final int AUTO_LOAD_POLYMORPHIC_CLASSES = 1 << 1;
75
76
/**
77
* Preserve null elements in collections and arrays
78
*/
79
public static final int PRESERVE_NULL_ELEMENTS = 1 << 2;
80
81
/**
82
* Enable morphing for non-final POJO types
83
*/
84
public static final int MORPH_NON_FINAL_POJOS = 1 << 3;
85
86
/**
87
* Enable morphing for collection interfaces (List, Set, etc.)
88
*/
89
public static final int MORPH_COLLECTION_INTERFACES = 1 << 4;
90
91
/**
92
* Enable morphing for map interfaces
93
*/
94
public static final int MORPH_MAP_INTERFACES = 1 << 5;
95
96
/**
97
* Use collection schema on repeated fields
98
*/
99
public static final int COLLECTION_SCHEMA_ON_REPEATED_FIELDS = 1 << 6;
100
101
/**
102
* Use POJO schema on collection fields
103
*/
104
public static final int POJO_SCHEMA_ON_COLLECTION_FIELDS = 1 << 7;
105
106
/**
107
* Use POJO schema on map fields
108
*/
109
public static final int POJO_SCHEMA_ON_MAP_FIELDS = 1 << 8;
110
111
/**
112
* Default flags combining common settings
113
*/
114
public static final int DEFAULT_FLAGS;
115
```
116
117
### DefaultIdStrategy Implementation
118
119
Concrete implementation of IdStrategy using fully qualified class names (FQCN) as type identifiers.
120
121
```java { .api }
122
/**
123
* Default ID strategy using fully qualified class names
124
*/
125
public final class DefaultIdStrategy extends IdStrategy {
126
127
/**
128
* Create DefaultIdStrategy with default settings
129
*/
130
public DefaultIdStrategy();
131
132
/**
133
* Create DefaultIdStrategy with custom flags
134
* @param flags Configuration flags
135
*/
136
public DefaultIdStrategy(int flags);
137
138
/**
139
* Create DefaultIdStrategy with primary group
140
* @param primaryGroup Primary strategy group
141
* @param groupId Group identifier
142
*/
143
public DefaultIdStrategy(IdStrategy primaryGroup, int groupId);
144
145
/**
146
* Create DefaultIdStrategy with all options
147
* @param flags Configuration flags
148
* @param primaryGroup Primary strategy group
149
* @param groupId Group identifier
150
*/
151
public DefaultIdStrategy(int flags, IdStrategy primaryGroup, int groupId);
152
}
153
```
154
155
### POJO Type Registration
156
157
Methods for registering Plain Old Java Objects with the type strategy.
158
159
```java { .api }
160
/**
161
* Register a POJO type with automatic schema generation
162
* @param typeClass The POJO class to register
163
* @return true if registration was successful
164
*/
165
public <T> boolean registerPojo(Class<T> typeClass);
166
167
/**
168
* Register a POJO type with custom schema
169
* @param typeClass The POJO class to register
170
* @param schema Custom schema for the POJO
171
* @return true if registration was successful
172
*/
173
public <T> boolean registerPojo(Class<T> typeClass, Schema<T> schema);
174
175
/**
176
* Map inheritance relationship for polymorphic handling
177
* @param baseClass The base/parent class
178
* @param typeClass The concrete/child class
179
* @return true if mapping was successful
180
*/
181
public <T> boolean map(Class<? super T> baseClass, Class<T> typeClass);
182
```
183
184
**Usage Examples:**
185
186
```java
187
DefaultIdStrategy strategy = new DefaultIdStrategy();
188
189
// Register POJOs
190
strategy.registerPojo(User.class);
191
strategy.registerPojo(Order.class);
192
193
// Register with custom schema
194
Schema<SpecialObject> customSchema = new MyCustomSchema();
195
strategy.registerPojo(SpecialObject.class, customSchema);
196
197
// Map inheritance hierarchies
198
strategy.map(Animal.class, Dog.class);
199
strategy.map(Animal.class, Cat.class);
200
strategy.map(Shape.class, Circle.class);
201
strategy.map(Shape.class, Rectangle.class);
202
```
203
204
### Enum Type Registration
205
206
Support for registering and configuring enum serialization behavior.
207
208
```java { .api }
209
/**
210
* Register an enum type for polymorphic serialization
211
* @param enumClass The enum class to register
212
* @return true if registration was successful
213
*/
214
public <T extends Enum<T>> boolean registerEnum(Class<T> enumClass);
215
```
216
217
**Usage Examples:**
218
219
```java
220
// Register enums for polymorphic handling
221
strategy.registerEnum(Status.class);
222
strategy.registerEnum(Priority.class);
223
strategy.registerEnum(Color.class);
224
225
// Configure enum serialization by name
226
DefaultIdStrategy strategyWithNames = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);
227
strategyWithNames.registerEnum(Status.class);
228
```
229
230
### Delegate Registration
231
232
Register custom serialization delegates for specific types.
233
234
```java { .api }
235
/**
236
* Register a delegate for custom serialization
237
* @param delegate The delegate implementation
238
* @return true if registration was successful
239
*/
240
public <T> boolean registerDelegate(Delegate<T> delegate);
241
242
/**
243
* Register a delegate by class name
244
* @param className The fully qualified class name
245
* @param delegate The delegate implementation
246
* @return true if registration was successful
247
*/
248
public <T> boolean registerDelegate(String className, Delegate<T> delegate);
249
```
250
251
**Usage Examples:**
252
253
```java
254
// Custom delegate for Date serialization
255
Delegate<Date> dateDelegate = new DateDelegate();
256
strategy.registerDelegate(dateDelegate);
257
258
// Register by class name (useful for optional dependencies)
259
strategy.registerDelegate("java.time.LocalDateTime", new LocalDateTimeDelegate());
260
```
261
262
### Collection and Map Registration
263
264
Register factories for polymorphic collection and map handling.
265
266
```java { .api }
267
/**
268
* Register a collection factory for polymorphic collections
269
* @param factory Collection message factory
270
* @return true if registration was successful
271
*/
272
public boolean registerCollection(CollectionSchema.MessageFactory factory);
273
274
/**
275
* Register a map factory for polymorphic maps
276
* @param factory Map message factory
277
* @return true if registration was successful
278
*/
279
public boolean registerMap(MapSchema.MessageFactory factory);
280
```
281
282
**Usage Examples:**
283
284
```java
285
// Register custom collection factories
286
CollectionSchema.MessageFactory listFactory = new MyListFactory();
287
strategy.registerCollection(listFactory);
288
289
MapSchema.MessageFactory mapFactory = new MyMapFactory();
290
strategy.registerMap(mapFactory);
291
```
292
293
### UnknownTypeException
294
295
Exception thrown when encountering unknown polymorphic types in strict mode.
296
297
```java { .api }
298
/**
299
* Exception thrown for unknown polymorphic types
300
*/
301
public static class UnknownTypeException extends RuntimeException {
302
303
/**
304
* Create exception with type information
305
* @param type The unknown type
306
*/
307
public UnknownTypeException(String type);
308
309
/**
310
* Create exception with type and cause
311
* @param type The unknown type
312
* @param cause The underlying cause
313
*/
314
public UnknownTypeException(String type, Throwable cause);
315
}
316
```
317
318
### IdStrategy Factory Interface
319
320
Factory interface for creating IdStrategy instances, useful for dependency injection and configuration.
321
322
```java { .api }
323
/**
324
* Factory interface for creating IdStrategy instances
325
*/
326
public interface Factory {
327
328
/**
329
* Create a new IdStrategy instance
330
* @return New IdStrategy instance
331
*/
332
IdStrategy create();
333
334
/**
335
* Post-creation configuration hook
336
*/
337
void postCreate();
338
}
339
```
340
341
## Configuration Examples
342
343
### Basic Configuration
344
345
```java
346
// Default strategy with standard settings
347
DefaultIdStrategy basicStrategy = new DefaultIdStrategy();
348
349
// Strategy with enum names instead of ordinals
350
DefaultIdStrategy enumNamesStrategy = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);
351
352
// Strategy with null preservation in collections
353
DefaultIdStrategy nullPreservingStrategy = new DefaultIdStrategy(
354
IdStrategy.PRESERVE_NULL_ELEMENTS | IdStrategy.ENUMS_BY_NAME
355
);
356
```
357
358
### Advanced Configuration
359
360
```java
361
// Comprehensive strategy with multiple flags
362
int advancedFlags = IdStrategy.ENUMS_BY_NAME
363
| IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES
364
| IdStrategy.PRESERVE_NULL_ELEMENTS
365
| IdStrategy.MORPH_NON_FINAL_POJOS
366
| IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
367
368
DefaultIdStrategy advancedStrategy = new DefaultIdStrategy(advancedFlags);
369
370
// Register all application types
371
advancedStrategy.registerPojo(User.class);
372
advancedStrategy.registerPojo(Order.class);
373
advancedStrategy.registerPojo(Product.class);
374
advancedStrategy.registerEnum(Status.class);
375
advancedStrategy.registerEnum(Priority.class);
376
377
// Set up inheritance hierarchies
378
advancedStrategy.map(BaseEntity.class, User.class);
379
advancedStrategy.map(BaseEntity.class, Order.class);
380
advancedStrategy.map(BaseEntity.class, Product.class);
381
```
382
383
### Custom Strategy Implementation
384
385
```java
386
// Custom strategy extending DefaultIdStrategy
387
public class ApplicationIdStrategy extends DefaultIdStrategy {
388
389
public ApplicationIdStrategy() {
390
super(IdStrategy.ENUMS_BY_NAME | IdStrategy.PRESERVE_NULL_ELEMENTS);
391
392
// Register application-specific types
393
registerApplicationTypes();
394
}
395
396
private void registerApplicationTypes() {
397
// POJOs
398
registerPojo(User.class);
399
registerPojo(Order.class);
400
registerPojo(Product.class);
401
402
// Enums
403
registerEnum(Status.class);
404
registerEnum(Priority.class);
405
406
// Custom delegates
407
registerDelegate(new TimestampDelegate());
408
registerDelegate(new MoneyDelegate());
409
410
// Inheritance mappings
411
map(BaseEntity.class, User.class);
412
map(BaseEntity.class, Order.class);
413
}
414
}
415
```
416
417
## Polymorphic Schema Factories
418
419
Enum defining factory types for different polymorphic schema scenarios.
420
421
```java { .api }
422
/**
423
* Predefined polymorphic schema factories
424
*/
425
public enum PolymorphicSchemaFactories {
426
ARRAY, // Array type factory
427
NUMBER, // Number type factory
428
CLASS, // Class type factory
429
ENUM, // Enum type factory
430
COLLECTION, // Collection type factory
431
MAP, // Map type factory
432
THROWABLE, // Throwable type factory
433
POJO, // POJO type factory
434
POJO_MAP, // POJO map factory
435
POJO_COLLECTION, // POJO collection factory
436
OBJECT; // Object type factory
437
438
/**
439
* Get factory from field information
440
* @param f The field to analyze
441
* @param strategy The ID strategy to use
442
* @return Appropriate polymorphic schema factory
443
*/
444
public static PolymorphicSchema.Factory getFactoryFromField(
445
java.lang.reflect.Field f, IdStrategy strategy);
446
447
/**
448
* Get factory from generic type information
449
* @param clazz The class with generic type information
450
* @return Appropriate polymorphic schema factory
451
*/
452
public static PolymorphicSchema.Factory getFactoryFromRepeatedValueGenericType(Class<?> clazz);
453
454
/**
455
* Get schema from collection or map generic type
456
* @param clazz The collection or map class
457
* @param strategy The ID strategy to use
458
* @return Polymorphic schema instance
459
*/
460
public static PolymorphicSchema getSchemaFromCollectionOrMapGenericType(
461
Class<?> clazz, IdStrategy strategy);
462
}
463
```
464
465
## Best Practices
466
467
1. **Strategy Configuration**: Configure your IdStrategy with appropriate flags for your use case
468
2. **Type Registration**: Register all polymorphic types upfront for better performance
469
3. **Inheritance Mapping**: Use `map()` to establish clear inheritance relationships
470
4. **Custom Delegates**: Implement delegates for types requiring special serialization logic
471
5. **Flag Combinations**: Combine flags using bitwise OR operations for complex configurations
472
6. **Factory Pattern**: Use IdStrategy.Factory for dependency injection scenarios