Skip to content

itcraft-cn/dyenums

Repository files navigation

dyenums - Dynamic Enum Library for Java

Java Maven License

dyenums is a dynamic enum library for Java 8+ that provides runtime-extensible enums. Unlike traditional Java enums that are fixed at compile time, dyenums allows you to register, modify, and load enum values at runtime.

Key Features

  • Runtime Registration: Register enum values dynamically at runtime
  • Configuration Loading: Load enums from properties files or databases (optional)
  • Custom Loaders: Implement DyEnumsLoader interface for any data source
  • Type-Safe Access: Full type safety with generics
  • Thread-Safe: Built with ConcurrentHashMap and proper synchronization
  • Minimal Core: Only SLF4J dependency required for core module
  • Spring Integration: Optional Spring/Boot support

Module Structure

dyenums
├── dyenums-core        # Core module (required) - minimal dependencies
├── dyenums-loader-file # File loader (optional) - properties file support
├── dyenums-loader-db   # Database loader (optional) - JDBC support
└── dyenums-spring      # Spring integration (optional) - auto-configuration
Use Case Required Modules
Manual registration only dyenums-core
Custom loader implementation dyenums-core
Load from properties files dyenums-core + dyenums-loader-file
Load from database dyenums-core + dyenums-loader-db
Spring/Boot integration dyenums-core + dyenums-spring

Installation

Maven

Core only (minimal dependencies):

<dependency>
    <groupId>cn.itcraft</groupId>
    <artifactId>dyenums-core</artifactId>
    <version>1.0.0</version>
</dependency>

With file loader:

<dependency>
    <groupId>cn.itcraft</groupId>
    <artifactId>dyenums-loader-file</artifactId>
    <version>1.0.0</version>
</dependency>

With database loader:

<dependency>
    <groupId>cn.itcraft</groupId>
    <artifactId>dyenums-loader-db</artifactId>
    <version>1.0.0</version>
</dependency>

With Spring integration:

<dependency>
    <groupId>cn.itcraft</groupId>
    <artifactId>dyenums-spring</artifactId>
    <version>1.0.0</version>
</dependency>

Build from Source

git clone https://github.com/itcraft-cn/dyenums.git
cd dyenums
mvn clean install

Quick Start

1. Define Your Enum Class

Extend BaseDyEnum:

import cn.itcraft.dyenums.core.BaseDyEnum;

public class UserStatus extends BaseDyEnum {
    
    public static final UserStatus ACTIVE = new UserStatus("ACTIVE", "Active", "User is active", 1);
    public static final UserStatus INACTIVE = new UserStatus("INACTIVE", "Inactive", "User is inactive", 2);
    public static final UserStatus LOCKED = new UserStatus("LOCKED", "Locked", "User is locked", 3);
    
    private UserStatus(String code, String name, String description, int order) {
        super(code, name, description, order);
    }
}

2. Register and Use

import cn.itcraft.dyenums.core.EnumRegistry;

public class Application {
    public static void main(String[] args) {
        // Register predefined values
        EnumRegistry.register(UserStatus.class, UserStatus.ACTIVE);
        EnumRegistry.register(UserStatus.class, UserStatus.INACTIVE);
        EnumRegistry.register(UserStatus.class, UserStatus.LOCKED);
        
        // Lookup by code
        UserStatus status = EnumRegistry.valueOf(UserStatus.class, "ACTIVE")
            .orElseThrow(() -> new IllegalArgumentException("Status not found"));
        
        System.out.println(status.getName()); // Output: Active
    }
}

Advanced Usage

Dynamic Registration

// Create and register at runtime
UserStatus customStatus = new UserStatus("CUSTOM", "Custom Status", "Custom status", 99);
EnumRegistry.register(UserStatus.class, customStatus);

// Or use EnumRegistry.addEnum with reflection
EnumRegistry.addEnum(UserStatus.class, "VIP", "VIP User", "VIP status", 100);

Custom Loader

Implement DyEnumsLoader interface to load enums from any source:

import cn.itcraft.dyenums.loader.DyEnumsLoader;
import cn.itcraft.dyenums.core.DyEnum;
import java.util.function.BiFunction;

public class MyCustomLoader<T extends DyEnum> implements DyEnumsLoader<T> {
    
    @Override
    public int load(Class<T> enumClass, BiFunction<String, String, T> factory) throws Exception {
        // Load from your data source (REST API, Redis, etc.)
        List<MyData> dataList = fetchFromMySource();
        
        int count = 0;
        for (MyData data : dataList) {
            String code = data.getCode();
            String valueString = data.getName() + "|" + data.getDesc() + "|" + data.getOrder();
            T enumValue = factory.apply(code, valueString);
            EnumRegistry.register(enumClass, enumValue);
            count++;
        }
        return count;
    }
    
    @Override
    public boolean validateSource() {
        return isMySourceAccessible();
    }
}

Multi-Language Support

Extend with language-aware messages:

import cn.itcraft.dyenums.core.BaseDyEnum;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;

public class ErrorCode extends BaseDyEnum {
    
    private final Map<String, String> messages;
    
    public ErrorCode(String code, String name, int order, Map<String, String> messages) {
        super(code, name, null, order);
        this.messages = messages;
    }
    
    public String getMessage(String lang) {
        return messages.getOrDefault(lang, getCode());
    }
    
    public String getMessage(Locale locale) {
        return getMessage(locale.getLanguage());
    }
    
    // Convenience methods
    public String getMessageZh() { return getMessage("zh"); }
    public String getMessageEn() { return getMessage("en"); }
}

// Usage
Map<String, String> messages = new HashMap<>();
messages.put("zh", "系统错误");
messages.put("en", "System error");
messages.put("pt", "Erro do sistema");
messages.put("ru", "Системная ошибка");

ErrorCode error = new ErrorCode("SYS_001", "System Error", 1, messages);
EnumRegistry.register(ErrorCode.class, error);

System.out.println(error.getMessageZh()); // 系统错误
System.out.println(error.getMessageEn()); // System error

Load from Properties File

Use dyenums-loader-file module:

# enums.properties
UserStatus.ACTIVE=ACTIVE|Active|User is active|1
UserStatus.INACTIVE=INACTIVE|Inactive|User is inactive|2
import cn.itcraft.dyenums.loader.file.FileBasedDyEnumsLoader;

FileBasedDyEnumsLoader<UserStatus> loader = new FileBasedDyEnumsLoader<>("enums.properties");
loader.load(UserStatus.class, UserStatus::fromValueString);

Load from Database

Use dyenums-loader-db module:

import cn.itcraft.dyenums.loader.db.DatabaseDyEnumsLoader;
import javax.sql.DataSource;

DatabaseDyEnumsLoader<UserStatus> loader = new DatabaseDyEnumsLoader<>(dataSource);
loader.load(UserStatus.class, UserStatus::fromValueString);

Spring Integration

Use dyenums-spring module:

import cn.itcraft.dyenums.spring.EnumService;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class UserService {
    
    @Autowired
    private EnumService enumService;
    
    public List<UserStatus> getAllStatuses() {
        return enumService.getValues(UserStatus.class);
    }
    
    public UserStatus getStatus(String code) {
        return enumService.getByCode(UserStatus.class, code);
    }
}

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Application Layer                       │
├─────────────────────────────────────────────────────────────┤
│  EnumRegistry (Core) - Registration, Lookup, Thread-Safety  │
├──────────────┬──────────────┬──────────────┬────────────────┤
│  BaseDyEnum  │ DyEnumsLoader│ @EnumDef     │ Spring Config  │
│  (Core)      │ (Core Interface)            │ (Optional)     │
├──────────────┴──────────────┴──────────────┴────────────────┤
│              Optional Loader Implementations                  │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐│
│  │ File Loader │ │  DB Loader  │ │  Custom Implementation  ││
│  │ (Optional)  │ │  (Optional) │ │  (Your Own)             ││
│  └─────────────┘ └─────────────┘ └─────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

Core Components

Component Module Description
DyEnum core Interface defining enum contract
BaseDyEnum core Abstract base implementation
EnumRegistry core Central registry for all enum instances
DyEnumsLoader core Interface for custom loaders
FileBasedDyEnumsLoader loader-file Properties file loader
PropDyEnumsLoader loader-file In-memory Properties loader
DatabaseDyEnumsLoader loader-db JDBC database loader
EnumService spring Spring service for enum access
EnumConverter spring Spring MVC type converter

Testing

# Run all tests
mvn test

# Run specific module tests
mvn test -pl dyenums-core
mvn test -pl dyenums-loader-file

# Run specific test class
mvn test -Dtest=EnumRegistryTest

Thread Safety

All registry operations are thread-safe:

// Safe for concurrent access
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
    final int id = i;
    executor.submit(() -> {
        EnumRegistry.addEnum(UserStatus.class, "STATUS_" + id, "Status " + id, null, id);
    });
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);

assertEquals(100, EnumRegistry.getCount(UserStatus.class));

Performance

  • O(1) Lookup: HashMap-based lookup by code
  • Concurrent Access: ConcurrentHashMap for thread-safe operations
  • Lazy Initialization: Enums created only when registered
  • Memory Efficient: Single shared registry instance

Best Practices

  1. Register enums during application startup
  2. Treat enum instances as immutable after creation
  3. Ensure codes are unique within each enum type
  4. Implement DyEnumsLoader for custom data sources
  5. Use EnumService in Spring applications

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'feat: add AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Support

  • Create an issue on GitHub
  • Check the doc directory for documentation
  • Review example implementations in dyenums-test module

About

a dynamic enum library for Java 8+ that provides runtime-extensible enums. Unlike traditional Java enums that are fixed at compile time, dyenums allows you to register, modify, and load enum values at runtime.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages