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

net.sf.andromedaioc.model.builder.packscan.PackageScannerBeansProvider Maven / Gradle / Ivy

The newest version!
package net.sf.andromedaioc.model.builder.packscan;

import net.sf.andromedaioc.annotation.Bean;
import net.sf.andromedaioc.annotation.Inject;
import net.sf.andromedaioc.annotation.Property;
import net.sf.andromedaioc.annotation.Resource;
import net.sf.andromedaioc.exception.PackageScanException;
import net.sf.andromedaioc.model.provider.Provider;
import net.sf.andromedaioc.resource.ResourceProvider;
import dalvik.system.DexFile;
import net.sf.andromedaioc.model.beans.*;
import net.sf.andromedaioc.util.BeanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class PackageScannerBeansProvider implements Provider> {

    private final List packagesToScan;
    private final ResourceProvider resourceProvider;
    private final Provider generatedBeanIdProvider;

    public PackageScannerBeansProvider(List packagesToScan, ResourceProvider resourceProvider, Provider generatedBeanIdProvider) {
        this.packagesToScan = packagesToScan;
        this.resourceProvider = resourceProvider;
        this.generatedBeanIdProvider = generatedBeanIdProvider;
    }

    public Map provide() {

        if(packagesToScan == null || packagesToScan.isEmpty()) {
            return Collections.emptyMap();
        }
        try {
            Map beans = new HashMap();
            DexFile dexFile = new DexFile(resourceProvider.getContext().getPackageCodePath());
            for (Enumeration iterator = dexFile.entries(); iterator.hasMoreElements();) {
                String candidate = iterator.nextElement();
                if(isInScanPackages(candidate)) {
                    Class candidateClass = Class.forName(candidate);
                    if(candidateClass.isAnnotationPresent(Bean.class)) {
                        BeanModel beanModel = getBeanModelFromClass(candidateClass);
                        beans.put(beanModel.getKey(), beanModel);
                    }
                }
            }
            return beans;
        } catch(Exception e) {
            throw new PackageScanException("Failed load beans from classpath. Reason: " + e.getMessage(), e);
        }
    }

    private BeanModel getBeanModelFromClass(Class beanClass) {
        Bean bean = beanClass.getAnnotation(Bean.class);
        BeanModel beanModel = new BeanModel();
        beanModel.setBeanClass(beanClass);
        beanModel.setBeanSource(BeanSource.CLASSPATH);
        if(bean.id().length() > 0) {
            beanModel.setKey(ReferenceKey.newPlainReferenceKey(bean.id()));
        } else {
            beanModel.setKey(ReferenceKey.newUndefinedReferenceKey(generatedBeanIdProvider.provide()));
        }
        beanModel.setScope(bean.scope());
        for(Field field : beanClass.getDeclaredFields()) {
            if(field.isAnnotationPresent(Inject.class)) {
                beanModel.addProperty(getPropertyFromField(field, field.getAnnotation(Inject.class)));
            } else if(field.isAnnotationPresent(Resource.class)) {
                beanModel.addProperty(getPropertyFromField(field, field.getAnnotation(Resource.class)));
            } else if(field.isAnnotationPresent(Property.class)) {
                beanModel.addProperty(getPropertyFromField(field, field.getAnnotation(Property.class)));
            }
        }

        Map setters = BeanUtils.getSetters(beanClass);
        for(Map.Entry entry : setters.entrySet()) {
            Method setter = entry.getValue();
            if(setter.isAnnotationPresent(Inject.class)) {
                beanModel.addProperty(getPropertyFromSetter(setter, entry.getKey(), setter.getAnnotation(Inject.class)));
            } else if(setter.isAnnotationPresent(Resource.class)) {
                beanModel.addProperty(getPropertyFromSetter(setter, entry.getKey(), setter.getAnnotation(Resource.class)));
            } else if(setter.isAnnotationPresent(Property.class)) {
                beanModel.addProperty(getPropertyFromSetter(setter, entry.getKey(), setter.getAnnotation(Property.class)));
            }
        }

        return beanModel;
    }

    private PropertyModel getPropertyFromField(Field field, Inject inject) {
        final ValueModel valueModel;
        if(inject.id() != null && inject.id().length() > 0) {
            valueModel = ValueModel.getBuilder().withReference(ReferenceKey.newPlainReferenceKey(inject.id())).build();
        } else {
            valueModel = ValueModel.getBuilder().withReference(ReferenceKey.BY_TYPE).withValueType(field.getType()).build();
        }
        PropertyModel propertyModel = PropertyModel.getBuilder()
                .withName(field.getName())
                .withAccessType(PropertyAccessType.FIELD)
                .withValue(valueModel)
                .build();
        return propertyModel;
    }

    private PropertyModel getPropertyFromField(Field field, Resource resource) {
        ValueModel valueModel = ValueModel.getBuilder().withResource(String.valueOf(resource.id())).build();
        PropertyModel propertyModel = PropertyModel.getBuilder()
                .withName(field.getName())
                .withAccessType(PropertyAccessType.FIELD)
                .withValue(valueModel)
                .build();
        return propertyModel;
    }

    private PropertyModel getPropertyFromField(Field field, Property property) {
        ValueModel valueModel = ValueModel.getBuilder().withProperty(property.name()).build();
        PropertyModel propertyModel = PropertyModel.getBuilder()
                .withName(field.getName())
                .withAccessType(PropertyAccessType.FIELD)
                .withValue(valueModel)
                .build();
        return propertyModel;
    }

    private PropertyModel getPropertyFromSetter(Method setter, String propertyName, Inject inject) {
        final ValueModel valueModel;
        if(inject.id() != null && inject.id().length() > 0) {
            valueModel = ValueModel.getBuilder().withReference(ReferenceKey.newPlainReferenceKey(inject.id())).build();
        } else {
            valueModel = ValueModel.getBuilder().withReference(ReferenceKey.BY_TYPE).withValueType(setter.getParameterTypes()[0]).build();
        }
        PropertyModel propertyModel = PropertyModel.getBuilder()
                .withName(propertyName)
                .withAccessType(PropertyAccessType.PROPERTY)
                .withValue(valueModel)
                .build();
        return propertyModel;
    }

    private PropertyModel getPropertyFromSetter(Method setter, String propertyName, Resource resource) {
        ValueModel valueModel = ValueModel.getBuilder().withResource(String.valueOf(resource.id())).build();
        PropertyModel propertyModel = PropertyModel.getBuilder()
                .withName(propertyName)
                .withAccessType(PropertyAccessType.PROPERTY)
                .withValue(valueModel)
                .build();
        return propertyModel;
    }

    private PropertyModel getPropertyFromSetter(Method setter, String propertyName, Property property) {
        ValueModel valueModel = ValueModel.getBuilder().withProperty(property.name()).build();
        PropertyModel propertyModel = PropertyModel.getBuilder()
                .withName(propertyName)
                .withAccessType(PropertyAccessType.PROPERTY)
                .withValue(valueModel)
                .build();
        return propertyModel;
    }

    private boolean isInScanPackages(String candidate) {
        if(candidate == null) {
            return false;
        }
        for(String scanPackage : packagesToScan) {
            if(candidate.startsWith(scanPackage)) {
                return true;
            }
        }
        return false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy