Protobuf serialization for pre-existing objects with runtime schema generation and polymorphic type handling
—
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.
Abstract base class defining the interface for type identification strategies used in polymorphic serialization.
/**
* Abstract base class for type identification strategies
*/
public abstract class IdStrategy {
/**
* Configuration flags for strategy behavior
*/
public final int flags;
public final IdStrategy primaryGroup;
public final int groupId;
/**
* Check if a delegate is registered for the specified type
* @param typeClass The class to check
* @return true if a delegate is registered
*/
public abstract boolean isDelegateRegistered(Class<?> typeClass);
/**
* Get delegate wrapper for polymorphic contexts
* @param typeClass The class to get delegate for
* @return HasDelegate wrapper or null if not found
*/
public abstract <T> HasDelegate<T> getDelegateWrapper(Class<? super T> typeClass);
/**
* Get delegate for the specified type
* @param typeClass The class to get delegate for
* @return Delegate instance or null if not found
*/
public abstract <T> Delegate<T> getDelegate(Class<? super T> typeClass);
/**
* Check if a type is registered with this strategy
* @param typeClass The class to check
* @return true if registered
*/
public abstract boolean isRegistered(Class<?> typeClass);
/**
* Get schema wrapper for the specified type
* @param typeClass The class to get schema for
* @param create Whether to create if not found
* @return HasSchema wrapper
*/
public abstract <T> HasSchema<T> getSchemaWrapper(Class<T> typeClass, boolean create);
}Configuration constants for controlling strategy behavior across various serialization scenarios.
/**
* Serialize enums by name instead of ordinal value
*/
public static final int ENUMS_BY_NAME = 1;
/**
* Automatically load polymorphic classes when encountered
*/
public static final int AUTO_LOAD_POLYMORPHIC_CLASSES = 1 << 1;
/**
* Preserve null elements in collections and arrays
*/
public static final int PRESERVE_NULL_ELEMENTS = 1 << 2;
/**
* Enable morphing for non-final POJO types
*/
public static final int MORPH_NON_FINAL_POJOS = 1 << 3;
/**
* Enable morphing for collection interfaces (List, Set, etc.)
*/
public static final int MORPH_COLLECTION_INTERFACES = 1 << 4;
/**
* Enable morphing for map interfaces
*/
public static final int MORPH_MAP_INTERFACES = 1 << 5;
/**
* Use collection schema on repeated fields
*/
public static final int COLLECTION_SCHEMA_ON_REPEATED_FIELDS = 1 << 6;
/**
* Use POJO schema on collection fields
*/
public static final int POJO_SCHEMA_ON_COLLECTION_FIELDS = 1 << 7;
/**
* Use POJO schema on map fields
*/
public static final int POJO_SCHEMA_ON_MAP_FIELDS = 1 << 8;
/**
* Default flags combining common settings
*/
public static final int DEFAULT_FLAGS;Concrete implementation of IdStrategy using fully qualified class names (FQCN) as type identifiers.
/**
* Default ID strategy using fully qualified class names
*/
public final class DefaultIdStrategy extends IdStrategy {
/**
* Create DefaultIdStrategy with default settings
*/
public DefaultIdStrategy();
/**
* Create DefaultIdStrategy with custom flags
* @param flags Configuration flags
*/
public DefaultIdStrategy(int flags);
/**
* Create DefaultIdStrategy with primary group
* @param primaryGroup Primary strategy group
* @param groupId Group identifier
*/
public DefaultIdStrategy(IdStrategy primaryGroup, int groupId);
/**
* Create DefaultIdStrategy with all options
* @param flags Configuration flags
* @param primaryGroup Primary strategy group
* @param groupId Group identifier
*/
public DefaultIdStrategy(int flags, IdStrategy primaryGroup, int groupId);
}Methods for registering Plain Old Java Objects with the type strategy.
/**
* Register a POJO type with automatic schema generation
* @param typeClass The POJO class to register
* @return true if registration was successful
*/
public <T> boolean registerPojo(Class<T> typeClass);
/**
* Register a POJO type with custom schema
* @param typeClass The POJO class to register
* @param schema Custom schema for the POJO
* @return true if registration was successful
*/
public <T> boolean registerPojo(Class<T> typeClass, Schema<T> schema);
/**
* Map inheritance relationship for polymorphic handling
* @param baseClass The base/parent class
* @param typeClass The concrete/child class
* @return true if mapping was successful
*/
public <T> boolean map(Class<? super T> baseClass, Class<T> typeClass);Usage Examples:
DefaultIdStrategy strategy = new DefaultIdStrategy();
// Register POJOs
strategy.registerPojo(User.class);
strategy.registerPojo(Order.class);
// Register with custom schema
Schema<SpecialObject> customSchema = new MyCustomSchema();
strategy.registerPojo(SpecialObject.class, customSchema);
// Map inheritance hierarchies
strategy.map(Animal.class, Dog.class);
strategy.map(Animal.class, Cat.class);
strategy.map(Shape.class, Circle.class);
strategy.map(Shape.class, Rectangle.class);Support for registering and configuring enum serialization behavior.
/**
* Register an enum type for polymorphic serialization
* @param enumClass The enum class to register
* @return true if registration was successful
*/
public <T extends Enum<T>> boolean registerEnum(Class<T> enumClass);Usage Examples:
// Register enums for polymorphic handling
strategy.registerEnum(Status.class);
strategy.registerEnum(Priority.class);
strategy.registerEnum(Color.class);
// Configure enum serialization by name
DefaultIdStrategy strategyWithNames = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);
strategyWithNames.registerEnum(Status.class);Register custom serialization delegates for specific types.
/**
* Register a delegate for custom serialization
* @param delegate The delegate implementation
* @return true if registration was successful
*/
public <T> boolean registerDelegate(Delegate<T> delegate);
/**
* Register a delegate by class name
* @param className The fully qualified class name
* @param delegate The delegate implementation
* @return true if registration was successful
*/
public <T> boolean registerDelegate(String className, Delegate<T> delegate);Usage Examples:
// Custom delegate for Date serialization
Delegate<Date> dateDelegate = new DateDelegate();
strategy.registerDelegate(dateDelegate);
// Register by class name (useful for optional dependencies)
strategy.registerDelegate("java.time.LocalDateTime", new LocalDateTimeDelegate());Register factories for polymorphic collection and map handling.
/**
* Register a collection factory for polymorphic collections
* @param factory Collection message factory
* @return true if registration was successful
*/
public boolean registerCollection(CollectionSchema.MessageFactory factory);
/**
* Register a map factory for polymorphic maps
* @param factory Map message factory
* @return true if registration was successful
*/
public boolean registerMap(MapSchema.MessageFactory factory);Usage Examples:
// Register custom collection factories
CollectionSchema.MessageFactory listFactory = new MyListFactory();
strategy.registerCollection(listFactory);
MapSchema.MessageFactory mapFactory = new MyMapFactory();
strategy.registerMap(mapFactory);Exception thrown when encountering unknown polymorphic types in strict mode.
/**
* Exception thrown for unknown polymorphic types
*/
public static class UnknownTypeException extends RuntimeException {
/**
* Create exception with type information
* @param type The unknown type
*/
public UnknownTypeException(String type);
/**
* Create exception with type and cause
* @param type The unknown type
* @param cause The underlying cause
*/
public UnknownTypeException(String type, Throwable cause);
}Factory interface for creating IdStrategy instances, useful for dependency injection and configuration.
/**
* Factory interface for creating IdStrategy instances
*/
public interface Factory {
/**
* Create a new IdStrategy instance
* @return New IdStrategy instance
*/
IdStrategy create();
/**
* Post-creation configuration hook
*/
void postCreate();
}// Default strategy with standard settings
DefaultIdStrategy basicStrategy = new DefaultIdStrategy();
// Strategy with enum names instead of ordinals
DefaultIdStrategy enumNamesStrategy = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);
// Strategy with null preservation in collections
DefaultIdStrategy nullPreservingStrategy = new DefaultIdStrategy(
IdStrategy.PRESERVE_NULL_ELEMENTS | IdStrategy.ENUMS_BY_NAME
);// Comprehensive strategy with multiple flags
int advancedFlags = IdStrategy.ENUMS_BY_NAME
| IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES
| IdStrategy.PRESERVE_NULL_ELEMENTS
| IdStrategy.MORPH_NON_FINAL_POJOS
| IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
DefaultIdStrategy advancedStrategy = new DefaultIdStrategy(advancedFlags);
// Register all application types
advancedStrategy.registerPojo(User.class);
advancedStrategy.registerPojo(Order.class);
advancedStrategy.registerPojo(Product.class);
advancedStrategy.registerEnum(Status.class);
advancedStrategy.registerEnum(Priority.class);
// Set up inheritance hierarchies
advancedStrategy.map(BaseEntity.class, User.class);
advancedStrategy.map(BaseEntity.class, Order.class);
advancedStrategy.map(BaseEntity.class, Product.class);// Custom strategy extending DefaultIdStrategy
public class ApplicationIdStrategy extends DefaultIdStrategy {
public ApplicationIdStrategy() {
super(IdStrategy.ENUMS_BY_NAME | IdStrategy.PRESERVE_NULL_ELEMENTS);
// Register application-specific types
registerApplicationTypes();
}
private void registerApplicationTypes() {
// POJOs
registerPojo(User.class);
registerPojo(Order.class);
registerPojo(Product.class);
// Enums
registerEnum(Status.class);
registerEnum(Priority.class);
// Custom delegates
registerDelegate(new TimestampDelegate());
registerDelegate(new MoneyDelegate());
// Inheritance mappings
map(BaseEntity.class, User.class);
map(BaseEntity.class, Order.class);
}
}Enum defining factory types for different polymorphic schema scenarios.
/**
* Predefined polymorphic schema factories
*/
public enum PolymorphicSchemaFactories {
ARRAY, // Array type factory
NUMBER, // Number type factory
CLASS, // Class type factory
ENUM, // Enum type factory
COLLECTION, // Collection type factory
MAP, // Map type factory
THROWABLE, // Throwable type factory
POJO, // POJO type factory
POJO_MAP, // POJO map factory
POJO_COLLECTION, // POJO collection factory
OBJECT; // Object type factory
/**
* Get factory from field information
* @param f The field to analyze
* @param strategy The ID strategy to use
* @return Appropriate polymorphic schema factory
*/
public static PolymorphicSchema.Factory getFactoryFromField(
java.lang.reflect.Field f, IdStrategy strategy);
/**
* Get factory from generic type information
* @param clazz The class with generic type information
* @return Appropriate polymorphic schema factory
*/
public static PolymorphicSchema.Factory getFactoryFromRepeatedValueGenericType(Class<?> clazz);
/**
* Get schema from collection or map generic type
* @param clazz The collection or map class
* @param strategy The ID strategy to use
* @return Polymorphic schema instance
*/
public static PolymorphicSchema getSchemaFromCollectionOrMapGenericType(
Class<?> clazz, IdStrategy strategy);
}map() to establish clear inheritance relationshipsInstall with Tessl CLI
npx tessl i tessl/maven-io-protostuff--protostuff-runtime