CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-protostuff--protostuff-runtime

Protobuf serialization for pre-existing objects with runtime schema generation and polymorphic type handling

Pending
Overview
Eval results
Files

polymorphic-schemas.mddocs/

Polymorphic Schema Factories

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.

Capabilities

PolymorphicSchemaFactories Enum

Central enum providing predefined factory implementations for different types of polymorphic scenarios.

/**
 * Enum providing polymorphic schema factories for different object types
 */
public enum PolymorphicSchemaFactories implements PolymorphicSchema.Factory {
    
    /**
     * Factory for array types
     */
    ARRAY,
    
    /**
     * Factory for numeric wrapper types (Integer, Long, etc.)
     */
    NUMBER,
    
    /**
     * Factory for Class objects
     */
    CLASS,
    
    /**
     * Factory for enum types
     */
    ENUM,
    
    /**
     * Factory for collection types (List, Set, etc.)
     */
    COLLECTION,
    
    /**
     * Factory for map types
     */
    MAP,
    
    /**
     * Factory for Throwable and exception types
     */
    THROWABLE,
    
    /**
     * Factory for Plain Old Java Objects (POJOs)
     */
    POJO,
    
    /**
     * Factory for POJO map implementations
     */
    POJO_MAP,
    
    /**
     * Factory for POJO collection implementations
     */
    POJO_COLLECTION,
    
    /**
     * Factory for generic Object types
     */
    OBJECT;
}

Factory Selection Methods

Static methods for automatically selecting appropriate factory based on field or type information.

/**
 * Get appropriate factory based on field reflection information
 * @param f Java reflection field to analyze
 * @param strategy ID strategy for polymorphic handling
 * @return Appropriate polymorphic schema factory
 */
public static PolymorphicSchema.Factory getFactoryFromField(java.lang.reflect.Field f, IdStrategy strategy);

/**
 * Get factory for repeated value generic types
 * @param clazz Class with generic type information
 * @return Appropriate factory for the repeated value type
 */
public static PolymorphicSchema.Factory getFactoryFromRepeatedValueGenericType(Class<?> clazz);

/**
 * Get schema for collection or map with generic type information
 * @param clazz Collection or map class
 * @param strategy ID strategy for polymorphic handling
 * @return Polymorphic schema instance
 */
public static PolymorphicSchema getSchemaFromCollectionOrMapGenericType(Class<?> clazz, IdStrategy strategy);

Polymorphic Schema Classes

PolymorphicSchema Base Class

Base class for all polymorphic schema implementations providing common functionality for type identification and serialization.

/**
 * Base class for polymorphic schema implementations
 */
public abstract class PolymorphicSchema implements Schema<Object> {
    
    /**
     * Factory interface for creating polymorphic schemas
     */
    public interface Factory {
        /**
         * Create polymorphic schema for the specified class
         * @param typeClass Class to create schema for
         * @param strategy ID strategy for type handling
         * @return Polymorphic schema instance
         */
        PolymorphicSchema create(Class<?> typeClass, IdStrategy strategy);
    }
    
    /**
     * Get the ID strategy used by this schema
     * @return ID strategy instance
     */
    public IdStrategy getStrategy();
    
    /**
     * Create new message instance
     * @return New Object instance
     */
    public Object newMessage();
    
    /**
     * Get message name for this schema
     * @return Message name string
     */
    public String messageName();
    
    /**
     * Get full message name for this schema
     * @return Full message name string
     */
    public String messageFullName();
    
    /**
     * Get type class for this schema
     * @return Class type
     */
    public Class<Object> typeClass();
}

Specialized Polymorphic Schema Classes

Concrete implementations for specific polymorphic scenarios.

/**
 * Polymorphic schema for array types
 */
public abstract class ArraySchema extends PolymorphicSchema {
    // Handles arrays of various types with type information
}

/**
 * Polymorphic schema for numeric wrapper types
 */
public abstract class NumberSchema extends PolymorphicSchema {
    // Handles Integer, Long, Double, Float, etc.
}

/**
 * Polymorphic schema for Class objects
 */
public abstract class ClassSchema extends PolymorphicSchema {
    // Handles Class<?> instances with type safety
}

/**
 * Polymorphic schema for enum types
 */
public abstract class PolymorphicEnumSchema extends PolymorphicSchema {
    // Handles enum values with type identification
}

/**
 * Polymorphic schema for collection types
 */
public abstract class PolymorphicCollectionSchema extends PolymorphicSchema {
    // Handles List, Set, Queue, and other collection interfaces
}

/**
 * Polymorphic schema for map types
 */
public abstract class PolymorphicMapSchema extends PolymorphicSchema {
    // Handles Map interfaces and implementations
}

/**
 * Polymorphic schema for POJO types
 */
public abstract class PolymorphicPojoSchema extends PolymorphicSchema {
    // Handles Plain Old Java Objects with inheritance
}

/**
 * Polymorphic schema for POJO collections
 */
public abstract class PolymorphicPojoCollectionSchema extends PolymorphicSchema {
    // Handles collections containing POJOs
}

/**
 * Polymorphic schema for POJO maps
 */
public abstract class PolymorphicPojoMapSchema extends PolymorphicSchema {
    // Handles maps containing POJOs
}

/**
 * Polymorphic schema for Throwable types
 */
public abstract class PolymorphicThrowableSchema extends PolymorphicSchema {
    // Handles exceptions and errors with inheritance
}

/**
 * Polymorphic schema for generic Object types
 */
public abstract class ObjectSchema extends PolymorphicSchema {
    // Handles generic Object references
}

DerivativeSchema

Special schema implementation for handling derived or wrapped types.

/**
 * Schema for derivative types that wrap or extend other types
 */
public abstract class DerivativeSchema implements Schema<Object> {
    
    /**
     * Get the base schema this derivative extends
     * @return Base schema instance
     */
    public abstract Schema<?> getBaseSchema();
    
    /**
     * Check if this schema can handle the specified type
     * @param typeClass Class to check
     * @return true if this schema can handle the type
     */
    public abstract boolean canHandle(Class<?> typeClass);
}

Usage Examples

Automatic Factory Selection

import io.protostuff.runtime.PolymorphicSchemaFactories;
import io.protostuff.runtime.DefaultIdStrategy;
import java.lang.reflect.Field;

// Automatic factory selection based on field
public class User {
    public List<String> tags;           // Collection field
    public Map<String, Object> data;    // Map field  
    public Animal pet;                  // POJO field with inheritance
    public Status status;               // Enum field
}

DefaultIdStrategy strategy = new DefaultIdStrategy();

// Get factories for different field types
Field tagsField = User.class.getField("tags");
PolymorphicSchema.Factory collectionFactory = 
    PolymorphicSchemaFactories.getFactoryFromField(tagsField, strategy);

Field dataField = User.class.getField("data");
PolymorphicSchema.Factory mapFactory = 
    PolymorphicSchemaFactories.getFactoryFromField(dataField, strategy);

Field petField = User.class.getField("pet");
PolymorphicSchema.Factory pojoFactory = 
    PolymorphicSchemaFactories.getFactoryFromField(petField, strategy);

Field statusField = User.class.getField("status");
PolymorphicSchema.Factory enumFactory = 
    PolymorphicSchemaFactories.getFactoryFromField(statusField, strategy);

Manual Factory Usage

// Direct factory usage for specific scenarios
DefaultIdStrategy strategy = new DefaultIdStrategy();

// Create schemas using specific factories
PolymorphicSchema arraySchema = PolymorphicSchemaFactories.ARRAY.create(String[].class, strategy);
PolymorphicSchema collectionSchema = PolymorphicSchemaFactories.COLLECTION.create(List.class, strategy);
PolymorphicSchema mapSchema = PolymorphicSchemaFactories.MAP.create(Map.class, strategy);
PolymorphicSchema pojoSchema = PolymorphicSchemaFactories.POJO.create(User.class, strategy);

// Use schemas for polymorphic serialization
// (requires protostuff-core for actual serialization)

Collection and Map Generic Type Handling

import java.util.*;

// Handle complex generic types
Class<List<User>> userListClass = (Class<List<User>>) (Class<?>) List.class;
PolymorphicSchema userListSchema = 
    PolymorphicSchemaFactories.getSchemaFromCollectionOrMapGenericType(userListClass, strategy);

Class<Map<String, List<User>>> complexMapClass = 
    (Class<Map<String, List<User>>>) (Class<?>) Map.class;
PolymorphicSchema complexMapSchema = 
    PolymorphicSchemaFactories.getSchemaFromCollectionOrMapGenericType(complexMapClass, strategy);

// Factory for repeated value types in collections
PolymorphicSchema.Factory repeatedFactory = 
    PolymorphicSchemaFactories.getFactoryFromRepeatedValueGenericType(User.class);

Inheritance Hierarchy Handling

