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

net.e6tech.elements.common.inject.Module Maven / Gradle / Ivy

There is a newer version: 2.7.9
Show newest version
/*
 * Copyright 2017 Futeh Kao
 *
 * 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 net.e6tech.elements.common.inject;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.reflect.TypeToken;
import net.e6tech.elements.common.resources.BindClass;
import net.e6tech.elements.common.resources.BindProperties;
import net.e6tech.elements.common.resources.Provision;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * Created by futeh.
 */
@SuppressWarnings({"squid:S1214", "unchecked"})
public interface Module {

    LoadingCache, String[]> bindProperties = CacheBuilder.newBuilder()
            .maximumSize(10000)
            .initialCapacity(100)
            .concurrencyLevel(Provision.cacheBuilderConcurrencyLevel)
            .expireAfterWrite(360 * 60 * 1000L,TimeUnit.MILLISECONDS)
            .build(new CacheLoader, String[]>() {
        public String[] load(Class cls)  {
            Objects.requireNonNull(cls);
            Class c = cls;
            Set set = new LinkedHashSet<>();
            while (c != null && !c.equals(Object.class)) {
                BindProperties annotation = c.getAnnotation(BindProperties.class);
                if (annotation != null) {
                    Collections.addAll(set, annotation.value());
                }
                c = c.getSuperclass();
            }
            return set.toArray(new String[set.size()]);
        }
    });

    @SuppressWarnings({"unchecked","squid:CommentedOutCodeLine"})
    LoadingCache, Type[]> bindTypes = CacheBuilder.newBuilder()
            .maximumSize(10000)
            .initialCapacity(100)
            .concurrencyLevel(Provision.cacheBuilderConcurrencyLevel)
            .expireAfterWrite(360 * 60 * 1000L, TimeUnit.MILLISECONDS)
            .build(new CacheLoader, Type[]>() {
        public Type[] load(Class cls) { return Module.load(cls);}
            });

    static Type[] load(Class cls)  {
        Objects.requireNonNull(cls);
        Class c = cls;
        Class prev = cls;
        List bindClasses = new LinkedList<>();
        Set list = new LinkedHashSet<>();
        list.add(cls);
        boolean found = false;
        // try to find BindClass annotation from class hierarchy
        while (c != null && !c.equals(Object.class)) {
            BindClass bind = c.getAnnotation(BindClass.class);
            if (bind != null) {
                if (bind.generics()) {
                    found = true;
                    list.add(prev.getGenericSuperclass());
                } else {
                    if (bind.value().length == 0) {
                        bindClasses.add(c);
                    } else {
                        for (Class bound : bind.value())
                            bindClasses.add(bound);
                    }
                }
                break;
            }
            prev = c;
            c = c.getSuperclass();
        }
        if (bindClasses.isEmpty())
            bindClasses.add(cls);

        if (!found) {
            for (Class bindClass : bindClasses) {
                if (bindClass.getGenericSuperclass() instanceof ParameterizedType
                        && bindClass.getTypeParameters().length == 0) {
                    // this is for anonymous class
                    // for example, new CacheFacade(KeyServer, "clientKeys") {}
                    list.add(bindClass.getGenericSuperclass());
                } else {
                    if (!bindClass.equals(cls))
                        list.add(bindClass);
                }
            }
        }

        // try to find using interfaces
        for (Class i : TypeToken.of(cls).getTypes().interfaces().rawTypes()) {
            BindClass bind = (BindClass) i.getAnnotation(BindClass.class);
            if (bind != null) {
                if (bind.value().length == 0)
                    list.add(i);
                else {
                    for (Class bound : bind.value())
                        list.add(bound);
                }
            }
        }

        list.removeIf(type -> type instanceof Class && ((Class) type).isSynthetic());
        return list.toArray(new Type[list.size()]);
    }

    default String[] getBindProperties(Class cls) {
        try {
            return bindProperties.get(cls);
        } catch (ExecutionException e) {
            return new String[0];
        }
    }

    default Type[] getBindTypes(Class cls) {
        try {
            return bindTypes.get(cls);
        } catch (ExecutionException e) {
            return new Type[0];
        }
    }

    ModuleFactory getFactory();

    void add(Module module);

    Map listBindings(Class cls);

    Map> listBindings();

    void bindClass(Class cls, Class service);

    Class getBoundClass(Class cls);

    Object bindInstance(Class cls, Object instance);

    Object rebindInstance(Class cls, Object instance);

    Object unbindInstance(Class cls);

    Object unbindNamedInstance(Class cls, String name);

     T getBoundInstance(Class cls);

    Object bindNamedInstance(Class cls, String name, Object instance);

    Object rebindNamedInstance(Class cls, String name, Object instance);

     T getBoundNamedInstance(Class cls, String name);

    Injector build(Module... components);

    Injector build(boolean strict, Module... components);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy