/*
* Copyright 2016 Igor Maznitsa.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.igormaznitsa.mindmap.swing.panel.utils;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.prefs.BackingStoreException;
import java.util.prefs.NodeChangeListener;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.xml.bind.DatatypeConverter;
import com.igormaznitsa.meta.annotation.MustNotContainNull;
import com.igormaznitsa.meta.common.utils.GetUtils;
/**
* Auxiliary class implementing Preferences, based on Properties.
* @since 1.3.1
*/
public class PropertiesPreferences extends Preferences {
private final Properties storage = new Properties();
private final List<PreferenceChangeListener> listeners = new ArrayList<PreferenceChangeListener>();
private final String comment;
public PropertiesPreferences(@Nullable final String comment, @Nonnull final String text) throws IOException {
this(comment);
this.storage.load(new StringReader(text));
}
public PropertiesPreferences(@Nullable final String comment){
super();
this.comment = comment;
}
@Override
public void put(@Nonnull final String key, @Nonnull final String value) {
this.storage.setProperty(key, value);
fireListeners(key, value);
}
@Override
@Nullable
public String get(@Nonnull final String key, @Nullable final String def) {
return this.storage.containsKey(key) ? this.storage.getProperty(key) : def;
}
@Override
public void remove(@Nonnull final String key) {
this.storage.remove(key);
fireListeners(key, null);
}
@Override
public void clear() throws BackingStoreException {
this.storage.clear();
fireListeners("", null);
}
@Override
public void putInt(@Nonnull final String key, final int value) {
final String newvalue = Integer.toString(value);
this.storage.setProperty(key, newvalue);
fireListeners(key, newvalue);
}
@Override
public int getInt(@Nonnull final String key, final int def) {
final String value = this.storage.getProperty(key);
return value == null ? def : Integer.parseInt(value);
}
@Override
public void putLong(@Nonnull final String key, final long value) {
final String newvalue = Long.toString(value);
this.storage.setProperty(key, newvalue);
fireListeners(key, newvalue);
}
@Override
public long getLong(@Nonnull final String key, final long def) {
final String value = this.storage.getProperty(key);
return value == null ? def : Long.parseLong(value);
}
@Override
public void putBoolean(@Nonnull final String key, final boolean value) {
final String newvalue = Boolean.toString(value);
this.storage.setProperty(key, newvalue);
fireListeners(key, newvalue);
}
@Override
public boolean getBoolean(@Nonnull final String key, final boolean def) {
final String value = this.storage.getProperty(key);
return value == null ? def : Boolean.parseBoolean(value);
}
@Override
public void putFloat(@Nonnull final String key, final float value) {
final String newvalue = Float.toString(value);
this.storage.setProperty(key, newvalue);
fireListeners(key, newvalue);
}
@Override
public float getFloat(@Nonnull final String key, final float def) {
final String value = this.storage.getProperty(key);
return value == null ? def : Float.parseFloat(value);
}
@Override
public void putDouble(@Nonnull final String key, final double value) {
final String newvalue = Double.toString(value);
this.storage.setProperty(key, newvalue);
fireListeners(key, newvalue);
}
@Override
public double getDouble(@Nonnull final String key, final double def) {
final String value = this.storage.getProperty(key);
return value == null ? def : Double.parseDouble(value);
}
@Override
public void putByteArray(@Nonnull final String key, @Nonnull final byte[] value) {
final String data = Utils.base64encode(value);
this.storage.setProperty(key, data);
fireListeners(key, data);
}
@Override
@Nullable
public byte[] getByteArray(@Nonnull final String key, @Nullable final byte[] def) {
final String found = this.storage.getProperty(key);
return found == null ? def : DatatypeConverter.parseBase64Binary(found);
}
@Override
@Nonnull
@MustNotContainNull
public String[] keys() throws BackingStoreException {
final Set<String> keys = this.storage.stringPropertyNames();
return keys.toArray(new String[keys.size()]);
}
@Override
@Nullable
@MustNotContainNull
public String[] childrenNames() throws BackingStoreException {
return null;
}
@Override
@Nullable
public Preferences parent() {
return null;
}
@Override
@Nullable
public Preferences node(@Nonnull final String pathName) {
return null;
}
@Override
public boolean nodeExists(@Nonnull final String pathName) throws BackingStoreException {
return false;
}
@Override
public void removeNode() throws BackingStoreException {
}
@Override
@Nonnull
public String name() {
return "/";
}
@Override
@Nonnull
public String absolutePath() {
return "/";
}
@Override
public boolean isUserNode() {
return false;
}
@Override
@Nonnull
public String toString() {
final StringWriter writer = new StringWriter();
try{
this.storage.store(writer, GetUtils.ensureNonNull(this.comment, ""));
return writer.toString();
}catch(IOException ex){
throw new Error("Unexpected error",ex);
}
}
@Override
public void flush() throws BackingStoreException {
}
@Override
public void sync() throws BackingStoreException {
}
@Override
public void addPreferenceChangeListener(@Nonnull final PreferenceChangeListener pcl) {
this.listeners.add(pcl);
}
@Override
public void removePreferenceChangeListener(@Nonnull final PreferenceChangeListener pcl) {
this.listeners.remove(pcl);
}
@Override
public void addNodeChangeListener(@Nonnull final NodeChangeListener ncl) {
}
@Override
public void removeNodeChangeListener(@Nonnull final NodeChangeListener ncl) {
}
@Override
public void exportNode(@Nonnull final OutputStream os) throws IOException, BackingStoreException {
this.exportSubtree(os);
}
@Override
public void exportSubtree(@Nonnull final OutputStream os) throws IOException, BackingStoreException {
this.storage.store(os, GetUtils.ensureNonNull(this.comment,""));
}
private void fireListeners(@Nonnull final String key, @Nullable final String newValue){
final PreferenceChangeEvent event = new PreferenceChangeEvent(this, key, newValue);
for(final PreferenceChangeListener l : this.listeners){
l.preferenceChange(event);
}
}
}