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

com.github.leeonky.jfactory.FactorySet Maven / Gradle / Ivy

There is a newer version: 0.7.2
Show newest version
package com.github.leeonky.jfactory;

import com.github.leeonky.util.BeanClass;
import com.github.leeonky.util.Classes;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;

class FactorySet {
    public final TypeSequence typeSequence = new TypeSequence();
    private final DefaultValueFactories defaultValueFactories = new DefaultValueFactories();
    private final Map, ObjectFactory> objectFactories = new HashMap<>();
    private final Map, SpecClassFactory> specClassFactoriesWithType = new HashMap<>();
    private final Map> specClassFactoriesWithName = new HashMap<>();

    @SuppressWarnings("unchecked")
    public  ObjectFactory queryObjectFactory(BeanClass type) {
        return (ObjectFactory) objectFactories.computeIfAbsent(type,
                key -> new ObjectFactory<>(key, this));
    }

    public > void registerSpecClassFactory(Class specClass) {
        Spec spec = Classes.newInstance(specClass);
        boolean globalSpec = isGlobalSpec(specClass);
        SpecClassFactory specClassFactory = specClassFactoriesWithType.computeIfAbsent(specClass,
                type -> new SpecClassFactory<>(specClass, this, globalSpec));
        specClassFactoriesWithName.put(spec.getName(), specClassFactory);
        if (globalSpec)
            registerGlobalSpec(specClassFactory);
        if (!specClass.getSuperclass().equals(Spec.class))
            registerSpecClassFactory((Class) specClass.getSuperclass());
    }

    private > boolean isGlobalSpec(Class specClass) {
        return specClass.getAnnotation(Global.class) != null;
    }

    private  void registerGlobalSpec(SpecClassFactory specClassFactory) {
        Class> specClass = specClassFactory.getSpecClass();
        if (specClassFactory.getBase() instanceof SpecClassFactory)
            throw new IllegalArgumentException(String.format("More than one @Global Spec class `%s` and `%s`",
                    ((SpecClassFactory) specClassFactory.getBase()).getSpecClass().getName(), specClass.getName()));
        if (!specClass.getSuperclass().equals(Spec.class))
            throw new IllegalArgumentException(String.format("Global Spec %s should not have super Spec %s.",
                    specClass.getName(), specClass.getSuperclass().getName()));
        objectFactories.put(specClassFactory.getType(), specClassFactory);
    }

    public void removeGlobalSpec(BeanClass type) {
        objectFactories.computeIfPresent(type, (key, factory) -> factory.getBase());
    }

    @SuppressWarnings("unchecked")
    public  SpecClassFactory querySpecClassFactory(String specName) {
        return (SpecClassFactory) specClassFactoriesWithName.computeIfAbsent(specName, key -> {
            throw new IllegalArgumentException("Spec `" + specName + "` not exist");
        });
    }

    @SuppressWarnings("unchecked")
    public  SpecClassFactory querySpecClassFactory(Class> specClass) {
        return (SpecClassFactory) specClassFactoriesWithType.computeIfAbsent(specClass, key -> {
            throw new IllegalArgumentException("Spec `" + specClass.getName() + "` not exist");
        });
    }

    public  Optional> queryDefaultValueBuilder(BeanClass type) {
        return defaultValueFactories.query(type.getType());
    }

    public  DefaultValueFactory getDefaultValueBuilder(BeanClass type) {
        return queryDefaultValueBuilder(type).orElseGet(() -> new DefaultValueFactories.DefaultTypeFactory<>(type));
    }

    public int nextSequence(Class type) {
        return typeSequence.generate(type);
    }

    public > SpecFactory createSpecFactory(Class specClass, Consumer trait) {
        return new SpecFactory<>(Classes.newInstance(specClass), this, trait);
    }

    public  void registerDefaultValueFactory(Class type, DefaultValueFactory factory) {
        defaultValueFactories.register(type, factory);
    }
}