// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.data.preferences; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; import org.openstreetmap.josm.tools.CheckParameterUtil; import org.openstreetmap.josm.tools.bugreport.BugReport; /** * This class represents a property that can be represented as String. * * @author Michael Zangl * * @param <T> The property content type. * @since 10824 */ public abstract class AbstractToStringProperty<T> extends AbstractProperty<T> { /** * This is a version of this property that attempts to get the property with a more specialized key and - if that fails - uses the property * value as default. * * @author Michael Zangl * @param <T> The content type */ public static class ChildProperty<T> extends AbstractToStringProperty<T> { private final AbstractToStringProperty<T> parent; ChildProperty(AbstractToStringProperty<T> parent, String key) { super(key, null); CheckParameterUtil.ensureParameterNotNull(parent, "parent"); this.parent = parent; } @Override protected void storeDefaultValue() { // Default value hidden in preferences. } @Override public T getDefaultValue() { return parent.get(); } @Override protected T fromString(String string) { return parent.fromString(string); } @Override protected String toString(T t) { return parent.toString(t); } @Override protected void addListenerImpl(PreferenceChangedListener adapter) { super.addListenerImpl(adapter); parent.addListenerImpl(adapter); } @Override protected void addWeakListenerImpl(PreferenceChangedListener adapter) { super.addWeakListenerImpl(adapter); parent.addWeakListenerImpl(adapter); } @Override protected void removeListenerImpl(PreferenceChangedListener adapter) { super.removeListenerImpl(adapter); parent.removeListenerImpl(adapter); } @Override public CachingProperty<T> cached() { throw new UnsupportedOperationException("Not implemented yet."); } } /** * Create a new property and store the default value. * @param key The key * @param defaultValue The default value. * @see AbstractProperty#AbstractProperty(String, Object) */ public AbstractToStringProperty(String key, T defaultValue) { super(key, defaultValue); storeDefaultValue(); } @Override public T get() { String string = getAsString(); if (!string.isEmpty()) { try { return fromString(string); } catch (InvalidPreferenceValueException e) { Main.warn(BugReport.intercept(e).put("key", key).put("value", string)); } } return getDefaultValue(); } /** * Converts the string to an object of the given type. * @param string The string * @return The object. * @throws InvalidPreferenceValueException If the value could not be converted. */ protected abstract T fromString(String string); @Override public boolean put(T value) { String string = value == null ? null : toString(value); return getPreferences().put(getKey(), string); } /** * Converts the string to an object of the given type. * @param t The object. * @return The string representing the object * @throws InvalidPreferenceValueException If the value could not be converted. */ protected abstract String toString(T t); /** * Gets the preference value as String. * @return The string preference value. */ protected String getAsString() { T def = getDefaultValue(); return getPreferences().get(key, def == null ? "" : toString(def)); } /** * Gets a specialized setting value that has the current value as default * <p> * The key will be getKey().spec * @param spec The key specialization * @return The property */ public AbstractToStringProperty<T> getSpecialized(String spec) { return getChildProperty(getKey() + "." + spec); } /** * Gets a setting that defaults to this setting if the key is not set. * @param key The more specialized key. * @return The new setting. */ protected AbstractToStringProperty<T> getChildProperty(String key) { return new ChildProperty<>(this, key); } /** * Creates a new {@link CachingProperty} instance for this property. * @return The new caching property instance. */ public CachingProperty<T> cached() { return new CachingProperty<>(this); } }