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

com.wizzardo.http.framework.di.DependencyFactory Maven / Gradle / Ivy

package com.wizzardo.http.framework.di;

import com.wizzardo.tools.cache.Cache;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: moxa
 * Date: 7/22/13
 */
public class DependencyFactory {

    private List classes;
    private final Map mappingByClass = new ConcurrentHashMap<>();
    private final Map mappingByName = new ConcurrentHashMap<>();

    private Cache dependencies = new Cache<>("dependencies", 0, clazz -> {
        Injectable injectable = getAnnotation(clazz, Injectable.class);
        Class mappedClass = mappingByClass.get(clazz);
        boolean mapped = mappedClass != null && clazz != mappedClass;

        if (injectable != null && !isAbstract(clazz) && !mapped)
            return getForge(injectable).forge(clazz, injectable.scope());

        Class implementation = findImplementation(clazz);
        if (implementation != null) {
            if (injectable == null)
                injectable = getAnnotation(implementation, Injectable.class);

            if (injectable != null)
                return getForge(injectable).forge(implementation, injectable.scope());
        }

        if (injectable != null) {
            Dependency dependency = getForge(injectable).forge(clazz, injectable.scope());
            if (dependency != null) {
                return dependency;
            }
        }

        throw new IllegalStateException("can't create dependency-holder for class: " + clazz);
    });

    protected Class findImplementation(Class interfase) {
        Class implementation = mappingByClass.get(interfase);
        if (implementation != null)
            return implementation;

        for (Class cl : classes) {
            if (interfase.isAssignableFrom(cl) && !isAbstract(cl)) {
                if (implementation != null) {
                    throw new IllegalStateException("can't resolve dependency '" + interfase + "'. Found more than one implementation: " + implementation + " and " + cl);
                }
                implementation = cl;
            }
        }
        return implementation;
    }

    protected boolean isAbstract(Class clazz) {
        int modifiers = clazz.getModifiers();
        return Modifier.isInterface(modifiers) && Modifier.isAbstract(modifiers);
    }

    static  boolean hasAnnotation(Class clazz, Class annotation) {
        return getAnnotation(clazz, annotation) != null;
    }

    static  A getAnnotation(Class clazz, Class annotation) {
        while (clazz != null) {
            A a = clazz.getAnnotation(annotation);
            if (a != null) {
                return a;
            }
            for (Class implemented : clazz.getInterfaces()) {
                a = getAnnotation(implemented, annotation);
                if (a != null)
                    return a;
            }
            clazz = clazz.getSuperclass();
        }
        return null;
    }

    protected DependencyForge getForge(Injectable injectable) {
        Class forge = injectable.forge();
        if (!DependencyForge.class.equals(forge))
            return resolve(forge);
        else
            return injectable.scope();
    }

    public void clear() {
        dependencies.clear();
    }

    private static class DependencyFactoryHolder {
        private static final DependencyFactory instance = new DependencyFactory();
    }

    public static  T get(Field field) {
        Dependency dependency = DependencyFactoryHolder.instance.mappingByName.get(field.getName());
        if (dependency != null)
            return dependency.get();

        return DependencyFactoryHolder.instance.resolve((Class) field.getType());
    }

    public static  T get(Class clazz) {
        return DependencyFactoryHolder.instance.resolve(clazz);
    }

    public static DependencyFactory get() {
        return DependencyFactoryHolder.instance;
    }

    @SuppressWarnings("unchecked")
    private  T resolve(Class clazz) {
        return (T) dependencies.get(clazz).get();
    }

    public void setClasses(List classes) {
        this.classes = classes;
    }

    public void register(Class abstractClass, Class implementation) {
        mappingByClass.put(abstractClass, implementation);
        dependencies.get(abstractClass);
    }

    public  void register(Class clazz, Dependency dependency) {
        dependencies.put(clazz, dependency);
    }

    public  void register(String name, Dependency dependency) {
        mappingByName.put(name, dependency);
    }

    public  void register(Class clazz, T dependency) {
        dependencies.put(clazz, new SingletonDependency<>(dependency));
    }

    public  void register(String name, T dependency) {
        mappingByName.put(name, new SingletonDependency<>(dependency));
    }

    public boolean contains(Class clazz) {
        return dependencies.contains(clazz);
    }

    public boolean contains(String clazz) {
        return mappingByName.containsKey(clazz);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy