Changeset 6578 in josm for trunk/src/org
- Timestamp:
- 2013-12-31T13:04:42+01:00 (11 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/CustomConfigurator.java
r6552 r6578 39 39 40 40 import org.openstreetmap.josm.Main; 41 import org.openstreetmap.josm.data.Preferences.ListListSetting; 42 import org.openstreetmap.josm.data.Preferences.ListSetting; 43 import org.openstreetmap.josm.data.Preferences.MapListSetting; 41 44 import org.openstreetmap.josm.data.Preferences.Setting; 45 import org.openstreetmap.josm.data.Preferences.StringSetting; 42 46 import org.openstreetmap.josm.gui.io.DownloadFileTask; 43 47 import org.openstreetmap.josm.plugins.PluginDownloadTask; … … 276 280 277 281 278 282 public static void deleteFile(String path, String base) { 279 283 String dir = getDirectoryByAbbr(base); 280 284 if (dir==null) { … … 290 294 deleteFileOrDirectory(fOut); 291 295 } 292 return;293 296 } 294 297 … … 401 404 public static Preferences clonePreferences(Preferences pref) { 402 405 Preferences tmp = new Preferences(); 403 tmp.defaults.putAll( pref.defaults ); 404 tmp.properties.putAll( pref.properties ); 405 tmp.arrayDefaults.putAll( pref.arrayDefaults ); 406 tmp.arrayProperties.putAll( pref.arrayProperties ); 407 tmp.collectionDefaults.putAll( pref.collectionDefaults ); 408 tmp.collectionProperties.putAll( pref.collectionProperties ); 409 tmp.listOfStructsDefaults.putAll( pref.listOfStructsDefaults ); 410 tmp.listOfStructsProperties.putAll( pref.listOfStructsProperties ); 406 tmp.settingsMap.putAll(pref.settingsMap); 407 tmp.defaultsMap.putAll(pref.defaultsMap); 411 408 tmp.colornames.putAll( pref.colornames ); 412 409 … … 738 735 739 736 /** 740 * Helper class to do specific Pref rences operation - appending, replacing,737 * Helper class to do specific Preferences operation - appending, replacing, 741 738 * deletion by key and by value 742 739 * Also contains functions that convert preferences object to JavaScript object and back … … 745 742 746 743 private static void replacePreferences(Preferences fragment, Preferences mainpref) { 747 // normal prefs 748 for (Entry<String, String> entry : fragment.properties.entrySet()) { 749 mainpref.put(entry.getKey(), entry.getValue()); 750 } 751 // "list" 752 for (Entry<String, List<String>> entry : fragment.collectionProperties.entrySet()) { 753 mainpref.putCollection(entry.getKey(), entry.getValue()); 754 } 755 // "lists" 756 for (Entry<String, List<List<String>>> entry : fragment.arrayProperties.entrySet()) { 757 List<Collection<String>> array = new ArrayList<Collection<String>>(); 758 array.addAll(entry.getValue()); 759 mainpref.putArray(entry.getKey(), array); 760 } 761 /// "maps" 762 for (Entry<String, List<Map<String, String>>> entry : fragment.listOfStructsProperties.entrySet()) { 763 mainpref.putListOfStructs(entry.getKey(), entry.getValue()); 764 } 765 744 for (Entry<String, Setting> entry: fragment.settingsMap.entrySet()) { 745 mainpref.putSetting(entry.getKey(), entry.getValue()); 746 } 766 747 } 767 748 768 749 private static void appendPreferences(Preferences fragment, Preferences mainpref) { 769 // normal prefs 770 for (Entry<String, String> entry : fragment.properties.entrySet()) { 771 mainpref.put(entry.getKey(), entry.getValue()); 772 } 773 774 // "list" 775 for (Entry<String, List<String>> entry : fragment.collectionProperties.entrySet()) { 750 for (Entry<String, Setting> entry: fragment.settingsMap.entrySet()) { 776 751 String key = entry.getKey(); 777 778 Collection<String> newItems = getCollection(mainpref, key, true); 779 if (newItems == null) continue; 780 781 for (String item : entry.getValue()) { 782 // add nonexisting elements to then list 783 if (!newItems.contains(item)) { 784 newItems.add(item); 752 if (entry.getValue() instanceof StringSetting) { 753 mainpref.putSetting(key, entry.getValue()); 754 } else if (entry.getValue() instanceof ListSetting) { 755 ListSetting lSetting = (ListSetting) entry.getValue(); 756 Collection<String> newItems = getCollection(mainpref, key, true); 757 if (newItems == null) continue; 758 for (String item : lSetting.getValue()) { 759 // add nonexisting elements to then list 760 if (!newItems.contains(item)) { 761 newItems.add(item); 762 } 785 763 } 764 mainpref.putCollection(key, newItems); 765 } else if (entry.getValue() instanceof ListListSetting) { 766 ListListSetting llSetting = (ListListSetting) entry.getValue(); 767 Collection<Collection<String>> newLists = getArray(mainpref, key, true); 768 if (newLists == null) continue; 769 770 for (Collection<String> list : llSetting.getValue()) { 771 // add nonexisting list (equals comparison for lists is used implicitly) 772 if (!newLists.contains(list)) { 773 newLists.add(list); 774 } 775 } 776 mainpref.putArray(key, newLists); 777 } else if (entry.getValue() instanceof MapListSetting) { 778 MapListSetting mlSetting = (MapListSetting) entry.getValue(); 779 List<Map<String, String>> newMaps = getListOfStructs(mainpref, key, true); 780 if (newMaps == null) continue; 781 782 // get existing properties as list of maps 783 784 for (Map<String, String> map : mlSetting.getValue()) { 785 // add nonexisting map (equals comparison for maps is used implicitly) 786 if (!newMaps.contains(map)) { 787 newMaps.add(map); 788 } 789 } 790 mainpref.putListOfStructs(entry.getKey(), newMaps); 786 791 } 787 mainpref.putCollection(entry.getKey(), newItems); 788 } 789 790 // "lists" 791 for (Entry<String, List<List<String>>> entry : fragment.arrayProperties.entrySet()) { 792 } 793 } 794 795 /** 796 * Delete items from @param mainpref collections that match items from @param fragment collections 797 */ 798 private static void deletePreferenceValues(Preferences fragment, Preferences mainpref) { 799 800 for (Entry<String, Setting> entry : fragment.settingsMap.entrySet()) { 792 801 String key = entry.getKey(); 793 794 Collection<Collection<String>> newLists = getArray(mainpref, key, true); 795 if (newLists == null) continue; 796 797 for (Collection<String> list : entry.getValue()) { 798 // add nonexisting list (equals comparison for lists is used implicitly) 799 if (!newLists.contains(list)) { 800 newLists.add(list); 802 if (entry.getValue() instanceof StringSetting) { 803 StringSetting sSetting = (StringSetting) entry.getValue(); 804 // if mentioned value found, delete it 805 if (sSetting.equals(mainpref.settingsMap.get(key))) { 806 mainpref.put(key, null); 801 807 } 808 } else if (entry.getValue() instanceof ListSetting) { 809 ListSetting lSetting = (ListSetting) entry.getValue(); 810 Collection<String> newItems = getCollection(mainpref, key, true); 811 if (newItems == null) continue; 812 813 // remove mentioned items from collection 814 for (String item : lSetting.getValue()) { 815 log("Deleting preferences: from list %s: %s\n", key, item); 816 newItems.remove(item); 817 } 818 mainpref.putCollection(entry.getKey(), newItems); 819 } else if (entry.getValue() instanceof ListListSetting) { 820 ListListSetting llSetting = (ListListSetting) entry.getValue(); 821 Collection<Collection<String>> newLists = getArray(mainpref, key, true); 822 if (newLists == null) continue; 823 824 // if items are found in one of lists, remove that list! 825 Iterator<Collection<String>> listIterator = newLists.iterator(); 826 while (listIterator.hasNext()) { 827 Collection<String> list = listIterator.next(); 828 for (Collection<String> removeList : llSetting.getValue()) { 829 if (list.containsAll(removeList)) { 830 // remove current list, because it matches search criteria 831 log("Deleting preferences: list from lists %s: %s\n", key, list); 832 listIterator.remove(); 833 } 834 } 835 } 836 837 mainpref.putArray(key, newLists); 838 } else if (entry.getValue() instanceof MapListSetting) { 839 MapListSetting mlSetting = (MapListSetting) entry.getValue(); 840 List<Map<String, String>> newMaps = getListOfStructs(mainpref, key, true); 841 if (newMaps == null) continue; 842 843 Iterator<Map<String, String>> mapIterator = newMaps.iterator(); 844 while (mapIterator.hasNext()) { 845 Map<String, String> map = mapIterator.next(); 846 for (Map<String, String> removeMap : mlSetting.getValue()) { 847 if (map.entrySet().containsAll(removeMap.entrySet())) { 848 // the map contain all mentioned key-value pair, so it should be deleted from "maps" 849 log("Deleting preferences: deleting map from maps %s: %s\n", key, map); 850 mapIterator.remove(); 851 } 852 } 853 } 854 mainpref.putListOfStructs(entry.getKey(), newMaps); 802 855 } 803 mainpref.putArray(entry.getKey(), newLists); 804 } 805 806 /// "maps" 807 for (Entry<String, List<Map<String, String>>> entry : fragment.listOfStructsProperties.entrySet()) { 808 String key = entry.getKey(); 809 810 List<Map<String, String>> newMaps = getListOfStructs(mainpref, key, true); 811 if (newMaps == null) continue; 812 813 // get existing properties as list of maps 814 815 for (Map<String, String> map : entry.getValue()) { 816 // add nonexisting map (equals comparison for maps is used implicitly) 817 if (!newMaps.contains(map)) { 818 newMaps.add(map); 819 } 820 } 821 mainpref.putListOfStructs(entry.getKey(), newMaps); 822 } 823 } 824 825 /** 826 * Delete items from @param mainpref collections that match items from @param fragment collections 827 */ 828 private static void deletePreferenceValues(Preferences fragment, Preferences mainpref) { 829 830 831 // normal prefs 832 for (Entry<String, String> entry : fragment.properties.entrySet()) { 833 // if mentioned value found, delete it 834 if (entry.getValue().equals(mainpref.properties.get(entry.getKey()))) { 835 mainpref.put(entry.getKey(), null); 836 } 837 } 838 839 // "list" 840 for (Entry<String, List<String>> entry : fragment.collectionProperties.entrySet()) { 841 String key = entry.getKey(); 842 843 Collection<String> newItems = getCollection(mainpref, key, true); 844 if (newItems == null) continue; 845 846 // remove mentioned items from collection 847 for (String item : entry.getValue()) { 848 log("Deleting preferences: from list %s: %s\n", key, item); 849 newItems.remove(item); 850 } 851 mainpref.putCollection(entry.getKey(), newItems); 852 } 853 854 // "lists" 855 for (Entry<String, List<List<String>>> entry : fragment.arrayProperties.entrySet()) { 856 String key = entry.getKey(); 857 858 859 Collection<Collection<String>> newLists = getArray(mainpref, key, true); 860 if (newLists == null) continue; 861 862 // if items are found in one of lists, remove that list! 863 Iterator<Collection<String>> listIterator = newLists.iterator(); 864 while (listIterator.hasNext()) { 865 Collection<String> list = listIterator.next(); 866 for (Collection<String> removeList : entry.getValue()) { 867 if (list.containsAll(removeList)) { 868 // remove current list, because it matches search criteria 869 log("Deleting preferences: list from lists %s: %s\n", key, list); 870 listIterator.remove(); 871 } 872 } 873 } 874 875 mainpref.putArray(entry.getKey(), newLists); 876 } 877 878 /// "maps" 879 for (Entry<String, List<Map<String, String>>> entry : fragment.listOfStructsProperties.entrySet()) { 880 String key = entry.getKey(); 881 882 List<Map<String, String>> newMaps = getListOfStructs(mainpref, key, true); 883 if (newMaps == null) continue; 884 885 Iterator<Map<String, String>> mapIterator = newMaps.iterator(); 886 while (mapIterator.hasNext()) { 887 Map<String, String> map = mapIterator.next(); 888 for (Map<String, String> removeMap : entry.getValue()) { 889 if (map.entrySet().containsAll(removeMap.entrySet())) { 890 // the map contain all mentioned key-value pair, so it should be deleted from "maps" 891 log("Deleting preferences: deleting map from maps %s: %s\n", key, map); 892 mapIterator.remove(); 893 } 894 } 895 } 896 mainpref.putListOfStructs(entry.getKey(), newMaps); 897 } 898 } 856 } 857 } 899 858 900 859 private static void deletePreferenceKeyByPattern(String pattern, Preferences pref) { … … 904 863 if (key.matches(pattern)) { 905 864 log("Deleting preferences: deleting key from preferences: " + key); 906 pref.putSetting(key, entry.getValue().getNullInstance());865 pref.putSetting(key, null); 907 866 } 908 867 } … … 913 872 if (allSettings.containsKey(key)) { 914 873 log("Deleting preferences: deleting key from preferences: " + key); 915 pref.putSetting(key, allSettings.get(key).getNullInstance());874 pref.putSetting(key, null); 916 875 } 917 876 } 918 877 919 878 private static Collection<String> getCollection(Preferences mainpref, String key, boolean warnUnknownDefault) { 920 Collection<String> existing = mainpref.collectionProperties.get(key); 921 Collection<String> defaults = mainpref.collectionDefaults.get(key); 922 879 ListSetting existing = Utils.cast(mainpref.settingsMap.get(key), ListSetting.class); 880 ListSetting defaults = Utils.cast(mainpref.defaultsMap.get(key), ListSetting.class); 923 881 if (existing == null && defaults == null) { 924 882 if (warnUnknownDefault) defaultUnknownWarning(key); 925 883 return null; 926 884 } 927 return (existing != null) 928 ? new ArrayList<String>(existing) : new ArrayList<String>(defaults); 885 if (existing != null) 886 return new ArrayList<String>(existing.getValue()); 887 else 888 return defaults.getValue() == null ? null : new ArrayList<String>(defaults.getValue()); 929 889 } 930 890 931 891 private static Collection<Collection<String>> getArray(Preferences mainpref, String key, boolean warnUnknownDefault) { 932 Collection<List<String>> existing = mainpref.arrayProperties.get(key);933 Collection<List<String>> defaults = mainpref.arrayDefaults.get(key);892 ListListSetting existing = Utils.cast(mainpref.settingsMap.get(key), ListListSetting.class); 893 ListListSetting defaults = Utils.cast(mainpref.defaultsMap.get(key), ListListSetting.class); 934 894 935 895 if (existing == null && defaults == null) { … … 937 897 return null; 938 898 } 939 940 return (existing != null) 941 ? new ArrayList<Collection<String>>(existing) : new ArrayList<Collection<String>>(defaults); 899 if (existing != null) 900 return new ArrayList<Collection<String>>(existing.getValue()); 901 else 902 return defaults.getValue() == null ? null : new ArrayList<Collection<String>>(defaults.getValue()); 942 903 } 943 904 944 905 private static List<Map<String, String>> getListOfStructs(Preferences mainpref, String key, boolean warnUnknownDefault) { 945 Collection<Map<String, String>> existing = mainpref.listOfStructsProperties.get(key);946 Collection<Map<String, String>> defaults = mainpref.listOfStructsDefaults.get(key);906 MapListSetting existing = Utils.cast(mainpref.settingsMap.get(key), MapListSetting.class); 907 MapListSetting defaults = Utils.cast(mainpref.settingsMap.get(key), MapListSetting.class); 947 908 948 909 if (existing == null && defaults == null) { … … 951 912 } 952 913 953 return (existing != null) 954 ? new ArrayList<Map<String, String>>(existing) : new ArrayList<Map<String, String>>(defaults); 914 if (existing != null) 915 return new ArrayList<Map<String, String>>(existing.getValue()); 916 else 917 return defaults.getValue() == null ? null : new ArrayList<Map<String, String>>(defaults.getValue()); 955 918 } 956 919 … … 965 928 966 929 private static void showPrefs(Preferences tmpPref) { 967 Main.info("properties: " + tmpPref.properties); 968 Main.info("collections: " + tmpPref.collectionProperties); 969 Main.info("arrays: " + tmpPref.arrayProperties); 970 Main.info("maps: " + tmpPref.listOfStructsProperties); 930 Main.info("properties: " + tmpPref.settingsMap); 971 931 } 972 932 … … 1037 997 Map<String, List<Map<String, String>>> listmapMap = (SortedMap<String, List<Map<String,String>>>) engine.get("listmapMap"); 1038 998 1039 tmpPref.properties.clear(); 1040 tmpPref.collectionProperties.clear(); 1041 tmpPref.arrayProperties.clear(); 1042 tmpPref.listOfStructsProperties.clear(); 1043 999 tmpPref.settingsMap.clear(); 1000 1001 Map<String, Setting> tmp = new HashMap<String, Setting>(); 1044 1002 for (Entry<String, String> e : stringMap.entrySet()) { 1045 if (e.getValue().equals( tmpPref.defaults.get(e.getKey())) ) continue; 1046 tmpPref.properties.put(e.getKey(), e.getValue()); 1047 } 1048 1003 tmp.put(e.getKey(), new StringSetting(e.getValue())); 1004 } 1049 1005 for (Entry<String, List<String>> e : listMap.entrySet()) { 1050 if (Preferences.equalCollection(e.getValue(), tmpPref.collectionDefaults.get(e.getKey()))) continue; 1051 tmpPref.collectionProperties.put(e.getKey(), e.getValue()); 1006 tmp.put(e.getKey(), new ListSetting(e.getValue())); 1052 1007 } 1053 1008 1054 1009 for (Entry<String, List<Collection<String>>> e : listlistMap.entrySet()) { 1055 if (Preferences.equalArray(e.getValue(), tmpPref.arrayDefaults.get(e.getKey()))) continue;1056 1010 @SuppressWarnings("unchecked") List<List<String>> value = (List)e.getValue(); 1057 tmpPref.arrayProperties.put(e.getKey(), value); 1058 } 1059 1011 tmp.put(e.getKey(), new ListListSetting(value)); 1012 } 1060 1013 for (Entry<String, List<Map<String, String>>> e : listmapMap.entrySet()) { 1061 if (Preferences.equalListOfStructs(e.getValue(), tmpPref.listOfStructsDefaults.get(e.getKey()))) continue; 1062 tmpPref.listOfStructsProperties.put(e.getKey(), e.getValue()); 1014 tmp.put(e.getKey(), new MapListSetting(e.getValue())); 1015 } 1016 for (Entry<String, Setting> e : tmp.entrySet()) { 1017 if (e.getValue().equals(tmpPref.defaultsMap.get(e.getKey()))) continue; 1018 tmpPref.settingsMap.put(e.getKey(), e.getValue()); 1063 1019 } 1064 1020 } … … 1079 1035 1080 1036 if (includeDefaults) { 1081 stringMap.putAll(tmpPref.defaults); 1082 listMap.putAll(tmpPref.collectionDefaults); 1083 listlistMap.putAll(tmpPref.arrayDefaults); 1084 listmapMap.putAll(tmpPref.listOfStructsDefaults); 1085 } 1086 1087 while (stringMap.values().remove(null)); 1088 while (listMap.values().remove(null)); 1089 while (listlistMap.values().remove(null)); 1090 while (listmapMap.values().remove(null)); 1091 1092 stringMap.putAll(tmpPref.properties); 1093 listMap.putAll(tmpPref.collectionProperties); 1094 listlistMap.putAll(tmpPref.arrayProperties); 1095 listmapMap.putAll(tmpPref.listOfStructsProperties); 1037 for (Map.Entry<String, Setting> e: tmpPref.defaultsMap.entrySet()) { 1038 Setting setting = e.getValue(); 1039 if (setting instanceof StringSetting) { 1040 stringMap.put(e.getKey(), ((StringSetting) setting).getValue()); 1041 } else if (setting instanceof ListSetting) { 1042 listMap.put(e.getKey(), ((ListSetting) setting).getValue()); 1043 } else if (setting instanceof ListListSetting) { 1044 listlistMap.put(e.getKey(), ((ListListSetting) setting).getValue()); 1045 } else if (setting instanceof MapListSetting) { 1046 listmapMap.put(e.getKey(), ((MapListSetting) setting).getValue()); 1047 } 1048 } 1049 } 1050 Iterator<Map.Entry<String, Setting>> it = tmpPref.settingsMap.entrySet().iterator(); 1051 while (it.hasNext()) { 1052 Map.Entry<String, Setting> e = it.next(); 1053 if (e.getValue().getValue() == null) { 1054 it.remove(); 1055 } 1056 } 1057 1058 for (Map.Entry<String, Setting> e: tmpPref.settingsMap.entrySet()) { 1059 Setting setting = e.getValue(); 1060 if (setting instanceof StringSetting) { 1061 stringMap.put(e.getKey(), ((StringSetting) setting).getValue()); 1062 } else if (setting instanceof ListSetting) { 1063 listMap.put(e.getKey(), ((ListSetting) setting).getValue()); 1064 } else if (setting instanceof ListListSetting) { 1065 listlistMap.put(e.getKey(), ((ListListSetting) setting).getValue()); 1066 } else if (setting instanceof MapListSetting) { 1067 listmapMap.put(e.getKey(), ((MapListSetting) setting).getValue()); 1068 } 1069 } 1096 1070 1097 1071 engine.put("stringMap", stringMap); -
trunk/src/org/openstreetmap/josm/data/Preferences.java
r6552 r6578 51 51 import org.openstreetmap.josm.io.MirroredInputStream; 52 52 import org.openstreetmap.josm.io.XmlWriter; 53 import org.openstreetmap.josm.tools.CheckParameterUtil; 53 54 import org.openstreetmap.josm.tools.ColorHelper; 54 55 import org.openstreetmap.josm.tools.Utils; … … 88 89 89 90 /** 90 * Map the property name to strings. Does not contain null or "" values. 91 */ 92 protected final SortedMap<String, String> properties = new TreeMap<String, String>(); 93 /** Map of defaults, can contain null values */ 94 protected final SortedMap<String, String> defaults = new TreeMap<String, String>(); 91 * Map the setting name to the current value of the setting. 92 * The map must not contain null as key or value. The mapped setting objects 93 * must not have a null value. 94 */ 95 protected final SortedMap<String, Setting> settingsMap = new TreeMap<String, Setting>(); 96 /** 97 * Map the setting name to the default value of the setting. 98 * The map must not contain null as key or value. The value of the mapped 99 * setting objects can be null. 100 */ 101 protected final SortedMap<String, Setting> defaultsMap = new TreeMap<String, Setting>(); 102 // maps color keys to human readable color name 95 103 protected final SortedMap<String, String> colornames = new TreeMap<String, String>(); 96 104 97 /** Mapping for list settings. Must not contain null values */ 98 protected final SortedMap<String, List<String>> collectionProperties = new TreeMap<String, List<String>>(); 99 /** Defaults, can contain null values */ 100 protected final SortedMap<String, List<String>> collectionDefaults = new TreeMap<String, List<String>>(); 101 102 protected final SortedMap<String, List<List<String>>> arrayProperties = new TreeMap<String, List<List<String>>>(); 103 protected final SortedMap<String, List<List<String>>> arrayDefaults = new TreeMap<String, List<List<String>>>(); 104 105 protected final SortedMap<String, List<Map<String,String>>> listOfStructsProperties = new TreeMap<String, List<Map<String,String>>>(); 106 protected final SortedMap<String, List<Map<String,String>>> listOfStructsDefaults = new TreeMap<String, List<Map<String,String>>>(); 107 108 /** 109 * Interface for a preference value 105 /** 106 * Interface for a preference value. 107 * 108 * Implementations must provide a proper <code>equals</code> method. 110 109 * 111 110 * @param <T> the data type for the value … … 118 117 */ 119 118 T getValue(); 119 120 /** 121 * Check if the value of this Setting object is equal to the given value. 122 * @param otherVal the other value 123 * @return true if the values are equal 124 */ 125 boolean equalVal(T otherVal); 126 127 /** 128 * Clone the current object. 129 * @return an identical copy of the current object 130 */ 131 Setting<T> copy(); 120 132 121 133 /** … … 142 154 */ 143 155 abstract public static class AbstractSetting<T> implements Setting<T> { 144 pr ivatefinal T value;156 protected final T value; 145 157 /** 146 158 * Constructs a new {@code AbstractSetting} with the given value … … 169 181 super(value); 170 182 } 183 @Override public boolean equalVal(String otherVal) { 184 if (value == null) return otherVal == null; 185 return value.equals(otherVal); 186 } 187 @Override public StringSetting copy() { 188 return new StringSetting(value); 189 } 171 190 @Override public void visit(SettingVisitor visitor) { 172 191 visitor.visit(this); … … 174 193 @Override public StringSetting getNullInstance() { 175 194 return new StringSetting(null); 195 } 196 @Override 197 public boolean equals(Object other) { 198 if (!(other instanceof StringSetting)) return false; 199 return equalVal(((StringSetting) other).getValue()); 176 200 } 177 201 } … … 187 211 public ListSetting(List<String> value) { 188 212 super(value); 213 consistencyTest(); 214 } 215 /** 216 * Convenience factory method. 217 * @param value the value 218 * @return a corresponding ListSetting object 219 */ 220 public static ListSetting create(Collection<String> value) { 221 return new ListSetting(value == null ? null : Collections.unmodifiableList(new ArrayList<String>(value))); 222 } 223 @Override public boolean equalVal(List<String> otherVal) { 224 return equalCollection(value, otherVal); 225 } 226 public static boolean equalCollection(Collection<String> a, Collection<String> b) { 227 if (a == null) return b == null; 228 if (b == null) return false; 229 if (a.size() != b.size()) return false; 230 Iterator<String> itA = a.iterator(); 231 Iterator<String> itB = b.iterator(); 232 while (itA.hasNext()) { 233 String aStr = itA.next(); 234 String bStr = itB.next(); 235 if (!Utils.equal(aStr,bStr)) return false; 236 } 237 return true; 238 } 239 @Override public ListSetting copy() { 240 return ListSetting.create(value); 241 } 242 private void consistencyTest() { 243 if (value != null && value.contains(null)) 244 throw new RuntimeException("Error: Null as list element in preference setting"); 189 245 } 190 246 @Override public void visit(SettingVisitor visitor) { … … 193 249 @Override public ListSetting getNullInstance() { 194 250 return new ListSetting(null); 251 } 252 @Override 253 public boolean equals(Object other) { 254 if (!(other instanceof ListSetting)) return false; 255 return equalVal(((ListSetting) other).getValue()); 195 256 } 196 257 } … … 206 267 public ListListSetting(List<List<String>> value) { 207 268 super(value); 269 consistencyTest(); 270 } 271 /** 272 * Convenience factory method. 273 * @param value the value 274 * @return a corresponding ListListSetting object 275 */ 276 public static ListListSetting create(Collection<Collection<String>> value) { 277 if (value != null) { 278 List<List<String>> valueList = new ArrayList<List<String>>(value.size()); 279 for (Collection<String> lst : value) { 280 valueList.add(new ArrayList<String>(lst)); 281 } 282 return new ListListSetting(valueList); 283 } 284 return new ListListSetting(null); 285 } 286 @Override public boolean equalVal(List<List<String>> otherVal) { 287 if (value == null) return otherVal == null; 288 if (otherVal == null) return false; 289 if (value.size() != otherVal.size()) return false; 290 Iterator<List<String>> itA = value.iterator(); 291 Iterator<List<String>> itB = otherVal.iterator(); 292 while (itA.hasNext()) { 293 if (!ListSetting.equalCollection(itA.next(), itB.next())) return false; 294 } 295 return true; 296 } 297 @Override public ListListSetting copy() { 298 if (value == null) return new ListListSetting(null); 299 300 List<List<String>> copy = new ArrayList<List<String>>(value.size()); 301 for (Collection<String> lst : value) { 302 List<String> lstCopy = new ArrayList<String>(lst); 303 copy.add(Collections.unmodifiableList(lstCopy)); 304 } 305 return new ListListSetting(Collections.unmodifiableList(copy)); 306 } 307 private void consistencyTest() { 308 if (value == null) return; 309 if (value.contains(null)) throw new RuntimeException("Error: Null as list element in preference setting"); 310 for (Collection<String> lst : value) { 311 if (lst.contains(null)) throw new RuntimeException("Error: Null as inner list element in preference setting"); 312 } 208 313 } 209 314 @Override public void visit(SettingVisitor visitor) { … … 212 317 @Override public ListListSetting getNullInstance() { 213 318 return new ListListSetting(null); 319 } 320 @Override 321 public boolean equals(Object other) { 322 if (!(other instanceof ListListSetting)) return false; 323 return equalVal(((ListListSetting) other).getValue()); 214 324 } 215 325 } … … 225 335 public MapListSetting(List<Map<String, String>> value) { 226 336 super(value); 337 consistencyTest(); 338 } 339 @Override public boolean equalVal(List<Map<String, String>> otherVal) { 340 if (value == null) return otherVal == null; 341 if (otherVal == null) return false; 342 if (value.size() != otherVal.size()) return false; 343 Iterator<Map<String, String>> itA = value.iterator(); 344 Iterator<Map<String, String>> itB = otherVal.iterator(); 345 while (itA.hasNext()) { 346 if (!equalMap(itA.next(), itB.next())) return false; 347 } 348 return true; 349 } 350 private static boolean equalMap(Map<String, String> a, Map<String, String> b) { 351 if (a == null) return b == null; 352 if (b == null) return false; 353 if (a.size() != b.size()) return false; 354 for (Entry<String, String> e : a.entrySet()) { 355 if (!Utils.equal(e.getValue(), b.get(e.getKey()))) return false; 356 } 357 return true; 358 } 359 @Override public MapListSetting copy() { 360 if (value == null) return new MapListSetting(null); 361 List<Map<String, String>> copy = new ArrayList<Map<String, String>>(value.size()); 362 for (Map<String, String> map : value) { 363 Map<String, String> mapCopy = new LinkedHashMap<String,String>(map); 364 copy.add(Collections.unmodifiableMap(mapCopy)); 365 } 366 return new MapListSetting(Collections.unmodifiableList(copy)); 367 } 368 private void consistencyTest() { 369 if (value == null) return; 370 if (value.contains(null)) throw new RuntimeException("Error: Null as list element in preference setting"); 371 for (Map<String, String> map : value) { 372 if (map.keySet().contains(null)) throw new RuntimeException("Error: Null as map key in preference setting"); 373 if (map.values().contains(null)) throw new RuntimeException("Error: Null as map value in preference setting"); 374 } 227 375 } 228 376 @Override public void visit(SettingVisitor visitor) { … … 231 379 @Override public MapListSetting getNullInstance() { 232 380 return new MapListSetting(null); 381 } 382 @Override 383 public boolean equals(Object other) { 384 if (!(other instanceof MapListSetting)) return false; 385 return equalVal(((MapListSetting) other).getValue()); 233 386 } 234 387 } … … 241 394 } 242 395 243 public interface PreferenceChangeEvent <T>{396 public interface PreferenceChangeEvent { 244 397 String getKey(); 245 Setting <T>getOldValue();246 Setting <T>getNewValue();398 Setting getOldValue(); 399 Setting getNewValue(); 247 400 } 248 401 … … 251 404 } 252 405 253 private static class DefaultPreferenceChangeEvent <T> implements PreferenceChangeEvent<T>{406 private static class DefaultPreferenceChangeEvent implements PreferenceChangeEvent { 254 407 private final String key; 255 private final Setting <T>oldValue;256 private final Setting <T>newValue;257 258 public DefaultPreferenceChangeEvent(String key, Setting <T> oldValue, Setting<T>newValue) {408 private final Setting oldValue; 409 private final Setting newValue; 410 411 public DefaultPreferenceChangeEvent(String key, Setting oldValue, Setting newValue) { 259 412 this.key = key; 260 413 this.oldValue = oldValue; … … 267 420 } 268 421 @Override 269 public Setting <T>getOldValue() {422 public Setting getOldValue() { 270 423 return oldValue; 271 424 } 272 425 @Override 273 public Setting <T>getNewValue() {426 public Setting getNewValue() { 274 427 return newValue; 275 428 } … … 294 447 } 295 448 296 protected <T> void firePreferenceChanged(String key, Setting<T> oldValue, Setting<T>newValue) {297 PreferenceChangeEvent <T> evt = new DefaultPreferenceChangeEvent<T>(key, oldValue, newValue);449 protected void firePreferenceChanged(String key, Setting oldValue, Setting newValue) { 450 PreferenceChangeEvent evt = new DefaultPreferenceChangeEvent(key, oldValue, newValue); 298 451 for (PreferenceChangedListener l : listeners) { 299 452 l.preferenceChanged(evt); … … 424 577 */ 425 578 synchronized public String get(final String key) { 426 putDefault(key, null); 427 if (!properties.containsKey(key)) 428 return ""; 429 return properties.get(key); 579 String value = get(key, null); 580 return value == null ? "" : value; 430 581 } 431 582 … … 439 590 */ 440 591 synchronized public String get(final String key, final String def) { 441 putDefault(key, def); 442 final String prop = properties.get(key); 443 if (prop == null || prop.isEmpty()) 444 return def; 445 return prop; 592 return getSetting(key, new StringSetting(def), StringSetting.class).getValue(); 446 593 } 447 594 448 595 synchronized public Map<String, String> getAllPrefix(final String prefix) { 449 596 final Map<String,String> all = new TreeMap<String,String>(); 450 for (final Entry<String,S tring> e : properties.entrySet()) {451 if (e.getKey().startsWith(prefix) ) {452 all.put(e.getKey(), e.getValue());597 for (final Entry<String,Setting> e : settingsMap.entrySet()) { 598 if (e.getKey().startsWith(prefix) && (e.getValue() instanceof StringSetting)) { 599 all.put(e.getKey(), ((StringSetting) e.getValue()).getValue()); 453 600 } 454 601 } … … 458 605 synchronized public List<String> getAllPrefixCollectionKeys(final String prefix) { 459 606 final List<String> all = new LinkedList<String>(); 460 for ( final String e : collectionProperties.keySet()) {461 if (e .startsWith(prefix)) {462 all.add(e );607 for (Map.Entry<String, Setting> entry : settingsMap.entrySet()) { 608 if (entry.getKey().startsWith(prefix) && entry.getValue() instanceof ListSetting) { 609 all.add(entry.getKey()); 463 610 } 464 611 } … … 468 615 synchronized public Map<String, String> getAllColors() { 469 616 final Map<String,String> all = new TreeMap<String,String>(); 470 for (final Entry<String,String> e : defaults.entrySet()) { 471 if (e.getKey().startsWith("color.") && e.getValue() != null) { 472 all.put(e.getKey().substring(6), e.getValue()); 473 } 474 } 475 for (final Entry<String,String> e : properties.entrySet()) { 476 if (e.getKey().startsWith("color.")) { 477 all.put(e.getKey().substring(6), e.getValue()); 617 for (final Entry<String,Setting> e : defaultsMap.entrySet()) { 618 if (e.getKey().startsWith("color.") && e.getValue() instanceof StringSetting) { 619 StringSetting d = (StringSetting) e.getValue(); 620 if (d.getValue() != null) { 621 all.put(e.getKey().substring(6), d.getValue()); 622 } 623 } 624 } 625 for (final Entry<String,Setting> e : settingsMap.entrySet()) { 626 if (e.getKey().startsWith("color.") && (e.getValue() instanceof StringSetting)) { 627 all.put(e.getKey().substring(6), ((StringSetting) e.getValue()).getValue()); 478 628 } 479 629 } … … 481 631 } 482 632 483 synchronized public Map<String, String> getDefaults() {484 return defaults;485 }486 487 synchronized public void putDefault(final String key, final String def) {488 if(!defaults.containsKey(key) || defaults.get(key) == null) {489 defaults.put(key, def);490 } else if(def != null && !defaults.get(key).equals(def)) {491 Main.info("Defaults for " + key + " differ: " + def + " != " + defaults.get(key));492 }493 }494 495 633 synchronized public boolean getBoolean(final String key) { 496 putDefault(key, null);497 return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : false;634 String s = get(key, null); 635 return s == null ? false : Boolean.parseBoolean(s); 498 636 } 499 637 500 638 synchronized public boolean getBoolean(final String key, final boolean def) { 501 putDefault(key, Boolean.toString(def)); 502 return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : def; 639 return Boolean.parseBoolean(get(key, Boolean.toString(def))); 503 640 } 504 641 505 642 synchronized public boolean getBoolean(final String key, final String specName, final boolean def) { 506 putDefault(key, Boolean.toString(def));643 boolean generic = getBoolean(key, def); 507 644 String skey = key+"."+specName; 508 if(properties.containsKey(skey))509 return Boolean.parseBoolean(properties.get(skey));510 return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : def;511 }512 513 /**514 * Set a value for a certain setting. The changed setting is saved 515 * to the preference file immediately. Due to caching mechanisms on modern516 * operating systems and hardware, this shouldn't be a performance problem.645 Setting prop = settingsMap.get(skey); 646 if (prop instanceof StringSetting) 647 return Boolean.parseBoolean(((StringSetting)prop).getValue()); 648 else 649 return generic; 650 } 651 652 /** 653 * Set a value for a certain setting. 517 654 * @param key the unique identifier for the setting 518 655 * @param value the value of the setting. Can be null or "" which both removes 519 656 * the key-value entry. 520 * @return if true,something has changed (i.e. value is different than before)657 * @return true, if something has changed (i.e. value is different than before) 521 658 */ 522 659 public boolean put(final String key, String value) { 523 boolean changed = false; 524 String oldValue = null; 525 526 synchronized (this) { 527 oldValue = properties.get(key); 528 if(value != null && value.length() == 0) { 529 value = null; 530 } 531 // value is the same as before - no need to save anything 532 boolean equalValue = oldValue != null && oldValue.equals(value); 533 // The setting was previously unset and we are supposed to put a 534 // value that equals the default value. This is not necessary because 535 // the default value is the same throughout josm. In addition we like 536 // to have the possibility to change the default value from version 537 // to version, which would not work if we wrote it to the preference file. 538 boolean unsetIsDefault = oldValue == null && (value == null || value.equals(defaults.get(key))); 539 540 if (!(equalValue || unsetIsDefault)) { 541 if (value == null) { 542 properties.remove(key); 543 } else { 544 properties.put(key, value); 545 } 546 try { 547 save(); 548 } catch (IOException e) { 549 Main.warn(tr("Failed to persist preferences to ''{0}''", getPreferenceFile().getAbsoluteFile())); 550 } 551 changed = true; 552 } 553 } 554 if (changed) { 555 // Call outside of synchronized section in case some listener wait for other thread that wait for preference lock 556 firePreferenceChanged(key, new StringSetting(oldValue), new StringSetting(value)); 557 } 558 return changed; 660 if(value != null && value.length() == 0) { 661 value = null; 662 } 663 return putSetting(key, value == null ? null : new StringSetting(value)); 559 664 } 560 665 … … 618 723 619 724 public void load() throws Exception { 620 properties.clear();725 settingsMap.clear(); 621 726 if (!Main.applet) { 622 727 File pref = getPreferenceFile(); … … 708 813 709 814 public final void resetToDefault(){ 710 properties.clear();815 settingsMap.clear(); 711 816 } 712 817 … … 764 869 colornames.put(colKey, colName); 765 870 } 766 putDefault("color."+colKey, ColorHelper.color2html(def));767 871 String colStr = specName != null ? get("color."+specName) : ""; 768 872 if(colStr.isEmpty()) { 769 colStr = get("color."+colKey );873 colStr = get("color."+colKey, ColorHelper.color2html(def)); 770 874 } 771 875 return colStr.isEmpty() ? def : ColorHelper.html2color(colStr); … … 773 877 774 878 synchronized public Color getDefaultColor(String colKey) { 775 String colStr = defaults.get("color."+colKey); 879 StringSetting col = Utils.cast(defaultsMap.get("color."+colKey), StringSetting.class); 880 String colStr = col == null ? null : col.getValue(); 776 881 return colStr == null || colStr.isEmpty() ? null : ColorHelper.html2color(colStr); 777 882 } … … 782 887 783 888 synchronized public int getInteger(String key, int def) { 784 putDefault(key, Integer.toString(def)); 785 String v = get(key); 889 String v = get(key, Integer.toString(def)); 786 890 if(v.isEmpty()) 787 891 return def; … … 796 900 797 901 synchronized public int getInteger(String key, String specName, int def) { 798 putDefault(key, Integer.toString(def));799 902 String v = get(key+"."+specName); 800 903 if(v.isEmpty()) 801 v = get(key );904 v = get(key,Integer.toString(def)); 802 905 if(v.isEmpty()) 803 906 return def; … … 812 915 813 916 synchronized public long getLong(String key, long def) { 814 putDefault(key, Long.toString(def)); 815 String v = get(key); 917 String v = get(key, Long.toString(def)); 816 918 if(null == v) 817 919 return def; … … 826 928 827 929 synchronized public double getDouble(String key, double def) { 828 putDefault(key, Double.toString(def)); 829 String v = get(key); 930 String v = get(key, Double.toString(def)); 830 931 if(null == v) 831 932 return def; … … 847 948 */ 848 949 public Collection<String> getCollection(String key, Collection<String> def) { 849 putCollectionDefault(key, def == null ? null : new ArrayList<String>(def)); 850 Collection<String> prop = collectionProperties.get(key); 851 if (prop != null) 852 return prop; 853 else 854 return def; 950 return getSetting(key, ListSetting.create(def), ListSetting.class).getValue(); 855 951 } 856 952 … … 862 958 */ 863 959 public Collection<String> getCollection(String key) { 864 putCollectionDefault(key, null); 865 Collection<String> prop = collectionProperties.get(key); 866 if (prop != null) 867 return prop; 868 else 869 return Collections.emptyList(); 960 Collection<String> val = getCollection(key, null); 961 return val == null ? Collections.<String>emptyList() : val; 870 962 } 871 963 … … 876 968 } 877 969 878 public boolean putCollection(String key, Collection<String> value) { 879 List<String> oldValue = null; 880 List<String> valueCopy = null; 881 970 /** 971 * Set a value for a certain setting. The changed setting is saved 972 * to the preference file immediately. Due to caching mechanisms on modern 973 * operating systems and hardware, this shouldn't be a performance problem. 974 * @param key the unique identifier for the setting 975 * @param setting the value of the setting. In case it is null, the key-value 976 * entry will be removed. 977 * @return true, if something has changed (i.e. value is different than before) 978 */ 979 public boolean putSetting(final String key, Setting setting) { 980 CheckParameterUtil.ensureParameterNotNull(key); 981 if (setting != null && setting.getValue() == null) 982 throw new IllegalArgumentException("setting argument must not have null value"); 983 Setting settingOld; 984 Setting settingCopy = null; 882 985 synchronized (this) { 883 if (value == null) { 884 oldValue = collectionProperties.remove(key); 885 boolean changed = oldValue != null; 886 changed |= properties.remove(key) != null; 887 if (!changed) return false; 986 if (setting == null) { 987 settingOld = settingsMap.remove(key); 988 if (settingOld == null) 989 return false; 888 990 } else { 889 oldValue = collectionProperties.get(key); 890 if (equalCollection(value, oldValue)) return false; 891 Collection<String> defValue = collectionDefaults.get(key); 892 if (oldValue == null && equalCollection(value, defValue)) return false; 893 894 valueCopy = new ArrayList<String>(value); 895 if (valueCopy.contains(null)) throw new RuntimeException("Error: Null as list element in preference setting (key '"+key+"')"); 896 collectionProperties.put(key, Collections.unmodifiableList(valueCopy)); 991 settingOld = settingsMap.get(key); 992 if (setting.equals(settingOld)) 993 return false; 994 if (settingOld == null && setting.equals(defaultsMap.get(key))) 995 return false; 996 settingCopy = setting.copy(); 997 settingsMap.put(key, settingCopy); 897 998 } 898 999 try { … … 903 1004 } 904 1005 // Call outside of synchronized section in case some listener wait for other thread that wait for preference lock 905 firePreferenceChanged(key, new ListSetting(oldValue), new ListSetting(valueCopy));1006 firePreferenceChanged(key, settingOld, settingCopy); 906 1007 return true; 907 1008 } 908 1009 909 public static boolean equalCollection(Collection<String> a, Collection<String> b) { 910 if (a == null) return b == null; 911 if (b == null) return false; 912 if (a.size() != b.size()) return false; 913 Iterator<String> itA = a.iterator(); 914 Iterator<String> itB = b.iterator(); 915 while (itA.hasNext()) { 916 String aStr = itA.next(); 917 String bStr = itB.next(); 918 if (!Utils.equal(aStr,bStr)) return false; 919 } 920 return true; 1010 synchronized public Setting getSetting(String key, Setting def) { 1011 return getSetting(key, def, Setting.class); 1012 } 1013 1014 /** 1015 * Get settings value for a certain key and provide default a value. 1016 * @param <T> the setting type 1017 * @param key the identifier for the setting 1018 * @param def the default value. For each call of getSetting() with a given 1019 * key, the default value must be the same. <code>def</code> must not be 1020 * null, but the value of <code>def</code> can be null. 1021 * @param klass the setting type (same as T) 1022 * @return the corresponding value if the property has been set before, 1023 * def otherwise 1024 */ 1025 synchronized public <T extends Setting> T getSetting(String key, T def, Class<T> klass) { 1026 CheckParameterUtil.ensureParameterNotNull(key); 1027 CheckParameterUtil.ensureParameterNotNull(def); 1028 if (defaultsMap.containsKey(key) && !def.equals(defaultsMap.get(key))) { 1029 Main.info("Defaults for " + key + " differ: " + def + " != " + defaultsMap.get(key)); 1030 } 1031 defaultsMap.put(key, def.copy()); 1032 Setting prop = settingsMap.get(key); 1033 if (klass.isInstance(prop)) { 1034 @SuppressWarnings("unchecked") 1035 T prop_cast = (T) prop; 1036 return prop_cast; 1037 } else { 1038 return def; 1039 } 1040 } 1041 1042 public boolean putCollection(String key, Collection<String> value) { 1043 return putSetting(key, value == null ? null : ListSetting.create(value)); 921 1044 } 922 1045 … … 935 1058 } 936 1059 937 synchronized private void putCollectionDefault(String key, List<String> val) {938 collectionDefaults.put(key, val);939 }940 941 1060 /** 942 1061 * Used to read a 2-dimensional array of strings from the preference file. 943 * If not a single entry could be found, defis returned.1062 * If not a single entry could be found, <code>def</code> is returned. 944 1063 */ 945 1064 synchronized public Collection<Collection<String>> getArray(String key, Collection<Collection<String>> def) { 946 if (def != null) { 947 List<List<String>> defCopy = new ArrayList<List<String>>(def.size()); 948 for (Collection<String> lst : def) { 949 defCopy.add(Collections.unmodifiableList(new ArrayList<String>(lst))); 950 } 951 putArrayDefault(key, Collections.unmodifiableList(defCopy)); 952 } else { 953 putArrayDefault(key, null); 954 } 955 List<List<String>> prop = arrayProperties.get(key); 956 if (prop != null) { 957 @SuppressWarnings({ "unchecked", "rawtypes" }) 958 Collection<Collection<String>> prop_cast = (Collection) prop; 959 return prop_cast; 960 } else 961 return def; 1065 ListListSetting val = getSetting(key, ListListSetting.create(def), ListListSetting.class); 1066 @SuppressWarnings({ "unchecked", "rawtypes" }) 1067 Collection<Collection<String>> val_cast = (Collection) val.getValue(); 1068 return val_cast; 962 1069 } 963 1070 964 1071 public Collection<Collection<String>> getArray(String key) { 965 putArrayDefault(key, null); 966 List<List<String>> prop = arrayProperties.get(key); 967 if (prop != null) { 968 @SuppressWarnings({ "unchecked", "rawtypes" }) 969 Collection<Collection<String>> prop_cast = (Collection) prop; 970 return prop_cast; 971 } else 972 return Collections.emptyList(); 1072 Collection<Collection<String>> res = getArray(key, null); 1073 return res == null ? Collections.<Collection<String>>emptyList() : res; 973 1074 } 974 1075 975 1076 public boolean putArray(String key, Collection<Collection<String>> value) { 976 List<List<String>> oldValue = null; 977 List<List<String>> valueCopy = null; 978 979 synchronized (this) { 980 oldValue = arrayProperties.get(key); 981 if (value == null) { 982 if (arrayProperties.remove(key) != null) return false; 983 } else { 984 if (equalArray(value, oldValue)) return false; 985 986 List<List<String>> defValue = arrayDefaults.get(key); 987 if (oldValue == null && equalArray(value, defValue)) return false; 988 989 valueCopy = new ArrayList<List<String>>(value.size()); 990 if (valueCopy.contains(null)) throw new RuntimeException("Error: Null as list element in preference setting (key '"+key+"')"); 991 for (Collection<String> lst : value) { 992 List<String> lstCopy = new ArrayList<String>(lst); 993 if (lstCopy.contains(null)) throw new RuntimeException("Error: Null as inner list element in preference setting (key '"+key+"')"); 994 valueCopy.add(Collections.unmodifiableList(lstCopy)); 995 } 996 arrayProperties.put(key, Collections.unmodifiableList(valueCopy)); 997 } 998 try { 999 save(); 1000 } catch (IOException e){ 1001 Main.warn(tr("Failed to persist preferences to ''{0}''", getPreferenceFile().getAbsoluteFile())); 1002 } 1003 } 1004 // Call outside of synchronized section in case some listener wait for other thread that wait for preference lock 1005 firePreferenceChanged(key, new ListListSetting(oldValue), new ListListSetting(valueCopy)); 1006 return true; 1007 } 1008 1009 public static boolean equalArray(Collection<Collection<String>> a, Collection<List<String>> b) { 1010 if (a == null) return b == null; 1011 if (b == null) return false; 1012 if (a.size() != b.size()) return false; 1013 Iterator<Collection<String>> itA = a.iterator(); 1014 Iterator<List<String>> itB = b.iterator(); 1015 while (itA.hasNext()) { 1016 if (!equalCollection(itA.next(), itB.next())) return false; 1017 } 1018 return true; 1019 } 1020 1021 synchronized private void putArrayDefault(String key, List<List<String>> val) { 1022 arrayDefaults.put(key, val); 1077 return putSetting(key, value == null ? null : ListListSetting.create(value)); 1023 1078 } 1024 1079 1025 1080 public Collection<Map<String, String>> getListOfStructs(String key, Collection<Map<String, String>> def) { 1026 if (def != null) { 1027 List<Map<String, String>> defCopy = new ArrayList<Map<String, String>>(def.size()); 1028 for (Map<String, String> map : def) { 1029 defCopy.add(Collections.unmodifiableMap(new LinkedHashMap<String,String>(map))); 1030 } 1031 putListOfStructsDefault(key, Collections.unmodifiableList(defCopy)); 1032 } else { 1033 putListOfStructsDefault(key, null); 1034 } 1035 Collection<Map<String, String>> prop = listOfStructsProperties.get(key); 1036 if (prop != null) 1037 return prop; 1038 else 1039 return def; 1081 return getSetting(key, new MapListSetting(def == null ? null : new ArrayList<Map<String, String>>(def)), MapListSetting.class).getValue(); 1040 1082 } 1041 1083 1042 1084 public boolean putListOfStructs(String key, Collection<Map<String, String>> value) { 1043 1044 List<Map<String, String>> oldValue; 1045 List<Map<String, String>> valueCopy = null; 1046 1047 synchronized (this) { 1048 oldValue = listOfStructsProperties.get(key); 1049 if (value == null) { 1050 if (listOfStructsProperties.remove(key) != null) return false; 1051 } else { 1052 if (equalListOfStructs(oldValue, value)) return false; 1053 1054 List<Map<String, String>> defValue = listOfStructsDefaults.get(key); 1055 if (oldValue == null && equalListOfStructs(value, defValue)) return false; 1056 1057 valueCopy = new ArrayList<Map<String, String>>(value.size()); 1058 if (valueCopy.contains(null)) throw new RuntimeException("Error: Null as list element in preference setting (key '"+key+"')"); 1059 for (Map<String, String> map : value) { 1060 Map<String, String> mapCopy = new LinkedHashMap<String,String>(map); 1061 if (mapCopy.keySet().contains(null)) throw new RuntimeException("Error: Null as map key in preference setting (key '"+key+"')"); 1062 if (mapCopy.values().contains(null)) throw new RuntimeException("Error: Null as map value in preference setting (key '"+key+"')"); 1063 valueCopy.add(Collections.unmodifiableMap(mapCopy)); 1064 } 1065 listOfStructsProperties.put(key, Collections.unmodifiableList(valueCopy)); 1066 } 1067 try { 1068 save(); 1069 } catch (IOException e) { 1070 Main.warn(tr("Failed to persist preferences to ''{0}''", getPreferenceFile().getAbsoluteFile())); 1071 } 1072 } 1073 // Call outside of synchronized section in case some listener wait for other thread that wait for preference lock 1074 firePreferenceChanged(key, new MapListSetting(oldValue), new MapListSetting(valueCopy)); 1075 return true; 1076 } 1077 1078 public static boolean equalListOfStructs(Collection<Map<String, String>> a, Collection<Map<String, String>> b) { 1079 if (a == null) return b == null; 1080 if (b == null) return false; 1081 if (a.size() != b.size()) return false; 1082 Iterator<Map<String, String>> itA = a.iterator(); 1083 Iterator<Map<String, String>> itB = b.iterator(); 1084 while (itA.hasNext()) { 1085 if (!equalMap(itA.next(), itB.next())) return false; 1086 } 1087 return true; 1088 } 1089 1090 private static boolean equalMap(Map<String, String> a, Map<String, String> b) { 1091 if (a == null) return b == null; 1092 if (b == null) return false; 1093 if (a.size() != b.size()) return false; 1094 for (Entry<String, String> e : a.entrySet()) { 1095 if (!Utils.equal(e.getValue(), b.get(e.getKey()))) return false; 1096 } 1097 return true; 1098 } 1099 1100 synchronized private void putListOfStructsDefault(String key, List<Map<String, String>> val) { 1101 listOfStructsDefaults.put(key, val); 1085 return putSetting(key, value == null ? null : new MapListSetting(new ArrayList<Map<String, String>>(value))); 1102 1086 } 1103 1087 … … 1255 1239 } 1256 1240 1257 public boolean putSetting(final String key, Setting value) {1258 if (value == null) return false;1259 class PutVisitor implements SettingVisitor {1260 public boolean changed;1261 @Override1262 public void visit(StringSetting setting) {1263 changed = put(key, setting.getValue());1264 }1265 @Override1266 public void visit(ListSetting setting) {1267 changed = putCollection(key, setting.getValue());1268 }1269 @Override1270 public void visit(ListListSetting setting) {1271 @SuppressWarnings("unchecked")1272 boolean changed = putArray(key, (Collection) setting.getValue());1273 this.changed = changed;1274 }1275 @Override1276 public void visit(MapListSetting setting) {1277 changed = putListOfStructs(key, setting.getValue());1278 }1279 }1280 PutVisitor putVisitor = new PutVisitor();1281 value.visit(putVisitor);1282 return putVisitor.changed;1283 }1284 1285 1241 public Map<String, Setting> getAllSettings() { 1286 Map<String, Setting> settings = new TreeMap<String, Setting>(); 1287 1288 for (Entry<String, String> e : properties.entrySet()) { 1289 settings.put(e.getKey(), new StringSetting(e.getValue())); 1290 } 1291 for (Entry<String, List<String>> e : collectionProperties.entrySet()) { 1292 settings.put(e.getKey(), new ListSetting(e.getValue())); 1293 } 1294 for (Entry<String, List<List<String>>> e : arrayProperties.entrySet()) { 1295 settings.put(e.getKey(), new ListListSetting(e.getValue())); 1296 } 1297 for (Entry<String, List<Map<String, String>>> e : listOfStructsProperties.entrySet()) { 1298 settings.put(e.getKey(), new MapListSetting(e.getValue())); 1299 } 1300 return settings; 1242 return new TreeMap<String, Setting>(settingsMap); 1301 1243 } 1302 1244 1303 1245 public Map<String, Setting> getAllDefaults() { 1304 Map<String, Setting> allDefaults = new TreeMap<String, Setting>(); 1305 1306 for (Entry<String, String> e : defaults.entrySet()) { 1307 allDefaults.put(e.getKey(), new StringSetting(e.getValue())); 1308 } 1309 for (Entry<String, List<String>> e : collectionDefaults.entrySet()) { 1310 allDefaults.put(e.getKey(), new ListSetting(e.getValue())); 1311 } 1312 for (Entry<String, List<List<String>>> e : arrayDefaults.entrySet()) { 1313 allDefaults.put(e.getKey(), new ListListSetting(e.getValue())); 1314 } 1315 for (Entry<String, List<Map<String, String>>> e : listOfStructsDefaults.entrySet()) { 1316 allDefaults.put(e.getKey(), new MapListSetting(e.getValue())); 1317 } 1318 return allDefaults; 1246 return new TreeMap<String, Setting>(defaultsMap); 1319 1247 } 1320 1248 … … 1414 1342 if (event == XMLStreamConstants.START_ELEMENT) { 1415 1343 if (parser.getLocalName().equals("tag")) { 1416 properties.put(parser.getAttributeValue(null, "key"), parser.getAttributeValue(null, "value"));1344 settingsMap.put(parser.getAttributeValue(null, "key"), new StringSetting(parser.getAttributeValue(null, "value"))); 1417 1345 jumpToEnd(); 1418 1346 } else if (parser.getLocalName().equals("list") || … … 1476 1404 } 1477 1405 if (entries != null) { 1478 collectionProperties.put(key, Collections.unmodifiableList(entries));1406 settingsMap.put(key, new ListSetting(Collections.unmodifiableList(entries))); 1479 1407 } else if (lists != null) { 1480 arrayProperties.put(key, Collections.unmodifiableList(lists));1408 settingsMap.put(key, new ListListSetting(Collections.unmodifiableList(lists))); 1481 1409 } else if (maps != null) { 1482 listOfStructsProperties.put(key, Collections.unmodifiableList(maps));1410 settingsMap.put(key, new MapListSetting(Collections.unmodifiableList(maps))); 1483 1411 } else { 1484 1412 if (name.equals("lists")) { 1485 arrayProperties.put(key, Collections.<List<String>>emptyList());1413 settingsMap.put(key, new ListListSetting(Collections.<List<String>>emptyList())); 1486 1414 } else if (name.equals("maps")) { 1487 listOfStructsProperties.put(key, Collections.<Map<String, String>>emptyList());1415 settingsMap.put(key, new MapListSetting(Collections.<Map<String, String>>emptyList())); 1488 1416 } else { 1489 collectionProperties.put(key, Collections.<String>emptyList());1417 settingsMap.put(key, new ListSetting(Collections.<String>emptyList())); 1490 1418 } 1491 1419 } … … 1550 1478 if (noPassword && key.equals("osm-server.password")) 1551 1479 return; // do not store plain password. 1552 String r = setting.getValue();1553 String s = defaults.get(key);1554 1480 /* don't save default values */ 1555 if (s == null || !s.equals(r)) {1556 b.append(" <tag key='");1557 b.append(XmlWriter.encode(key));1558 b.append("' value='");1559 b.append(XmlWriter.encode(setting.getValue()));1560 b.append("'/>\n");1561 }1481 if (setting.equals(defaultsMap.get(key))) 1482 return; 1483 b.append(" <tag key='"); 1484 b.append(XmlWriter.encode(key)); 1485 b.append("' value='"); 1486 b.append(XmlWriter.encode(setting.getValue())); 1487 b.append("'/>\n"); 1562 1488 } 1563 1489 … … 1604 1530 Version.getInstance().getVersion() + "\">\n"); 1605 1531 SettingToXml toXml = new SettingToXml(b, nopass); 1606 Map<String, Setting<?>> settings = new TreeMap<String, Setting<?>>(); 1607 1608 for (Entry<String, String> e : properties.entrySet()) { 1609 settings.put(e.getKey(), new StringSetting(e.getValue())); 1610 } 1611 for (Entry<String, List<String>> e : collectionProperties.entrySet()) { 1612 settings.put(e.getKey(), new ListSetting(e.getValue())); 1613 } 1614 for (Entry<String, List<List<String>>> e : arrayProperties.entrySet()) { 1615 settings.put(e.getKey(), new ListListSetting(e.getValue())); 1616 } 1617 for (Entry<String, List<Map<String, String>>> e : listOfStructsProperties.entrySet()) { 1618 settings.put(e.getKey(), new MapListSetting(e.getValue())); 1619 } 1620 for (Entry<String, Setting<?>> e : settings.entrySet()) { 1532 for (Entry<String, Setting> e : settingsMap.entrySet()) { 1621 1533 toXml.setKey(e.getKey()); 1622 1534 e.getValue().visit(toXml); … … 1648 1560 }; 1649 1561 for (String key : obsolete) { 1650 boolean removed = false; 1651 if (properties.containsKey(key)) { properties.remove(key); removed = true; } 1652 if (collectionProperties.containsKey(key)) { collectionProperties.remove(key); removed = true; } 1653 if (arrayProperties.containsKey(key)) { arrayProperties.remove(key); removed = true; } 1654 if (listOfStructsProperties.containsKey(key)) { listOfStructsProperties.remove(key); removed = true; } 1655 if (removed) { 1562 if (settingsMap.containsKey(key)) { 1563 settingsMap.remove(key); 1656 1564 Main.info(tr("Preference setting {0} has been removed since it is no longer used.", key)); 1657 1565 } … … 1659 1567 } 1660 1568 1661 public static boolean isEqual(Setting<?> a, Setting<?> b) { 1662 if (a==null && b==null) return true; 1663 if (a==null) return false; 1664 if (b==null) return false; 1665 if (a==b) return true; 1666 1667 if (a instanceof StringSetting) 1668 return (a.getValue().equals(b.getValue())); 1669 if (a instanceof ListSetting) { 1670 @SuppressWarnings("unchecked") Collection<String> aValue = (Collection<String>) a.getValue(); 1671 @SuppressWarnings("unchecked") Collection<String> bValue = (Collection<String>) b.getValue(); 1672 return equalCollection(aValue, bValue); 1673 } 1674 if (a instanceof ListListSetting) { 1675 @SuppressWarnings("unchecked") Collection<Collection<String>> aValue = (Collection<Collection<String>>) a.getValue(); 1676 @SuppressWarnings("unchecked") Collection<List<String>> bValue = (Collection<List<String>>) b.getValue(); 1677 return equalArray(aValue, bValue); 1678 } 1679 if (a instanceof MapListSetting) { 1680 @SuppressWarnings("unchecked") Collection<Map<String, String>> aValue = (Collection<Map<String, String>>) a.getValue(); 1681 @SuppressWarnings("unchecked") Collection<Map<String, String>> bValue = (Collection<Map<String, String>>) b.getValue(); 1682 return equalListOfStructs(aValue, bValue); 1683 } 1569 public static boolean isEqual(Setting a, Setting b) { 1570 if (a == null) return b == null; 1684 1571 return a.equals(b); 1685 1572 } -
trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java
r6380 r6578 151 151 152 152 public void download(String userName, String password) { 153 if (! properties.containsKey("applet.username") && userName != null) {154 properties.put("applet.username", userName);153 if (!settingsMap.containsKey("applet.username") && userName != null) { 154 settingsMap.put("applet.username", new StringSetting(userName)); 155 155 } 156 if (! properties.containsKey("applet.password") && password != null) {157 properties.put("applet.password", password);156 if (!settingsMap.containsKey("applet.password") && password != null) { 157 settingsMap.put("applet.password", new StringSetting(password)); 158 158 } 159 159 try { -
trunk/src/org/openstreetmap/josm/gui/MainApplication.java
r6528 r6578 398 398 Main.MasterWindowListener.setup(); 399 399 400 boolean maximized = Boolean.parseBoolean(Main.pref.get("gui.maximized"));400 boolean maximized = Main.pref.getBoolean("gui.maximized", false); 401 401 if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) { 402 402 if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) { -
trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java
r6529 r6578 436 436 for (PrefEntry e : allData) { 437 437 if (e.isChanged()) { 438 Main.pref.putSetting(e.getKey(), e.getValue() );438 Main.pref.putSetting(e.getKey(), e.getValue().getValue() == null ? null : e.getValue()); 439 439 } 440 440 } -
trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PreferencesTable.java
r6495 r6578 1 1 // License: GPL. See LICENSE file for details. 2 2 package org.openstreetmap.josm.gui.preferences.advanced; 3 4 import static org.openstreetmap.josm.tools.I18n.marktr; 5 import static org.openstreetmap.josm.tools.I18n.tr; 3 6 4 7 import java.awt.Color; … … 12 15 import java.util.List; 13 16 import java.util.Map; 17 14 18 import javax.swing.ButtonGroup; 15 19 import javax.swing.DefaultCellEditor; … … 22 26 import javax.swing.table.DefaultTableCellRenderer; 23 27 import javax.swing.table.DefaultTableModel; 28 24 29 import org.openstreetmap.josm.Main; 25 30 import org.openstreetmap.josm.data.Preferences; … … 27 32 import org.openstreetmap.josm.gui.widgets.JosmTextField; 28 33 import org.openstreetmap.josm.tools.GBC; 29 import static org.openstreetmap.josm.tools.I18n.marktr;30 import static org.openstreetmap.josm.tools.I18n.tr;31 34 import org.openstreetmap.josm.tools.Utils; 32 35 … … 106 109 if (lEditor.getValue() == 1) { 107 110 List<String> data = lEditor.getData(); 108 if (! Preferences.equalCollection(lSetting.getValue(),data)) {111 if (!lSetting.equalVal(data)) { 109 112 e.setValue(new Preferences.ListSetting(data)); 110 113 return true; … … 112 115 } 113 116 } else if (stg instanceof Preferences.ListListSetting) { 114 ListListEditor llEditor = new ListListEditor(gui, e, (Preferences.ListListSetting) stg); 117 Preferences.ListListSetting llSetting = (Preferences.ListListSetting) stg; 118 ListListEditor llEditor = new ListListEditor(gui, e, llSetting); 115 119 llEditor.showDialog(); 116 120 if (llEditor.getValue() == 1) { … … 118 122 @SuppressWarnings("unchecked") 119 123 Collection<Collection<String>> stgValue = (Collection<Collection<String>>) stg.getValue(); 120 if (! Preferences.equalArray(stgValue,data)) {124 if (!llSetting.equalVal(data)) { 121 125 e.setValue(new Preferences.ListListSetting(data)); 122 126 return true; … … 129 133 if (mlEditor.getValue() == 1) { 130 134 List<Map<String, String>> data = mlEditor.getData(); 131 if (! Preferences.equalListOfStructs(mlSetting.getValue(),data)) {135 if (!mlSetting.equalVal(data)) { 132 136 e.setValue(new Preferences.MapListSetting(data)); 133 137 return true; … … 196 200 if (lEditor.getValue() == 1) { 197 201 List<String> data = lEditor.getData(); 198 if (! Preferences.equalCollection(lSetting.getValue(),data)) {202 if (!lSetting.equalVal(data)) { 199 203 pe.setValue(new Preferences.ListSetting(data)); 200 204 ok = true; … … 208 212 if (llEditor.getValue() == 1) { 209 213 List<List<String>> data = llEditor.getData(); 210 @SuppressWarnings("unchecked") 211 Collection<Collection<String>> llSettingValue = (Collection) llSetting.getValue(); 212 if (!Preferences.equalArray(llSettingValue, data)) { 214 if (!llSetting.equalVal(data)) { 213 215 pe.setValue(new Preferences.ListListSetting(data)); 214 216 ok = true; … … 222 224 if (mlEditor.getValue() == 1) { 223 225 List<Map<String, String>> data = mlEditor.getData(); 224 if (! Preferences.equalListOfStructs(mlSetting.getValue(),data)) {226 if (!mlSetting.equalVal(data)) { 225 227 pe.setValue(new Preferences.MapListSetting(data)); 226 228 ok = true; -
trunk/src/org/openstreetmap/josm/tools/Utils.java
r6552 r6578 857 857 } 858 858 } 859 860 /** 861 * Cast an object savely. 862 * @param <T> the target type 863 * @param o the object to cast 864 * @param klass the target class (same as T) 865 * @return null if <code>o</code> is null or the type <code>o</code> is not 866 * a subclass of <code>klass</code>. The casted value otherwise. 867 */ 868 public static <T> T cast(Object o, Class<T> klass) { 869 if (klass.isInstance(o)) { 870 @SuppressWarnings("unchecked") 871 T ret = (T) o; 872 return ret; 873 } 874 return null; 875 } 876 859 877 }
Note:
See TracChangeset
for help on using the changeset viewer.