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

com.github.aidensuen.mongo.spring.mongodao.ClassPathMongoDaoScanner Maven / Gradle / Ivy

There is a newer version: 1.1.2
Show newest version
package com.github.aidensuen.mongo.spring.mongodao;

import com.github.aidensuen.mongo.annotation.RegisterMongoDao;
import com.github.aidensuen.mongo.core.MongoDaoRepository;
import com.github.aidensuen.mongo.exception.MongoDaoException;
import com.github.aidensuen.mongo.session.Configuration;
import com.github.aidensuen.mongo.session.MongoSessionFactory;
import com.github.aidensuen.mongo.spring.MongoSessionTemplate;
import com.github.aidensuen.util.SpringBootBindUtil;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.env.Environment;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Properties;
import java.util.Set;

public class ClassPathMongoDaoScanner extends ClassPathBeanDefinitionScanner {

    private MongoSessionTemplate mongoSessionTemplate;

    private MongoSessionFactory mongoSessionFactory;

    private String mongoSessionFactoryBeanName;

    private String mongoSessionTemplateBeanName;

    private boolean addToConfig = true;

    private final String repositoryName = "mongoDaoRepository";

    private Class annotationClass;

    private Class markerInterface;

    private MongoDaoRepository mongoDaoRepository;

    private String mongoDaoRepositoryBeaName;

    private MongoDaoFactoryBean mongoDaoFactoryBean = new MongoDaoFactoryBean<>();

    private final String registerMongoDaoName = RegisterMongoDao.class.getName();