// Define inheritance hierarchy
public abstract class Animal {
    public String name;
}

public class Dog extends Animal {
    public String breed;
}

public class Cat extends Animal {
    public boolean indoor;
}

// Register polymorphic types
DefaultIdStrategy strategy = new DefaultIdStrategy();
strategy.registerPojo(Animal.class);
strategy.registerPojo(Dog.class);
strategy.registerPojo(Cat.class);

// Map inheritance relationships
strategy.map(Animal.class, Dog.class);
strategy.map(Animal.class, Cat.class);

// Create polymorphic schema for the base class
PolymorphicSchema animalSchema = PolymorphicSchemaFactories.POJO.create(Animal.class, strategy);

// The schema can now handle Dog, Cat, or any other Animal subtype

Custom Polymorphic Schema Creation

/**
 * Custom polymorphic schema factory for special handling
 */
public class CustomPolymorphicFactory implements PolymorphicSchema.Factory {
    
    @Override
    public PolymorphicSchema create(Class<?> typeClass, IdStrategy strategy) {
        if (isSpecialType(typeClass)) {
            return new CustomPolymorphicSchema(typeClass, strategy);
        }
        // Delegate to appropriate default factory
        return PolymorphicSchemaFactories.POJO.create(typeClass, strategy);
    }
    
    private boolean isSpecialType(Class<?> typeClass) {
        // Custom logic to identify special types
        return typeClass.isAnnotationPresent(CustomSerialization.class);
    }
}

// Custom schema implementation
public class CustomPolymorphicSchema extends PolymorphicSchema {
    
    private final Class<?> typeClass;
    private final IdStrategy strategy;
    
    public CustomPolymorphicSchema(Class<?> typeClass, IdStrategy strategy) {
        this.typeClass = typeClass;
        this.strategy = strategy;
    }
    
    @Override
    public Object newMessage() {
        // Custom object creation logic
        return createCustomInstance(typeClass);
    }
    
    // Implement other required methods...
}

Factory Selection Logic

The getFactoryFromField method uses the following logic to select appropriate factories:

  1. Array Types: Returns ARRAY factory for array fields
  2. Collection Types: Returns COLLECTION for List, Set, Queue interfaces
  3. Map Types: Returns MAP for Map interfaces
  4. Enum Types: Returns ENUM for enum fields
  5. Number Types: Returns NUMBER for numeric wrapper types
  6. Class Types: Returns CLASS for Class<?> fields
  7. Throwable Types: Returns THROWABLE for exception fields
  8. POJO Types: Returns POJO for custom object types
  9. Object Types: Returns OBJECT for generic Object fields

Configuration with IdStrategy

Polymorphic schemas work closely with IdStrategy configuration:

// Configure strategy with polymorphic flags
int flags = IdStrategy.MORPH_COLLECTION_INTERFACES 
          | IdStrategy.MORPH_MAP_INTERFACES
          | IdStrategy.MORPH_NON_FINAL_POJOS
          | IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;

DefaultIdStrategy strategy = new DefaultIdStrategy(flags);

// Register types for polymorphic handling
strategy.registerPojo(BaseClass.class);
strategy.registerPojo(DerivedClass1.class);
strategy.registerPojo(DerivedClass2.class);

// Create polymorphic schemas with configured strategy
PolymorphicSchema schema = PolymorphicSchemaFactories.POJO.create(BaseClass.class, strategy);

Performance Considerations

  1. Factory Caching: Factories cache created schemas for performance
  2. Type Registration: Pre-register polymorphic types for better performance
  3. Strategy Configuration: Configure IdStrategy flags appropriately for your use case
  4. Generic Type Resolution: Complex generic types may have resolution overhead
  5. Inheritance Depth: Deep inheritance hierarchies may impact performance

Best Practices

  1. Type Registration: Register all polymorphic types upfront with IdStrategy
  2. Factory Selection: Use automatic factory selection when possible
  3. Generic Types: Be explicit about generic type parameters for better schema generation
  4. Strategy Configuration: Configure IdStrategy flags based on your polymorphic requirements
  5. Error Handling: Handle UnknownTypeException for unregistered polymorphic types
  6. Testing: Test polymorphic serialization with all expected type combinations

Install with Tessl CLI

npx tessl i tessl/maven-io-protostuff--protostuff-runtime

docs

annotations.md

custom-serialization.md

field-access.md

index.md

polymorphic-schemas.md

runtime-environment.md

schema-generation.md

type-strategy.md

tile.json