EnumRegistryConfiguration.java

package com.tdmconsult.ete.configuration;

import com.google.common.collect.ImmutableList;
import com.tdmconsult.ete.utils.ApiEnum;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EnumRegistryConfiguration {

    public record EnumRegistry(ImmutableList<EnumDefinition> enums) {}

    public record EnumDefinition(String enumName, ImmutableList<EnumValue> values) {}

    public record EnumValue(String name, String displayName) {
        public static EnumValue of(final ApiEnum e) {
            return new EnumValue(e.name(), e.getDisplayName());
        }
    }

    @Bean
    public EnumRegistry apiEnumRegistry() {
        final ImmutableList.Builder<EnumDefinition> enumDefinitions = ImmutableList.builder();

        try (ScanResult scanResult = new ClassGraph()
                .acceptPackages("com.tdmconsult")
                .scan()) {

            final var classes = scanResult
                    .getClassesImplementing(ApiEnum.class.getName())
                    .loadClasses();

            classes.stream().filter(Class::isEnum).forEach(clazz -> {
                final var enumValues = Arrays.stream((ApiEnum[]) clazz.getEnumConstants())
                        .map(constant -> new EnumValue(constant.name(), constant.getDisplayName()))
                        .collect(ImmutableList.toImmutableList());

                enumDefinitions.add(new EnumDefinition(resolveEnumApiName(clazz), enumValues));
            });
        }

        return new EnumRegistry(enumDefinitions.build());
    }

    private String resolveEnumApiName(final Class<?> clazz) {
        if (clazz.isMemberClass() && clazz.getEnclosingClass() != null) {
            return resolveEnumApiName(clazz.getEnclosingClass()) + "$" + clazz.getSimpleName();
        }
        return clazz.getSimpleName();
    }
}