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

com.github.bingoohuang.utils.conf.ConfFactory Maven / Gradle / Ivy

package com.github.bingoohuang.utils.conf;

import com.github.bingoohuang.utils.file.Pathx;
import com.github.bingoohuang.utils.lang.Classpath;
import com.github.bingoohuang.utils.lang.Str;
import com.google.common.primitives.Primitives;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.n3r.diamond.client.Miner;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;

import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE;

@Slf4j
public class ConfFactory {
    @SuppressWarnings("unchecked")
    public static  T create(Class confInterface) {
        val cl = ConfFactory.class.getClassLoader();
        return (T) Proxy.newProxyInstance(cl, new Class[]{confInterface}, (proxy, method, args) -> {
            val props = createProperties(method);
            String value = parseValue(method, props);
            value = parseDefaultValue(method, value);

            return convertType(value, method);
        });
    }

    private static String parseDefaultValue(Method method, String value) {
        if (StringUtils.isNotEmpty(value)) return value;

        val defaultValue = method.getAnnotation(Conf.DefaultValue.class);
        if (defaultValue != null) return defaultValue.value();

        return value;
    }

    private static String parseValue(Method method, Properties props) {
        val confKey = method.getAnnotation(Conf.Key.class);
        if (confKey != null) return props.getProperty(confKey.value());

        val value = props.getProperty(method.getName());
        if (StringUtils.isNotEmpty(value)) return value;

        val name = LOWER_CAMEL.to(LOWER_UNDERSCORE, method.getName()).replace('_', '.');
        return props.getProperty(name);
    }

    @SneakyThrows
    private static Properties createProperties(Method method) {
        val source = method.getDeclaringClass().getAnnotation(Conf.Source.class);
        if (source == null) return dealDefaultProperties(method);

        val props = new Properties();
        for (val src : source.value()) {
            if (src.startsWith("diamond:")) {
                val axis = src.substring("diamond:".length());
                val group = StringUtils.substringBefore(axis, "^");
                val dataId = StringUtils.substringAfter(axis, "^");
                props.putAll(new Miner().getProperties(group, dataId));
            } else if (src.startsWith("classpath:")) {
                val cp = src.substring("classpath:".length());
                props.putAll(Classpath.loadProperties(cp));
            } else if (src.startsWith("file:")) {
                val file = src.substring("file:".length());
                val expand = Pathx.expandUserHome(file);
                val p = new Properties();
                p.load(new FileInputStream(expand));
                props.putAll(p);
            }
        }
        return props;
    }

    /**
     * 按照以下顺序,加载文件:
     * 1. classpath:conf/{SimpleClassName}.properties
     * 2. ~/.appconf/{SimpleClassName}.properties
     * 3. current_directory/conf/{SimpleClassName}.properties。
     * 4. Diamond client
     *
     * @param method 方法
     * @return 属性文件
     */
    private static Properties dealDefaultProperties(Method method) {
        val simpleName = method.getDeclaringClass().getSimpleName();
        val pfile = simpleName + ".properties";
        val p = Classpath.loadProperties("conf/" + pfile, true);

        val userHomeFile = new File(Pathx.userHome + "/.appconf/" + pfile);
        loadPropertiesFile(p, userHomeFile);

        val usdrDirFile = new File(Pathx.userDir + "/conf/" + pfile);
        loadPropertiesFile(p, usdrDirFile);

        p.putAll(new Miner().getProperties(simpleName, "default"));

        return p;
    }

    @SneakyThrows
    private static void loadPropertiesFile(Properties p, File file) {
        if (!file.exists()) return;

        val p1 = new Properties();
        p1.load(new FileInputStream(file));
        p.putAll(p1);
    }

    private static Object convertType(String value, Method method) {
        val rt = Primitives.unwrap(method.getReturnType());
        if (rt == String.class) return value;

        val converted = rt.isPrimitive() ? parsePrimitive(rt, value) : parseOther(rt, value);
        log.debug("get config {}.{} = {}", method.getDeclaringClass().getSimpleName(), method.getName(), converted);

        return converted;
    }

    private static Object parseOther(Class rt, String value) {
        return null;
    }

    private static Object parsePrimitive(Class rt, String value) {
        if (rt == boolean.class) return Str.anyOfIgnoreCase(value, "yes", "true", "on");
        if (rt == short.class) return Short.parseShort(value);
        if (rt == int.class) return Integer.parseInt(value);
        if (rt == long.class) return Long.parseLong(value);
        if (rt == float.class) return Float.parseFloat(value);
        if (rt == double.class) return Double.parseDouble(value);
        if (rt == byte.class) return Byte.parseByte(value);
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy