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

com.mysema.query.codegen.AbstractModule Maven / Gradle / Ivy

There is a newer version: 3.7.4
Show newest version
/*
 * Copyright 2011, Mysema Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mysema.query.codegen;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

/**
 * AbstractModule provides a base class for annotation based dependency injection
 *
 * @author tiwe
 *
 */
public abstract class AbstractModule {

    private final Map, Object> instances = new HashMap, Object>();

    private final Map, Class> bindings = new HashMap, Class>();

    private final Map namedInstances = new HashMap();

    private final Map> namedBindings = new HashMap>();

    public AbstractModule() {
        configure();
    }

    public final  AbstractModule bind(Class clazz) {
        if (clazz.isInterface()) {
            throw new IllegalArgumentException("Interfaces can't be instantiated");
        }
        bind(clazz, clazz);
        return this;
    }

    public final  AbstractModule bind(String name, Class implementation) {
        namedBindings.put(name, implementation);
        return this;
    }

    public final  AbstractModule bind(String name, T implementation) {
        namedInstances.put(name, implementation);
        return this;
    }

    public final  AbstractModule bindInstance(String name, Class implementation) {
        namedInstances.put(name, implementation);
        return this;
    }

    public final  AbstractModule bind(Class iface, Class implementation) {
        bindings.put(iface, implementation);
        return this;
    }

    public final  AbstractModule bind(Class iface, T implementation) {
        instances.put(iface, implementation);
        return this;
    }

    protected abstract void configure();

    @SuppressWarnings("unchecked")
    public final  T get(Class iface) {
        if (instances.containsKey(iface)) {
            return (T)instances.get(iface);
        } else if (bindings.containsKey(iface)) {
            Class implementation = bindings.get(iface);
            T instance = (T)createInstance(implementation);
            instances.put(iface, instance);
            return instance;
        } else {
            throw new IllegalArgumentException(iface.getName() + " is not registered");
        }
    }

    @SuppressWarnings("unchecked")
    public final  T get(Class iface, String name) {
        if (namedInstances.containsKey(name)) {
            return (T)namedInstances.get(name);
        } else if (namedBindings.containsKey(name)) {
            Class implementation = namedBindings.get(name);
            if (implementation != null) {
                T instance = (T)createInstance(implementation);
                namedInstances.put(name, instance);
                return instance;
            } else {
                return null;
            }
        } else {
            throw new IllegalArgumentException(iface.getName() + " " + name + " is not registered");
        }
    }

    @SuppressWarnings("unchecked")
    private  T createInstance(Class implementation) {
        Constructor constructor = null;
        for (Constructor c : implementation.getConstructors()) {
            if (c.getAnnotation(Inject.class) != null) {
                constructor = c;
                break;
            }
        }

        // fallback to default constructor
        if (constructor == null) {
            try {
                constructor = implementation.getConstructor();
            } catch (SecurityException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }

        if (constructor != null) {
            Object[] args = new Object[constructor.getParameterTypes().length];
            for (int i = 0; i < constructor.getParameterTypes().length; i++) {
                Named named = getNamedAnnotation(constructor.getParameterAnnotations()[i]);
                if (named != null) {
                    args[i] = get(constructor.getParameterTypes()[i], named.value());
                } else {
                    args[i] = get(constructor.getParameterTypes()[i]);
                }
            }
            try {
                return (T) constructor.newInstance(args);
                // TODO : populate fields as well?!?
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }

        } else {
            throw new IllegalArgumentException("Got no annotated constructor for " + implementation.getName());
        }

    }

    private Named getNamedAnnotation(Annotation[] annotations) {
        for (Annotation annotation : annotations) {
            if (annotation.annotationType().equals(Named.class)) {
                return (Named)annotation;
            }
        }
        return null;
    }



}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy