All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.scaff.crud.annotation.FastOrmRepositoryRegistrar Maven / Gradle / Ivy

The newest version!
package org.zodiac.scaff.crud.annotation;

import org.zodiac.commons.util.Annotations;
import org.zodiac.fastorm.rdb.mapping.defaults.DefaultReactiveRepository;
import org.zodiac.fastorm.rdb.mapping.defaults.DefaultSyncRepository;
import org.zodiac.scaff.api.crud.entity.GenericEntity;
import org.zodiac.scaff.api.crud.entity.ImplementFor;
import org.zodiac.scaff.crud.AutoDDLProcessor;
import org.zodiac.scaff.crud.EntityInfo;
import org.zodiac.scaff.crud.ReactiveRepositoryFactoryBean;
import org.zodiac.scaff.crud.SyncRepositoryFactoryBean;
import org.zodiac.sdk.toolkit.util.ClassUtil;
import org.zodiac.sdk.toolkit.util.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FastOrmRepositoryRegistrar implements ImportBeanDefinitionRegistrar {

    static AtomicInteger count = new AtomicInteger();

    protected final Logger log = LoggerFactory.getLogger(getClass());

    private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

    private final MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();

    public FastOrmRepositoryRegistrar() {
        super();
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        try {
            Map attr = importingClassMetadata.getAnnotationAttributes(EnableFastOrmRepository.class.getName());
            if (attr == null) {
                return;
            }
            boolean reactiveEnabled = Boolean.TRUE.equals(attr.get("reactive"));
            boolean nonReactiveEnabled = Boolean.TRUE.equals(attr.get("nonReactive"));

            String[] arr = (String[]) attr.get("value");
            Set resources = Arrays.stream(arr)
                    .flatMap(this::doGetResources)
                    .collect(Collectors.toSet());

            Class[] anno = (Class[]) attr.get("annotation");

            Set entityInfos = new HashSet<>();

            for (Resource resource : resources) {
                MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
                String className = reader.getClassMetadata().getClassName();
                Class entityType = ClassUtils.forName(className, null);
                if (Arrays.stream(anno)
                          .noneMatch(ann -> Annotations.findAnnotation(entityType, ann) != null)) {
                    continue;
                }

                ImplementFor implementFor = Annotations.findAnnotation(entityType, ImplementFor.class);
                Reactive reactive = Annotations.findAnnotation(entityType, Reactive.class);
                Class genericType = Optional
                        .ofNullable(implementFor)
                        .map(ImplementFor::value)
                        .orElseGet(() -> {
                            return Stream
                                    .of(entityType.getInterfaces())
                                    .filter(e -> GenericEntity.class.isAssignableFrom(e))
                                    .findFirst()
                                    .orElse(entityType);
                        });

                Class idType = null;
                if (implementFor == null || implementFor.idType() == Void.class) {
                    try {
                        if (GenericEntity.class.isAssignableFrom(entityType)) {
                            idType = ClassUtil.getGenericType(entityType);
                        }
                        if (idType == null) {
                            Method getId = ClassUtils.getMethod(entityType, "getId");
                            idType = getId.getReturnType();
                        }
                    } catch (Exception e) {
                        idType = String.class;
                    }
                } else {
                    idType = implementFor.idType();
                }

                EntityInfo entityInfo = new EntityInfo(genericType,
                                                       entityType,
                                                       idType,
                                                       reactiveEnabled,
                                                       nonReactiveEnabled);
                if (!entityInfos.contains(entityInfo) || implementFor != null) {
                    entityInfos.add(entityInfo);
                }

            }
            for (EntityInfo entityInfo : entityInfos) {
                Class entityType = entityInfo.getEntityType();
                Class idType = entityInfo.getIdType();
                Class realType = entityInfo.getRealType();
                if (entityInfo.isReactive()) {
                    log.trace("register ReactiveRepository<{},{}>", entityType.getName(), idType.getSimpleName());

                    ResolvableType repositoryType = ResolvableType.forClassWithGenerics(DefaultReactiveRepository.class, entityType, idType);

                    RootBeanDefinition definition = new RootBeanDefinition();
                    definition.setTargetType(repositoryType);
                    definition.setBeanClass(ReactiveRepositoryFactoryBean.class);
                    definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
                    definition.getPropertyValues().add("entityType", realType);
                    registry.registerBeanDefinition(realType.getSimpleName().concat("ReactiveRepository"), definition);
                }
                if (entityInfo.isNonReactive()) {
                    log.trace("register SyncRepository<{},{}>", entityType.getName(), idType.getSimpleName());
                    ResolvableType repositoryType = ResolvableType.forClassWithGenerics(DefaultSyncRepository.class, entityType, idType);
                    RootBeanDefinition definition = new RootBeanDefinition();
                    definition.setTargetType(repositoryType);
                    definition.setBeanClass(SyncRepositoryFactoryBean.class);
                    definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
                    definition.getPropertyValues().add("entityType", realType);
                    registry.registerBeanDefinition(realType.getSimpleName().concat("SyncRepository"), definition);
                }
            }

            Map> group = entityInfos.stream()
                    .collect(Collectors.groupingBy(EntityInfo::isReactive, Collectors.toSet()));

            for (Map.Entry> entry : group.entrySet()) {
                RootBeanDefinition definition = new RootBeanDefinition();
                definition.setTargetType(AutoDDLProcessor.class);
                definition.setBeanClass(AutoDDLProcessor.class);
                definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
                definition.getPropertyValues().add("entities", entityInfos);
                definition.getPropertyValues().add("reactive", entry.getKey());
                definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
                definition.setSynthetic(true);
                registry.registerBeanDefinition(AutoDDLProcessor.class.getName() + "_" + count.incrementAndGet(), definition);
            }

//        try {
//            BeanDefinition definition = registry.getBeanDefinition(AutoDDLProcessor.class.getName());
//            Set infos = (Set) definition.getPropertyValues().get("entities");
//            infos.addAll(entityInfos);
//        } catch (NoSuchBeanDefinitionException e) {
//
//        }
        } catch (Exception e) {
            ExceptionUtil.chuck(e);
        }
    }

    private Stream doGetResources(String packageStr) {
        Stream result = null;
        try {
            String path = ResourcePatternResolver
                .CLASSPATH_ALL_URL_PREFIX
                .concat(packageStr.replace(".", "/")).concat("/**/*.class");
            result = Arrays.stream(resourcePatternResolver.getResources(path));
        } catch (Exception e) {
            ExceptionUtil.chuck(e);
        }
        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy