001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.preferences; 003 004import org.openstreetmap.josm.Main; 005import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; 006import org.openstreetmap.josm.tools.CheckParameterUtil; 007import org.openstreetmap.josm.tools.bugreport.BugReport; 008 009/** 010 * This class represents a property that can be represented as String. 011 * 012 * @author Michael Zangl 013 * 014 * @param <T> The property content type. 015 * @since 10824 016 */ 017public abstract class AbstractToStringProperty<T> extends AbstractProperty<T> { 018 019 /** 020 * 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 021 * value as default. 022 * 023 * @author Michael Zangl 024 * @param <T> The content type 025 */ 026 public static class ChildProperty<T> extends AbstractToStringProperty<T> { 027 private final AbstractToStringProperty<T> parent; 028 029 ChildProperty(AbstractToStringProperty<T> parent, String key) { 030 super(key, null); 031 CheckParameterUtil.ensureParameterNotNull(parent, "parent"); 032 this.parent = parent; 033 } 034 035 @Override 036 protected void storeDefaultValue() { 037 // Default value hidden in preferences. 038 } 039 040 @Override 041 public T getDefaultValue() { 042 return parent.get(); 043 } 044 045 @Override 046 protected T fromString(String string) { 047 return parent.fromString(string); 048 } 049 050 @Override 051 protected String toString(T t) { 052 return parent.toString(t); 053 } 054 055 @Override 056 protected void addListenerImpl(PreferenceChangedListener adapter) { 057 super.addListenerImpl(adapter); 058 parent.addListenerImpl(adapter); 059 } 060 061 @Override 062 protected void addWeakListenerImpl(PreferenceChangedListener adapter) { 063 super.addWeakListenerImpl(adapter); 064 parent.addWeakListenerImpl(adapter); 065 } 066 067 @Override 068 protected void removeListenerImpl(PreferenceChangedListener adapter) { 069 super.removeListenerImpl(adapter); 070 parent.removeListenerImpl(adapter); 071 } 072 073 @Override 074 public CachingProperty<T> cached() { 075 throw new UnsupportedOperationException("Not implemented yet."); 076 } 077 } 078 079 /** 080 * Create a new property and store the default value. 081 * @param key The key 082 * @param defaultValue The default value. 083 * @see AbstractProperty#AbstractProperty(String, Object) 084 */ 085 public AbstractToStringProperty(String key, T defaultValue) { 086 super(key, defaultValue); 087 storeDefaultValue(); 088 } 089 090 @Override 091 public T get() { 092 String string = getAsString(); 093 if (!string.isEmpty()) { 094 try { 095 return fromString(string); 096 } catch (InvalidPreferenceValueException e) { 097 Main.warn(BugReport.intercept(e).put("key", key).put("value", string)); 098 } 099 } 100 return getDefaultValue(); 101 } 102 103 /** 104 * Converts the string to an object of the given type. 105 * @param string The string 106 * @return The object. 107 * @throws InvalidPreferenceValueException If the value could not be converted. 108 */ 109 protected abstract T fromString(String string); 110 111 @Override 112 public boolean put(T value) { 113 String string = value == null ? null : toString(value); 114 return getPreferences().put(getKey(), string); 115 } 116 117 /** 118 * Converts the string to an object of the given type. 119 * @param t The object. 120 * @return The string representing the object 121 * @throws InvalidPreferenceValueException If the value could not be converted. 122 */ 123 protected abstract String toString(T t); 124 125 /** 126 * Gets the preference value as String. 127 * @return The string preference value. 128 */ 129 protected String getAsString() { 130 T def = getDefaultValue(); 131 return getPreferences().get(key, def == null ? "" : toString(def)); 132 } 133 134 /** 135 * Gets a specialized setting value that has the current value as default 136 * <p> 137 * The key will be getKey().spec 138 * @param spec The key specialization 139 * @return The property 140 */ 141 public AbstractToStringProperty<T> getSpecialized(String spec) { 142 return getChildProperty(getKey() + "." + spec); 143 } 144 145 /** 146 * Gets a setting that defaults to this setting if the key is not set. 147 * @param key The more specialized key. 148 * @return The new setting. 149 */ 150 protected AbstractToStringProperty<T> getChildProperty(String key) { 151 return new ChildProperty<>(this, key); 152 } 153 154 /** 155 * Creates a new {@link CachingProperty} instance for this property. 156 * @return The new caching property instance. 157 */ 158 public CachingProperty<T> cached() { 159 return new CachingProperty<>(this); 160 } 161}