Skip to content

1.2.0

Choose a tag to compare

@Traqueur-dev Traqueur-dev released this 20 Oct 07:31
· 16 commits to main since this release
807b3e7

🔧 Structura v1.2.0 – Custom Reader System

Extensible type conversion system for external libraries and custom types.

✨ New Features

  • Custom Reader System: Register custom converters for types not natively supported by Structura
  • Reader<T> interface: Simple functional interface for String → T conversion
  • CustomReaderRegistry: Thread-safe singleton registry for managing custom readers
  • Automatic conversion: Registered readers are automatically used during YAML parsing
  • Priority conversion: Custom readers are checked before standard type conversion

🎯 Key Components

// Register a custom reader for Adventure API Component
CustomReaderRegistry.getInstance().register(
    Component.class,
    str -> MiniMessage.miniMessage().deserialize(str)
);

// Use in configuration records
public record MessageConfig(
    Component welcomeMessage,  // Automatically converted
    Component errorMessage
) implements Loadable {}

// Parse YAML with automatic conversion
String yaml = """
    welcome-message: "<green>Welcome!</green>"
    error-message: "<red>Error!</red>"
    """;
MessageConfig config = Structura.parse(yaml, MessageConfig.class);

🔧 API

CustomReaderRegistry methods:

  • register(Class<T> targetClass, Reader<T> reader) - Register a custom reader
  • unregister(Class<?> targetClass) - Remove a registered reader
  • hasReader(Class<?> targetClass) - Check if a reader exists
  • convert(Object value, Class<T> targetClass) - Convert a value using registered reader
  • clear() - Remove all readers (useful for testing)
  • size() - Get count of registered readers

📦 New Classes

  • fr.traqueur.structura.readers.Reader<T> - Functional interface for custom conversion
  • fr.traqueur.structura.registries.CustomReaderRegistry - Registry for managing readers

🔄 Integration

  • ValueConverter enhancement: Custom readers are checked first in the conversion pipeline
  • Type safety: Uses Class.cast() for runtime type verification
  • String-only: Readers only work with String YAML values (use records/polymorphic for complex objects)
  • Thread-safe: ConcurrentHashMap-based storage for concurrent access

🎮 Use Cases

  • Adventure API Components: Convert MiniMessage strings to Component objects
  • Custom Color types: Parse color strings into custom Color classes
  • External libraries: Integrate any library requiring custom String parsing
  • Domain-specific types: Convert formatted strings to business objects

🧪 Testing

  • Complete test suite: 30+ unit tests covering all registry operations
  • Integration tests: End-to-end scenarios with mock Adventure API
  • Thread safety tests: Concurrent registration validation
  • Error handling tests: Comprehensive exception scenario coverage

📋 Migration Guide

No breaking changes - this is a purely additive feature. Existing code continues to work unchanged.

New users can immediately:

  1. Register readers at application startup
  2. Use custom types in configuration records
  3. Parse YAML with automatic conversion

⚙️ Technical Details

  • Conversion priority: Custom readers → Polymorphic types → Standard types
  • Exception handling: Reader failures wrapped in StructuraException
  • Type checking: Runtime verification via Class.cast()
  • Storage: ConcurrentHashMap<Class<?>, Reader<?>> for thread-safe access

🔗 Related Features

  • Works alongside PolymorphicRegistry for complex object hierarchies
  • Complements default value annotations for optional fields
  • Integrates with validation system for converted values

Full Changelog: 1.1.1...1.2.0