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

org.swiftboot.util.pref.PreferenceManager Maven / Gradle / Ivy

The newest version!
package org.swiftboot.util.pref;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

/**
 * A singleton wrapper class for Java Preference class.
 * There are getPreference() methods for retrieving preference in different manner, and call savePreference() to save preferences.
 * As of 2.4.7, use getPreferenceAlias() if you want to read preference from different keys, it is very useful when you decide to
 * migrate one preference key to another.
 *
 * @author allen
 * @since 2.3
 */
public class PreferenceManager {

    private final static Logger log = LoggerFactory.getLogger(PreferenceManager.class);

    /**
     * Class that identifies the application.
     */
    private static Class ownerClass;

    private static PreferenceManager instance;

    private final Preferences prefs;

    private final Map converterMap = new HashMap<>();

    /**
     * prefix adds to the preference key with dot '.',
     * like "prefix.my_pref"
     */
    private String prefix;

    private PreferenceManager(Class clazz) {
        prefs = Preferences.userNodeForPackage(clazz);
    }

    public static synchronized PreferenceManager getInstance(Class ownerClass) {
        if (ownerClass == null) {
            throw new RuntimeException("Owner class represent the application must be provided");
        }
        PreferenceManager.ownerClass = ownerClass;
        return getInstance();
    }

