Package net.cakenet.jsaton.config

Source Code of net.cakenet.jsaton.config.Configuration

package net.cakenet.jsaton.config;

import net.cakenet.jsaton.Main;
import net.cakenet.jsaton.util.FileManager;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public final class Configuration {
    public static final Configuration APP_CONFIG;

    private Path path;
    private LinkedHashMap<String, Object> props = new LinkedHashMap<>();

    private Configuration(Path path) {
        this.path = path;
        load();
    }

    public <T> T get(String key) {
        if (!props.containsKey(key))
            return null;
        return (T) props.get(key);
    }

    public <T> T get(String key, T def) {
        if (!props.containsKey(key))
            set(key, def);
        return (T) props.get(key);
    }

    public void set(String key, Object value) {
        props.put(key, value);
        save();
    }

    public LinkedHashMap<String, Object> getEntries() {
        return props;
    }

    private void load() {
        try {
            File f = FileManager.getAppFile(path);
            props.clear();
            if (!f.exists())
                return;
            SAXBuilder b = new SAXBuilder();
            Document d = b.build(f);

            Element root = d.getRootElement();

            // Get config
            props = loadConfig(root);
        } catch (Exception e) {
            throw new RuntimeException("Error loading config", e);
        }
    }

    private void save() {
        File f = FileManager.getAppFile(path);
        Element root = new Element("config");
        Document d = new Document(root);
        storeConfig(root, props);
        XMLOutputter xo = new XMLOutputter(Format.getPrettyFormat());
        try {
            OutputStream os = new FileOutputStream(f);
            xo.output(d, os);
            os.close();
        } catch (IOException e) {
            throw new RuntimeException("Error saving config", e);
        }
    }

    private LinkedHashMap<String, Object> loadConfig(Element c) {
        LinkedHashMap<String, Object> props = new LinkedHashMap<String, Object>();
        for (Element e : c.getChildren("config")) {
            String name = e.getAttributeValue("name");
            String type = e.getAttributeValue("type");
            Object v = loadValue(e, type);

            // multiple values, bung in array
            if (props.containsKey(name)) {
                Object o = props.get(name);
                Object[] d;
                int idx;
                if (o.getClass().isArray()) {
                    Object[] s = (Object[]) o;
                    idx = Array.getLength(o);
                    d = new Object[idx + 1];
                    System.arraycopy(s, 0, d, 0, idx);
                } else {
                    d = new Object[2];
                    d[0] = o;
                    idx = 1;
                }
                d[idx] = v;
                v = d;
            }
            props.put(name, v);
        }
        return props;
    }

    private Object loadValue(Element e, String type) {
        String value = e.getTextTrim();
        if (type.equals("int"))
            return Integer.parseInt(value);
        else if (type.equals("float"))
            return Float.parseFloat(value);
        else if (type.equals("double"))
            return Double.parseDouble(value);
        else if (type.equals("bool"))
            return Boolean.parseBoolean(value);
        else if (type.equals("map")) {
            String entryTypes = e.getAttributeValue("valueType");
            Map<String, Object> objs = new TreeMap<String, Object>();
            for (Element child : e.getChildren("entry")) {
                objs.put(child.getAttributeValue("key"), loadValue(child, entryTypes));
            }
            return objs;
        } else if (type.equals("list")) {
            String entryTypes = e.getAttributeValue("valueType");
            List<Object> list = new LinkedList<Object>();
            for (Element child : e.getChildren("entry")) {
                list.add(loadValue(child, entryTypes));
            }
            return list;
        } else if (type.equals("array")) {
            String entryTypes = e.getAttributeValue("valueType");
            List<Element> children = e.getChildren("entry");
            Object[] o = new Object[children.size()];
            for (int i = 0; i < children.size(); i++)
                o[i] = loadValue(children.get(i), entryTypes);
            return o;
        }
        return value;
    }

    private void storeConfig(Element parent, Map<String, Object> properties) {
        for (String key : properties.keySet()) {
            Object v = properties.get(key);
            parent.addContent(createProperty("config", key, v, classToType(v.getClass())));
        }
    }

    private Element createProperty(String nodeName, String key, Object o, String type) {
        Element e = new Element(nodeName);
        if (key != null)
            e.setAttribute("name", key);
        if (type != null)
            e.setAttribute("type", type);
        if (o instanceof Map) { // map
            Map<String, Object> m = (Map<String, Object>) o;
            if (m.isEmpty())
                return e; // ignore
            Class<? extends Object> eType = null;
            for (String k : m.keySet()) {
                Object val = m.get(k);
                if (eType == null)
                    eType = val.getClass();
                eType = findCommonType(eType, val.getClass());
                Element c = createProperty("entry", null, val, null);
                c.setAttribute("key", k);
                e.addContent(c);
            }
            e.setAttribute("valueType", classToType(eType));
            return e;
        } else if (o instanceof List) {
            List<?> list = (List<?>) o;
            if (list.isEmpty())
                return e; // ignore...
            Class<?> eType = null;
            for (Object a : list) {
                if (eType == null)
                    eType = a.getClass();
                eType = findCommonType(eType, a.getClass());
                Element c = createProperty("entry", null, a, null);
                e.addContent(c);
            }
            e.setAttribute("valueType", classToType(eType));
            return e;
        } else if (o.getClass().isArray()) { // array
            Object[] vals = (Object[]) o;
            Class<? extends Object> eType = null;
            for (Object val : vals) {
                if (eType == null)
                    eType = val.getClass();
                eType = findCommonType(eType, val.getClass());
                e.addContent(createProperty("entry", null, val, null));
            }
            e.setAttribute("valueType", classToType(eType));
            return e;
        }
        e.setText(o.toString());
        return e;
    }

    private static Class<?> findCommonType(Class<?> a, Class<?> b) {
        if (a == b)
            return a;
        if (a.isAssignableFrom(b))
            return a;
        if (b.isAssignableFrom(a))
            return b;
        return null;
    }

    private static String classToType(Class<?> c) {
        if (c == String.class)
            return "string";
        if (c == Boolean.TYPE || c == Boolean.class)
            return "bool";
        if (c == Integer.TYPE || c == Integer.class)
            return "int";
        if (c == Float.TYPE || c == Float.class)
            return "float";
        if (c == Double.TYPE || c == Double.class)
            return "double";
        if (c.isArray())
            return "array";
        if (Map.class.isAssignableFrom(c))
            return "map";
        if (List.class.isAssignableFrom(c))
            return "list";
        return null;
    }

    public static Configuration load(String base, String... sub) {
        return new Configuration(Paths.get(base, sub));
    }

    static {
        APP_CONFIG = Configuration.load("config.xml");
        String userDataPath = APP_CONFIG.get("user.data", FileManager.USER_HOME.resolve(Main.APP_NAME).toString());
        FileManager.setUserDataPath(Paths.get(userDataPath));
    }
}
TOP

Related Classes of net.cakenet.jsaton.config.Configuration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.