0
# Polymorphic Schema Factories
1
2
Factory system for creating polymorphic schemas that handle inheritance, collections, and complex object hierarchies. Polymorphic schemas enable protostuff-runtime to serialize and deserialize objects when the exact type is not known at compile time, supporting inheritance, collections, maps, and other complex object graphs.
3
4
## Capabilities
5
6
### PolymorphicSchemaFactories Enum
7
8
Central enum providing predefined factory implementations for different types of polymorphic scenarios.
9
10
```java { .api }
11
/**
12
* Enum providing polymorphic schema factories for different object types
13
*/
14
public enum PolymorphicSchemaFactories implements PolymorphicSchema.Factory {
15
16
/**
17
* Factory for array types
18
*/
19
ARRAY,
20
21
/**
22
* Factory for numeric wrapper types (Integer, Long, etc.)
23
*/
24
NUMBER,
25
26
/**
27
* Factory for Class objects
28
*/
29
CLASS,
30
31
/**
32
* Factory for enum types
33
*/
34
ENUM,
35
36
/**
37
* Factory for collection types (List, Set, etc.)
38
*/
39
COLLECTION,
40
41
/**
42
* Factory for map types
43
*/
44
MAP,
45
46
/**
47
* Factory for Throwable and exception types
48
*/
49
THROWABLE,
50
51
/**
52
* Factory for Plain Old Java Objects (POJOs)
53
*/
54
POJO,
55
56
/**
57
* Factory for POJO map implementations
58
*/
59
POJO_MAP,
60
61
/**
62
* Factory for POJO collection implementations
63
*/
64
POJO_COLLECTION,
65
66
/**
67
* Factory for generic Object types
68
*/
69
OBJECT;
70
}
71
```
72
73
### Factory Selection Methods
74
75
Static methods for automatically selecting appropriate factory based on field or type information.
76
77
```java { .api }
78
/**
79
* Get appropriate factory based on field reflection information
80
* @param f Java reflection field to analyze
81
* @param strategy ID strategy for polymorphic handling
82
* @return Appropriate polymorphic schema factory
83
*/
84
public static PolymorphicSchema.Factory getFactoryFromField(java.lang.reflect.Field f, IdStrategy strategy);
85
86
/**
87
* Get factory for repeated value generic types
88
* @param clazz Class with generic type information
89
* @return Appropriate factory for the repeated value type
90
*/
91
public static PolymorphicSchema.Factory getFactoryFromRepeatedValueGenericType(Class<?> clazz);
92
93
/**
94
* Get schema for collection or map with generic type information
95
* @param clazz Collection or map class
96
* @param strategy ID strategy for polymorphic handling
97
* @return Polymorphic schema instance
98
*/
99
public static PolymorphicSchema getSchemaFromCollectionOrMapGenericType(Class<?> clazz, IdStrategy strategy);
100
```
101
102
## Polymorphic Schema Classes
103
104
### PolymorphicSchema Base Class
105
106
Base class for all polymorphic schema implementations providing common functionality for type identification and serialization.
107
108
```java { .api }
109
/**
110
* Base class for polymorphic schema implementations
111
*/
112
public abstract class PolymorphicSchema implements Schema<Object> {
113
114
/**
115
* Factory interface for creating polymorphic schemas
116
*/
117
public interface Factory {
118
/**
119
* Create polymorphic schema for the specified class
120
* @param typeClass Class to create schema for
121
* @param strategy ID strategy for type handling
122
* @return Polymorphic schema instance
123
*/
124
PolymorphicSchema create(Class<?> typeClass, IdStrategy strategy);
125
}
126
127
/**
128
* Get the ID strategy used by this schema
129
* @return ID strategy instance
130
*/
131
public IdStrategy getStrategy();
132
133
/**
134
* Create new message instance
135
* @return New Object instance
136
*/
137
public Object newMessage();
138
139
/**
140
* Get message name for this schema
141
* @return Message name string
142
*/
143
public String messageName();
144
145
/**
146
* Get full message name for this schema
147
* @return Full message name string
148
*/
149
public String messageFullName();
150
151
/**
152
* Get type class for this schema
153
* @return Class type
154
*/
155
public Class<Object> typeClass();
156
}
157
```
158
159
### Specialized Polymorphic Schema Classes
160
161
Concrete implementations for specific polymorphic scenarios.
162
163
```java { .api }
164
/**
165
* Polymorphic schema for array types
166
*/
167
public abstract class ArraySchema extends PolymorphicSchema {
168
// Handles arrays of various types with type information
169
}
170
171
/**
172
* Polymorphic schema for numeric wrapper types
173
*/
174
public abstract class NumberSchema extends PolymorphicSchema {
175
// Handles Integer, Long, Double, Float, etc.
176
}
177
178
/**
179
* Polymorphic schema for Class objects
180
*/
181
public abstract class ClassSchema extends PolymorphicSchema {
182
// Handles Class<?> instances with type safety
183
}
184
185
/**
186
* Polymorphic schema for enum types
187
*/
188
public abstract class PolymorphicEnumSchema extends PolymorphicSchema {
189
// Handles enum values with type identification
190
}
191
192
/**
193
* Polymorphic schema for collection types
194
*/
195
public abstract class PolymorphicCollectionSchema extends PolymorphicSchema {
196
// Handles List, Set, Queue, and other collection interfaces
197
}
198
199
/**
200
* Polymorphic schema for map types
201
*/
202
public abstract class PolymorphicMapSchema extends PolymorphicSchema {
203
// Handles Map interfaces and implementations
204
}
205
206
/**
207
* Polymorphic schema for POJO types
208
*/
209
public abstract class PolymorphicPojoSchema extends PolymorphicSchema {
210
// Handles Plain Old Java Objects with inheritance
211
}
212
213
/**
214
* Polymorphic schema for POJO collections
215
*/
216
public abstract class PolymorphicPojoCollectionSchema extends PolymorphicSchema {
217
// Handles collections containing POJOs
218
}
219
220
/**
221
* Polymorphic schema for POJO maps
222
*/
223
public abstract class PolymorphicPojoMapSchema extends PolymorphicSchema {
224
// Handles maps containing POJOs
225
}
226
227
/**
228
* Polymorphic schema for Throwable types
229
*/
230
public abstract class PolymorphicThrowableSchema extends PolymorphicSchema {
231
// Handles exceptions and errors with inheritance
232
}
233
234
/**
235
* Polymorphic schema for generic Object types
236
*/
237
public abstract class ObjectSchema extends PolymorphicSchema {
238
// Handles generic Object references
239
}
240
```
241
242
### DerivativeSchema
243
244
Special schema implementation for handling derived or wrapped types.
245
246
```java { .api }
247
/**
248
* Schema for derivative types that wrap or extend other types
249
*/
250
public abstract class DerivativeSchema implements Schema<Object> {
251
252
/**
253
* Get the base schema this derivative extends
254
* @return Base schema instance
255
*/
256
public abstract Schema<?> getBaseSchema();
257
258
/**
259
* Check if this schema can handle the specified type
260
* @param typeClass Class to check
261
* @return true if this schema can handle the type
262
*/
263
public abstract boolean canHandle(Class<?> typeClass);
264
}
265
```
266
267
## Usage Examples
268
269
### Automatic Factory Selection
270
271
```java
272
import io.protostuff.runtime.PolymorphicSchemaFactories;
273
import io.protostuff.runtime.DefaultIdStrategy;
274
import java.lang.reflect.Field;
275
276
// Automatic factory selection based on field
277
public class User {
278
public List<String> tags; // Collection field
279
public Map<String, Object> data; // Map field
280
public Animal pet; // POJO field with inheritance
281
public Status status; // Enum field
282
}
283
284
DefaultIdStrategy strategy = new DefaultIdStrategy();
285
286
// Get factories for different field types
287
Field tagsField = User.class.getField("tags");
288
PolymorphicSchema.Factory collectionFactory =
289
PolymorphicSchemaFactories.getFactoryFromField(tagsField, strategy);
290
291
Field dataField = User.class.getField("data");
292
PolymorphicSchema.Factory mapFactory =
293
PolymorphicSchemaFactories.getFactoryFromField(dataField, strategy);
294
295
Field petField = User.class.getField("pet");
296
PolymorphicSchema.Factory pojoFactory =
297
PolymorphicSchemaFactories.getFactoryFromField(petField, strategy);
298
299
Field statusField = User.class.getField("status");
300
PolymorphicSchema.Factory enumFactory =
301
PolymorphicSchemaFactories.getFactoryFromField(statusField, strategy);
302
```
303
304
### Manual Factory Usage
305
306
```java
307
// Direct factory usage for specific scenarios
308
DefaultIdStrategy strategy = new DefaultIdStrategy();
309
310
// Create schemas using specific factories
311
PolymorphicSchema arraySchema = PolymorphicSchemaFactories.ARRAY.create(String[].class, strategy);
312
PolymorphicSchema collectionSchema = PolymorphicSchemaFactories.COLLECTION.create(List.class, strategy);
313
PolymorphicSchema mapSchema = PolymorphicSchemaFactories.MAP.create(Map.class, strategy);
314
PolymorphicSchema pojoSchema = PolymorphicSchemaFactories.POJO.create(User.class, strategy);
315
316
// Use schemas for polymorphic serialization
317
// (requires protostuff-core for actual serialization)
318
```
319
320
### Collection and Map Generic Type Handling
321
322
```java
323
import java.util.*;
324
325
// Handle complex generic types
326
Class<List<User>> userListClass = (Class<List<User>>) (Class<?>) List.class;
327
PolymorphicSchema userListSchema =
328
PolymorphicSchemaFactories.getSchemaFromCollectionOrMapGenericType(userListClass, strategy);
329
330
Class<Map<String, List<User>>> complexMapClass =
331
(Class<Map<String, List<User>>>) (Class<?>) Map.class;
332
PolymorphicSchema complexMapSchema =
333
PolymorphicSchemaFactories.getSchemaFromCollectionOrMapGenericType(complexMapClass, strategy);
334
335
// Factory for repeated value types in collections
336
PolymorphicSchema.Factory repeatedFactory =
337
PolymorphicSchemaFactories.getFactoryFromRepeatedValueGenericType(User.class);
338
```
339
340
### Inheritance Hierarchy Handling
341
342
```java
343
// Define inheritance hierarchy
344
public abstract class Animal {
345
public String name;
346
}
347
348
public class Dog extends Animal {
349
public String breed;
350
}
351
352
public class Cat extends Animal {
353
public boolean indoor;
354
}
355
356
// Register polymorphic types
357
DefaultIdStrategy strategy = new DefaultIdStrategy();
358
strategy.registerPojo(Animal.class);
359
strategy.registerPojo(Dog.class);
360
strategy.registerPojo(Cat.class);
361
362
// Map inheritance relationships
363
strategy.map(Animal.class, Dog.class);
364
strategy.map(Animal.class, Cat.class);
365
366
// Create polymorphic schema for the base class
367
PolymorphicSchema animalSchema = PolymorphicSchemaFactories.POJO.create(Animal.class, strategy);
368
369
// The schema can now handle Dog, Cat, or any other Animal subtype
370
```
371
372
### Custom Polymorphic Schema Creation
373
374
```java
375
/**
376
* Custom polymorphic schema factory for special handling
377
*/
378
public class CustomPolymorphicFactory implements PolymorphicSchema.Factory {
379
380
@Override
381
public PolymorphicSchema create(Class<?> typeClass, IdStrategy strategy) {
382
if (isSpecialType(typeClass)) {
383
return new CustomPolymorphicSchema(typeClass, strategy);
384
}
385
// Delegate to appropriate default factory
386
return PolymorphicSchemaFactories.POJO.create(typeClass, strategy);
387
}
388
389
private boolean isSpecialType(Class<?> typeClass) {
390
// Custom logic to identify special types
391
return typeClass.isAnnotationPresent(CustomSerialization.class);
392
}
393
}
394
395
// Custom schema implementation
396
public class CustomPolymorphicSchema extends PolymorphicSchema {
397
398
private final Class<?> typeClass;
399
private final IdStrategy strategy;
400
401
public CustomPolymorphicSchema(Class<?> typeClass, IdStrategy strategy) {
402
this.typeClass = typeClass;
403
this.strategy = strategy;
404
}
405
406
@Override
407
public Object newMessage() {
408
// Custom object creation logic
409
return createCustomInstance(typeClass);
410
}
411
412
// Implement other required methods...
413
}
414
```
415
416
## Factory Selection Logic
417
418
The `getFactoryFromField` method uses the following logic to select appropriate factories:
419
420
1. **Array Types**: Returns `ARRAY` factory for array fields
421
2. **Collection Types**: Returns `COLLECTION` for List, Set, Queue interfaces
422
3. **Map Types**: Returns `MAP` for Map interfaces
423
4. **Enum Types**: Returns `ENUM` for enum fields
424
5. **Number Types**: Returns `NUMBER` for numeric wrapper types
425
6. **Class Types**: Returns `CLASS` for Class<?> fields
426
7. **Throwable Types**: Returns `THROWABLE` for exception fields
427
8. **POJO Types**: Returns `POJO` for custom object types
428
9. **Object Types**: Returns `OBJECT` for generic Object fields
429
430
## Configuration with IdStrategy
431
432
Polymorphic schemas work closely with `IdStrategy` configuration:
433
434
```java
435
// Configure strategy with polymorphic flags
436
int flags = IdStrategy.MORPH_COLLECTION_INTERFACES
437
| IdStrategy.MORPH_MAP_INTERFACES
438
| IdStrategy.MORPH_NON_FINAL_POJOS
439
| IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
440
441
DefaultIdStrategy strategy = new DefaultIdStrategy(flags);
442
443
// Register types for polymorphic handling
444
strategy.registerPojo(BaseClass.class);
445
strategy.registerPojo(DerivedClass1.class);
446
strategy.registerPojo(DerivedClass2.class);
447
448
// Create polymorphic schemas with configured strategy
449
PolymorphicSchema schema = PolymorphicSchemaFactories.POJO.create(BaseClass.class, strategy);
450
```
451
452
## Performance Considerations
453
454
1. **Factory Caching**: Factories cache created schemas for performance
455
2. **Type Registration**: Pre-register polymorphic types for better performance
456
3. **Strategy Configuration**: Configure IdStrategy flags appropriately for your use case
457
4. **Generic Type Resolution**: Complex generic types may have resolution overhead
458
5. **Inheritance Depth**: Deep inheritance hierarchies may impact performance
459
460
## Best Practices
461
462
1. **Type Registration**: Register all polymorphic types upfront with IdStrategy
463
2. **Factory Selection**: Use automatic factory selection when possible
464
3. **Generic Types**: Be explicit about generic type parameters for better schema generation
465
4. **Strategy Configuration**: Configure IdStrategy flags based on your polymorphic requirements
466
5. **Error Handling**: Handle UnknownTypeException for unregistered polymorphic types
467
6. **Testing**: Test polymorphic serialization with all expected type combinations