    /**
     * Setup ownerClass before calling this method.
     *
     * @return
     */
    public static synchronized PreferenceManager getInstance() {
        if (instance == null) {
            if (ownerClass == null) {
                ownerClass = PreferenceManager.class;
            }
            log.info("Initialize preference for class: " + ownerClass);
            instance = new PreferenceManager(ownerClass);
        }
        return instance;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    private String absoluteKey(String key) {
        if (StringUtils.isNotBlank(prefix)) {
            return String.format("%s.%s", prefix, key);
        }
        return key;
    }

    /**
     * Add converter to user customized object.
     * The converter converts customized object to value that can be saved to preferences storage, and also reversely.
     *
     * @param clazz
     * @param converter
     */
    public void setConverter(Class clazz, Converter converter) {
        if (converterMap.containsKey(clazz)) {
            throw new RuntimeException(String.format("Converter for class type %s already exists", clazz));
        }
        converterMap.put(clazz, converter);
    }

    /**
     * Remove converter for class.
     *
     * @param clazz
     */
    public void removeConverter(Class clazz) {
        converterMap.remove(clazz);
    }

    /**
     * @param key
     * @param value
     */
    public void savePreference(String key, Object value) {
        if (value == null) return;
        key = absoluteKey(key);
        if (value instanceof String) {
            prefs.put(key, (String) value);
        }
        else if (value instanceof Integer) {
            prefs.putInt(key, (Integer) value);
        }
        else if (value instanceof Long) {
            prefs.putLong(key, (Long) value);
        }
        else if (value instanceof Boolean) {
            prefs.putBoolean(key, (Boolean) value);
        }
        else if (value instanceof Double) {
            prefs.putDouble(key, (Double) value);
        }
        else if (value instanceof Float) {
            prefs.putFloat(key, (Float) value);
        }
        else if (value instanceof byte[]) {
            prefs.putByteArray(key, (byte[]) value);
        }
        else {
            for (Class c : converterMap.keySet()) {
                if (c.isAssignableFrom(value.getClass())) {
                    Converter converter = converterMap.get(c);
                    Class saveAs = converter.getSaveAs();
                    log.trace(String.format("Save %s as: %s", value.getClass(), saveAs));
                    Object serialized = converter.serialize(value);
                    if (saveAs == String.class) {
                        prefs.put(key, (String) serialized);
                        return;
                    }
                    else if (saveAs == Integer.class) {
                        prefs.putInt(key, (Integer) serialized);
                        return;
                    }
                    else if (saveAs == Long.class) {
                        prefs.putLong(key, (Long) serialized);
                        return;
                    }
                    else if (saveAs == byte[].class) {
                        prefs.putByteArray(key, (byte[]) serialized);
                        return;
                    }
                    else {
                        throw new RuntimeException(String.format("Can't save preference as data type %s", saveAs));
                    }
                }
            }
            throw new RuntimeException("Not supported class type: " + value.getClass());
        }
    }

    /**
     * Get preference by key, return null if it doesn't exist.
     *
     * @param key
     * @return
     */
    public Object getPreference(String key) {
        return prefs.get(key, null);
    }

    public Object getPreferenceAlias(String key, String alias) {
        Object v = this.getPreference(key);
        if (v == null && alias != null) {
            v = this.getPreference(alias);
        }
        return v;
    }

    /**
     * Get preference by field of an object, if not exists, return the field value of object.
     *
     * @param key
     * @param field
     * @param target
     * @param 
     * @return
     */
    public  T getPreference(String key, Field field, Object target) {
        if (field == null) {
            throw new RuntimeException("field can't be null");
        }
        if (target == null) {
            throw new RuntimeException("target object can't be null");
        }
        key = absoluteKey(key);
        Class clazz = (Class) field.getType();
        field.setAccessible(true);
        Object val = null;
        try {
            if (clazz == Integer.class || clazz == int.class) {
                val = prefs.getInt(key, field.getInt(target));
            }
            else if (clazz == Long.class || clazz == long.class) {
                val = prefs.getLong(key, field.getLong(target));
            }
            else if (clazz == Boolean.class || clazz == boolean.class) {
                val = prefs.getBoolean(key, field.getBoolean(target));
            }
            else if (clazz == Float.class || clazz == float.class) {
                val = prefs.getFloat(key, field.getFloat(target));
            }
            else if (clazz == Double.class || clazz == double.class) {
                val = prefs.getDouble(key, field.getDouble(target));
            }
            else if (clazz == byte[].class) {
                val = prefs.getByteArray(key, (byte[]) field.get(target));
            }
            else if (clazz == String.class) {
                val = prefs.get(key, (String) field.get(target));
            }
            else {
                for (Class c : converterMap.keySet()) {
                    if (c.isAssignableFrom(clazz)) {
                        Converter converter = converterMap.get(clazz);
                        Class saveAs = converter.getSaveAs();
                        if (saveAs == String.class) {
                            String s = prefs.get(key, null);
                            val = s == null ? field.get(target) : (T) converter.deserialize(s);
                        }
                        else if (saveAs == Integer.class) {
                            int v = prefs.getInt(key, Integer.MIN_VALUE);
                            val = v == Integer.MIN_VALUE ? field.get(target) : (T) converter.deserialize(Integer.valueOf(v));
                        }
                        else if (saveAs == Long.class) {
                            long v = prefs.getLong(key, Long.MIN_VALUE);
                            val = v == Long.MIN_VALUE ? field.get(target) : (T) converter.deserialize(v);
                        }
                        else if (saveAs == byte[].class) {
                            byte[] v = prefs.getByteArray(key, null);
                            val = v == null ? (byte[]) field.get(target) : (T) converter.deserialize(v);
                        }
                        else {
                            throw new RuntimeException(String.format("Can't get preference as data type %s", saveAs));
                        }
                        break;
                    }
                }
            }
        } catch (IllegalAccessException | RuntimeException e) {
            e.printStackTrace();
            return null;
        }
        if (val == null) {
            return null;
        }
        return (T) val;
    }

    public  T getPreferenceAlias(String key, String alias, Field field, Object target) {
        T v = this.getPreference(key, field, target);
        if (v == null && alias != null) {
            v = this.getPreference(alias, field, target);
        }
        return v;
    }

    /**
     * Get preference by class type, if not exits, return defaultValue.
     *
     * @param key
     * @param clazz
     * @param defaultValue
     * @param 
     * @return
     */
    public  T getPreference(String key, Class clazz, T defaultValue) {
        if (clazz == null) {
            throw new RuntimeException("class type can't be null");
        }
        if (defaultValue == null) {
            throw new RuntimeException(String.format("default value for %s can't be null", key));
        }
        key = absoluteKey(key);
        Object val = null;
        if (clazz == Integer.class || clazz == int.class) {
            val = prefs.getInt(key, (Integer) defaultValue);
        }
        else if (clazz == Long.class || clazz == long.class) {
            val = prefs.getLong(key, (Long) defaultValue);
        }
        else if (clazz == Boolean.class || clazz == boolean.class) {
            val = prefs.getBoolean(key, (Boolean) defaultValue);
        }
        else if (clazz == Float.class || clazz == float.class) {
            val = prefs.getFloat(key, (Float) defaultValue);
        }
        else if (clazz == Double.class || clazz == double.class) {
            val = prefs.getDouble(key, (Double) defaultValue);
        }
        else if (clazz == byte[].class) {
            val = prefs.getByteArray(key, ((byte[]) defaultValue));
        }
        else if (clazz == String.class) {
            val = prefs.get(key, (String) defaultValue);
        }
        else {
            for (Class c : converterMap.keySet()) {
                if (c.isAssignableFrom(clazz)) {
                    Converter converter = converterMap.get(clazz);
                    Class saveAs = converter.getSaveAs();
                    if (saveAs == String.class) {
                        String s = prefs.get(key, null);
                        val = s == null ? defaultValue : (T) converter.deserialize(s);
                    }
                    else if (saveAs == Integer.class) {
                        int v = prefs.getInt(key, Integer.MIN_VALUE);
                        val = v == Integer.MIN_VALUE ? defaultValue : (T) converter.deserialize(Integer.valueOf(v));
                    }
                    else if (saveAs == Long.class) {
                        long v = prefs.getLong(key, Long.MIN_VALUE);
                        val = v == Long.MIN_VALUE ? defaultValue : (T) converter.deserialize(Long.valueOf(v));
                    }
                    else if (saveAs == byte[].class) {
                        byte[] v = prefs.getByteArray(key, null);
                        val = v == null ? defaultValue : (T) converter.deserialize(v);
                    }
                    else {
                        throw new RuntimeException(String.format("Can't get preference as data type %s", saveAs));
                    }
                    break;
                }
            }
        }
        if (val == null) {
            return defaultValue;
        }
        return (T) val;
    }


    public  T getPreferenceAlias(String key, String alias, Class clazz, T defaultValue) {
        key = absoluteKey(key);
        Object check = prefs.get(key, null);
        T v = null;
        if (check == null && alias != null) {
            v = this.getPreference(alias, clazz, defaultValue);
        }
        return v;
    }

    /**
     * Get preference by class type, if not exists, return MIN_VALUE for integer/long or float/double type, empty bytes array for byte array type
     * false for boolean type, "" for string type, null for user customized object.
     *
     * @param key
     * @param clazz
     * @param 
     * @return
     */
    public  T getPreference(String key, Class clazz) {
        if (clazz == null) {
            throw new RuntimeException("class type can't be null");
        }
        key = absoluteKey(key);
        T val = null;
        if (clazz == Integer.class || clazz == int.class) {
            val = (T) Integer.valueOf(prefs.getInt(key, Integer.MIN_VALUE));
        }
        else if (clazz == Long.class || clazz == long.class) {
            val = (T) Long.valueOf(prefs.getLong(key, Long.MIN_VALUE));
        }
        else if (clazz == Boolean.class || clazz == boolean.class) {
            val = (T) Boolean.valueOf(prefs.getBoolean(key, Boolean.FALSE));
        }
        else if (clazz == Float.class || clazz == float.class) {
            val = (T) Float.valueOf(prefs.getFloat(key, Float.MIN_VALUE));
        }
        else if (clazz == Double.class || clazz == double.class) {
            val = (T) Double.valueOf(prefs.getDouble(key, Double.MIN_VALUE));
        }
        else if (clazz == byte[].class) {
            val = (T) prefs.getByteArray(key, new byte[]{});
        }
        else if (clazz == String.class) {
            val = (T) prefs.get(key, ""); // as string
        }
        else {
            for (Class c : converterMap.keySet()) {
                if (clazz.isAssignableFrom(c)) {
                    Converter converter = converterMap.get(clazz);
                    Class saveAs = converter.getSaveAs();
                    if (saveAs == String.class) {
                        String v = prefs.get(key, null);
                        val = v == null ? null : (T) converter.deserialize(v);
                    }
                    else if (saveAs == Integer.class) {
                        int v = prefs.getInt(key, Integer.MIN_VALUE);
                        val = v == Integer.MIN_VALUE ? null : (T) converter.deserialize(Integer.valueOf(v));
                    }
                    else if (saveAs == Long.class) {
                        long v = prefs.getLong(key, Long.MIN_VALUE);
                        val = v == Long.MIN_VALUE ? null : (T) converter.deserialize(Long.valueOf(v));
                    }
                    else if (saveAs == byte[].class) {
                        byte[] v = prefs.getByteArray(key, null);
                        val = v == null ? null : (T) converter.deserialize(v);
                    }
                    else {
                        throw new RuntimeException(String.format("Can't get preference as data type %s", saveAs));
                    }
                    break;
                }
            }
        }
        if (val == null) {
            return null;
        }
        return (T) val;
    }


    public  T getPreferenceAlias(String key, String alias, Class clazz) {
        key = absoluteKey(key);
        Object check = prefs.get(key, null);
        T v;
        if (check == null && alias != null) {
            v = this.getPreference(absoluteKey(alias), clazz);
        }
        else {
            v = this.getPreference(key, clazz);
        }
        return v;
    }


    /**
     * Get preference only by key, if not exists, return user provided default value.
     *
     * @param key
     * @param def
     * @param 
     * @return
     */
    public  T getPreference(String key, T def) {
        if (def == null) {
            throw new RuntimeException(String.format("default value for %s can't be null", key));
        }
        key = absoluteKey(key);
        T val = null;
        if (def instanceof Integer) {
            val = (T) Integer.valueOf(prefs.getInt(key, (Integer) def));
        }
        else if (def instanceof Long) {
            val = (T) Long.valueOf(prefs.getLong(key, (Long) def));
        }
        else if (def instanceof Boolean) {
            val = (T) Boolean.valueOf(prefs.getBoolean(key, (Boolean) def));
        }
        else if (def instanceof Float) {
            val = (T) Float.valueOf(prefs.getFloat(key, (Float) def));
        }
        else if (def instanceof Double) {
            val = (T) Double.valueOf(prefs.getDouble(key, (Double) def));
        }
        else if (def instanceof byte[]) {
            val = (T) prefs.getByteArray(key, (byte[]) def);
        }
        else if (def instanceof String) {
            val = (T) prefs.get(key, (String) def);
        }
        else {
            for (Class clazz : converterMap.keySet()) {
                if (clazz.isAssignableFrom(def.getClass())) {
                    Converter converter = converterMap.get(clazz);
                    Class saveAs = converter.getSaveAs();
                    if (saveAs == String.class) {
                        String s = prefs.get(key, null);
                        val = s == null ? def : (T) converter.deserialize(s);
                    }
                    else if (saveAs == Integer.class) {
                        int v = prefs.getInt(key, Integer.MIN_VALUE);
                        val = v == Integer.MIN_VALUE ? def : (T) converter.deserialize(Integer.valueOf(v));
                    }
                    else if (saveAs == Long.class) {
                        long v = prefs.getLong(key, Long.MIN_VALUE);
                        val = v == Long.MIN_VALUE ? def : (T) converter.deserialize(Long.valueOf(v));
                    }
                    else if (saveAs == byte[].class) {
                        byte[] v = prefs.getByteArray(key, null);
                        val = v == null ? def : (T) converter.deserialize(v);
                    }
                    else {
                        throw new RuntimeException(String.format("Can't get preference as data type %s", saveAs));
                    }
                }
            }
        }
        if (val == null) {
            return def;
        }
        return val;
    }

    public  T getPreferenceAlias(String key, String alias, T defaultValue) {
        key = absoluteKey(key);
        Object check = prefs.get(key, null);
        T v;
        if (check == null && alias != null) {
            v = this.getPreference(absoluteKey(alias), defaultValue);
        }
        else {
            v = this.getPreference(key, defaultValue);
        }
        return v;
    }

    public void removePreference(String key) {
        prefs.remove(key);
    }

    public void flush() {
        try {
            prefs.flush();
        } catch (BackingStoreException e) {
            e.printStackTrace();
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy