filebot/source/net/sourceforge/tuned/PreferencesMap.java

348 lines
6.6 KiB
Java

package net.sourceforge.tuned;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
public class PreferencesMap<T> implements Map<String, T> {
private final Preferences prefs;
private final Adapter<T> adapter;
public PreferencesMap(Preferences prefs, Adapter<T> adapter) {
this.prefs = prefs;
this.adapter = adapter;
}
@Override
public T get(Object key) {
return adapter.get(prefs, key.toString());
}
@Override
public T put(String key, T value) {
adapter.put(prefs, key, value);
// don't know previous entry
return null;
}
@Override
public T remove(Object key) {
adapter.remove(prefs, key.toString());
// don't know removed entry
return null;
}
public String[] keys() {
try {
return adapter.keys(prefs);
} catch (BackingStoreException e) {
throw new RuntimeException(e);
}
}
@Override
public void clear() {
for (String key : keys()) {
adapter.remove(prefs, key);
}
}
@Override
public boolean containsKey(Object key) {
if (key instanceof String) {
return Arrays.asList(keys()).contains(key);
}
return false;
}
@Override
public boolean containsValue(Object value) {
for (String key : keys()) {
if (value.equals(get(key)))
return true;
}
return false;
}
@Override
public Set<Entry<String, T>> entrySet() {
Set<Map.Entry<String, T>> entries = new LinkedHashSet<Map.Entry<String, T>>();
for (String key : keys()) {
entries.add(new PreferencesEntry<T>(prefs, key, adapter));
}
return entries;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public Set<String> keySet() {
return new LinkedHashSet<String>(Arrays.asList(keys()));
}
@Override
public void putAll(Map<? extends String, ? extends T> map) {
for (Map.Entry<? extends String, ? extends T> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public int size() {
return keys().length;
}
@Override
public Collection<T> values() {
List<T> values = new ArrayList<T>();
for (String key : keys()) {
values.add(get(key));
}
return values;
}
public static PreferencesMap<String> map(Preferences prefs) {
return map(prefs, new StringAdapter());
}
public static <T> PreferencesMap<T> map(Preferences prefs, Adapter<T> adapter) {
return new PreferencesMap<T>(prefs, adapter);
}
public static interface Adapter<T> {
public String[] keys(Preferences prefs) throws BackingStoreException;
public T get(Preferences prefs, String key);
public void put(Preferences prefs, String key, T value);
public void remove(Preferences prefs, String key);
}
public static abstract class AbstractAdapter<T> implements Adapter<T> {
@Override
public abstract T get(Preferences prefs, String key);
@Override
public abstract void put(Preferences prefs, String key, T value);
@Override
public String[] keys(Preferences prefs) throws BackingStoreException {
return prefs.keys();
}
@Override
public void remove(Preferences prefs, String key) {
prefs.remove(key);
}
}
public static class StringAdapter extends AbstractAdapter<String> {
@Override
public String get(Preferences prefs, String key) {
return prefs.get(key, null);
}
@Override
public void put(Preferences prefs, String key, String value) {
prefs.put(key, value);
}
}
public static class SimpleAdapter<T> extends AbstractAdapter<T> {
private final Constructor<T> constructor;
public SimpleAdapter(Class<T> type) {
try {
constructor = type.getConstructor(String.class);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
@Override
public T get(Preferences prefs, String key) {
String value = prefs.get(key, null);
if (value != null) {
try {
return constructor.newInstance(value);
} catch (InvocationTargetException e) {
// try to throw the cause directly, e.g. NumberFormatException
throw ExceptionUtilities.asRuntimeException(e.getCause());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return null;
}
@Override
public void put(Preferences prefs, String key, T value) {
prefs.put(key, value.toString());
}
public static <T> SimpleAdapter<T> forClass(Class<T> type) {
return new SimpleAdapter<T>(type);
}
}
public static class SerializableAdapter<T extends Serializable> extends AbstractAdapter<T> {
@SuppressWarnings("unchecked")
@Override
public T get(Preferences prefs, String key) {
byte[] bytes = prefs.getByteArray(key, null);
if (bytes == null)
return null;
try {
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
Object object = in.readObject();
in.close();
return (T) object;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void put(Preferences prefs, String key, T value) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try {
ObjectOutputStream out = new ObjectOutputStream(buffer);
out.writeObject(value);
out.close();
prefs.putByteArray(key, buffer.toByteArray());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static class PreferencesEntry<T> implements Entry<String, T> {
private final String key;
private final Preferences prefs;
private final Adapter<T> adapter;
private T defaultValue = null;
public PreferencesEntry(Preferences prefs, String key, Adapter<T> adapter) {
this.key = key;
this.prefs = prefs;
this.adapter = adapter;
}
@Override
public String getKey() {
return key;
}
@Override
public T getValue() {
T value = adapter.get(prefs, key);
return value != null ? value : defaultValue;
}
@Override
public T setValue(T value) {
adapter.put(prefs, key, value);
return null;
}
public PreferencesEntry<T> defaultValue(T defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public void remove() {
adapter.remove(prefs, key);
}
}
}