    public ClassPathMongoDaoScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
    }

    public void registerFilters() {
        boolean acceptAllInterfaces = true;

        // if specified, use the given com.github.aidensuen.spring.annotation and / or marker interface
        if (this.annotationClass != null) {
            addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
            acceptAllInterfaces = false;
        }

        // override AssignableTypeFilter to ignore matches on the actual marker interface
        if (this.markerInterface != null) {
            addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {
                @Override
                protected boolean matchClassName(String className) {
                    logger.info(className);
                    return false;
                }
            });
            acceptAllInterfaces = false;
        }

        if (acceptAllInterfaces) {
            // default include filter that accepts all classes
            addIncludeFilter(new TypeFilter() {
                @Override
                public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                    return true;
                }
            });
        }

        // exclude package-info.java
        addExcludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                String className = metadataReader.getClassMetadata().getClassName();
                if (className.endsWith("package-info")) {
                    return true;
                }
                return metadataReader.getAnnotationMetadata()
                        .hasAnnotation(registerMongoDaoName);
            }
        });
    }

    @Override
    public Set doScan(String... basePackages) {
        return doScan0(basePackages);
    }

    private Set doScan0(String... basePackages) {
        Set beanDefinitions = super.doScan(basePackages);
        if (beanDefinitions.isEmpty()) {
            logger.warn("No Mongo dao was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
        } else {
            processBeanDefinitions(beanDefinitions);
        }

        return beanDefinitions;
    }

    private void processBeanDefinitions(Set beanDefinitions) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
            definition = (GenericBeanDefinition) holder.getBeanDefinition();

            if (logger.isDebugEnabled()) {
                logger.debug("Creating MongoDaoFactoryBean with name '" + holder.getBeanName()
                        + "' and '" + definition.getBeanClassName() + "' mongoDaoInterface");
            }

            definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
            definition.setBeanClass(this.mongoDaoFactoryBean.getClass());

            //set generic dao
            if (StringUtils.hasText(this.mongoDaoRepositoryBeaName)) {
                definition.getPropertyValues().add(repositoryName, new RuntimeBeanReference(this.mongoDaoRepositoryBeaName));
            } else {
                if (this.mongoDaoRepository == null) {
                    this.mongoDaoRepository = new MongoDaoRepository();
                }
                definition.getPropertyValues().add(repositoryName, this.mongoDaoRepository);
            }

            definition.getPropertyValues().add("addToConfig", this.addToConfig);

            boolean explicitFactoryUsed = false;
            if (StringUtils.hasText(this.mongoSessionFactoryBeanName)) {
                definition.getPropertyValues().add("mongoSessionFactory", new RuntimeBeanReference(this.mongoSessionFactoryBeanName));
                explicitFactoryUsed = true;
            } else if (this.mongoSessionFactory != null) {
                definition.getPropertyValues().add("mongoSessionFactory", this.mongoSessionFactory);
                explicitFactoryUsed = true;
            }

            if (StringUtils.hasText(this.mongoSessionTemplateBeanName)) {
                if (explicitFactoryUsed) {
                    logger.warn("Cannot use both: mongoSessionTemplate and mongoSessionFactory together. mongoSessionFactory is ignored.");
                }
                definition.getPropertyValues().add("mongoSessionTemplate", new RuntimeBeanReference(this.mongoSessionTemplateBeanName));
                explicitFactoryUsed = true;
            } else if (this.mongoSessionTemplate != null) {
                if (explicitFactoryUsed) {
                    logger.warn("Cannot use both: mongoSessionTemplate and mongoSessionFactory together. mongoSessionFactory is ignored.");
                }
                definition.getPropertyValues().add("mongoSessionTemplate", this.mongoSessionTemplate);
                explicitFactoryUsed = true;
            }


            if (!explicitFactoryUsed) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Enabling autowire by type for MongoDaoFactoryBean with name '" + holder.getBeanName() + "'.");
                }
                definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            }
        }
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    @Override
    protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) {
        if (super.checkCandidate(beanName, beanDefinition)) {
            return true;
        } else {
            logger.warn("Skipping MongoDaoFactoryBean with name '" + beanName
                    + "' and '" + beanDefinition.getBeanClassName() + "' mongoDaoInterface"
                    + ". Bean already defined with the same name!");
            return false;
        }
    }


    public Class getAnnotationClass() {
        return annotationClass;
    }

    public void setAnnotationClass(Class annotationClass) {
        this.annotationClass = annotationClass;
    }

    public Class getMarkerInterface() {
        return markerInterface;
    }

    public void setMarkerInterface(Class markerInterface) {
        this.markerInterface = markerInterface;
    }

    public void setMongoDaoRepository(MongoDaoRepository mongoDaoRepository) {
        this.mongoDaoRepository = mongoDaoRepository;
    }

    public void setAddToConfig(boolean addToConfig) {
        this.addToConfig = addToConfig;
    }

    public String getRepositoryName() {
        return repositoryName;
    }

    public void setMongoDaoFactoryBean(MongoDaoFactoryBean mongoDaoFactoryBean) {
        this.mongoDaoFactoryBean = mongoDaoFactoryBean != null ? mongoDaoFactoryBean : new MongoDaoFactoryBean();
    }

    public void setMongoDaoProperties(String[] properties) {
        if (mongoDaoRepository == null) {
            mongoDaoRepository = new MongoDaoRepository();
        }

        Properties props = new Properties();
        for (String property : properties) {
            property = property.trim();
            int index = property.indexOf("=");
            if (index < 0) {
                throw new MongoDaoException("incorrect format in properties"
                );
            }
            props.put(property.substring(0, index).trim(), property.substring(index + 1).trim());
        }
        mongoDaoRepository.setProperties(props);
    }

    public void setMongoDaoProperties(Environment environment) {
        if (mongoDaoRepository == null) {
            mongoDaoRepository = new MongoDaoRepository();
        }
        Properties p = SpringBootBindUtil.bind(environment, Properties.class, Configuration.PREFIX);
        mongoDaoRepository.setProperties(p);
    }

    public void setMongoDaoRepositoryBeaName(String mongoDaoRepositoryBeaName) {
        this.mongoDaoRepositoryBeaName = mongoDaoRepositoryBeaName;
    }

    public void setMongoSessionFactory(MongoSessionFactory mongoSessionFactory) {
        this.mongoSessionFactory = mongoSessionFactory;
    }

    public void setMongoSessionFactoryBeanName(String mongoSessionFactoryBeanName) {
        this.mongoSessionFactoryBeanName = mongoSessionFactoryBeanName;
    }

    public void setMongoSessionTemplate(MongoSessionTemplate mongoSessionTemplate) {
        this.mongoSessionTemplate = mongoSessionTemplate;
    }

    public void setMongoSessionTemplateBeanName(String mongoSessionTemplateBeanName) {
        this.mongoSessionTemplateBeanName = mongoSessionTemplateBeanName;
    }
}