com.puresoltechnologies.javafx.preferences.Preferences Maven / Gradle / Ivy
package com.puresoltechnologies.javafx.preferences;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceLoader;
import com.puresoltechnologies.javafx.extensions.properties.PropertyDefinition;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
/**
* This is the central service object for the preferences handling.
*
* @author Rick-Rainer Ludwig
*/
public class Preferences {
public static final String PREFERENCES_DIRECTORY_PROPERTY = Preferences.class.getPackage().getName() + ".directory";
private final Map> preferencesValues = new HashMap<>();
private static Preferences instance = null;
/**
* This method is used to initialize once the {@link Preferences} service.
* Without initialization, the service cannot be used.
*
* @throws IOException
*/
public static void initialize() throws IOException {
if (isInitialized()) {
throw new IllegalStateException("Preferences were already initialized.");
}
String directoryString = System.getProperty(PREFERENCES_DIRECTORY_PROPERTY);
if ((directoryString == null) || (directoryString.isEmpty())) {
directoryString = System.getProperty("user.home") + File.separator + ".javafx" + File.separator
+ "preferences";
}
File directory = new File(directoryString);
if (!directory.exists()) {
if (!directory.mkdirs()) {
throw new IOException("Could not create preferences directory '" + directoryString + "'.");
}
} else {
if (!directory.isDirectory()) {
throw new IOException("Preferences directory '" + directoryString + "' is not a directory.");
}
}
instance = new Preferences(directory);
}
public static void shutdown() {
if (!isInitialized()) {
throw new IllegalStateException("Preferences are not initialized.");
}
instance = null;
}
public static boolean isInitialized() {
return instance != null;
}
public static Preferences getInstance() {
if (instance == null) {
throw new IllegalStateException("Preferences are not initialized.");
}
return instance;
}
public static ObjectProperty getProperty(PropertyDefinition definition) {
assureInitialized();
return instance.getValueProperty(definition);
}
private static void assureInitialized() {
if (!isInitialized()) {
throw new IllegalStateException("Preferences not initialized.");
}
}
private final File directory;
public Preferences(File directory) {
this.directory = directory;
}
public T getValue(PropertyDefinition definition) {
return getValueProperty(definition).get();
}
public ObjectProperty getValueProperty(PropertyDefinition definition) {
@SuppressWarnings("unchecked")
ObjectProperty value = (ObjectProperty) preferencesValues.get(definition.getId());
if (value == null) {
T t = readValue(definition);
if (t != null) {
value = new SimpleObjectProperty<>(t);
} else {
value = new SimpleObjectProperty<>(definition.getDefaultValue());
}
preferencesValues.put(definition.getId(), value);
}
return value;
}
private T readValue(PropertyDefinition definition) {
File file = new File(directory, definition.getId());
if (!file.exists()) {
return null;
}
PreferencesSerializer serializer = findSerializer(definition);
try (FileInputStream fileInputStream = new FileInputStream(file)) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[256];
int size = -1;
while ((size = fileInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, size);
}
String string = new String(byteArrayOutputStream.toByteArray(), Charset.defaultCharset());
return serializer.deserialize(definition, string);
} catch (IOException e) {
return null;
}
}
public T setValue(PropertyDefinition definition, T newValue) {
writeValue(definition, newValue);
@SuppressWarnings("unchecked")
ObjectProperty value = (ObjectProperty) preferencesValues.get(definition.getId());
T oldValue = null;
if (value == null) {
value = new SimpleObjectProperty<>(definition.getDefaultValue());
preferencesValues.put(definition.getId(), value);
} else {
oldValue = value.get();
value.set(newValue);
}
return oldValue;
}
private void writeValue(PropertyDefinition definition, T value) {
File file = new File(directory, definition.getId());
if (file.exists()) {
if (!file.delete()) {
return; // XXX Needs fixing...
}
}
PreferencesSerializer serializer = findSerializer(definition);
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
String serialized = serializer.serialize(value);
fileOutputStream.write(serialized.getBytes(Charset.defaultCharset()));
} catch (IOException e) {
// intentionally left empty
}
}
private PreferencesSerializer findSerializer(PropertyDefinition definition) {
@SuppressWarnings("rawtypes")
ServiceLoader loader = ServiceLoader.load(PreferencesSerializer.class);
@SuppressWarnings("rawtypes")
Iterator iterator = loader.iterator();
while (iterator.hasNext()) {
@SuppressWarnings("unchecked")
PreferencesSerializer next = iterator.next();
if (next.isSuitable(definition)) {
return next;
}
}
return null;
}
}