Ignore:
Timestamp:
2016-02-18T11:07:38+01:00 (8 years ago)
Author:
bastiK
Message:

fixed #12522 - Advanced preferences: display default entries consistently

Saves default preference entries to a cache file (cache/default_preferences.xml), so the list of advanced preferences is filled with all known default values consistently from the start and not gradually as you use different features during a session.

Location:
trunk/src/org/openstreetmap/josm/data/preferences
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/preferences/AbstractSetting.java

    r9759 r9821  
    1212public abstract class AbstractSetting<T> implements Setting<T> {
    1313    protected final T value;
     14    protected Long time;
     15    protected boolean isNew;
    1416    /**
    1517     * Constructs a new {@code AbstractSetting} with the given value
     
    1820    public AbstractSetting(T value) {
    1921        this.value = value;
     22        this.time = null;
     23        this.isNew = false;
    2024    }
    2125
     
    2327    public T getValue() {
    2428        return value;
     29    }
     30
     31    @Override
     32    public void setTime(Long time) {
     33        this.time = time;
     34    }
     35
     36    @Override
     37    public Long getTime() {
     38        return this.time;
     39    }
     40
     41    @Override
     42    public void setNew(boolean isNew) {
     43        this.isNew = isNew;
     44    }
     45
     46    @Override
     47    public boolean isNew() {
     48        return isNew;
    2549    }
    2650
  • trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java

    r9798 r9821  
    3838public class PreferencesReader {
    3939
     40    private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
     41
    4042    private final SortedMap<String, Setting<?>> settings = new TreeMap<>();
    4143    private int version = 0;
    4244    private XMLStreamReader parser;
     45
     46    private final boolean defaults;
     47
     48    /**
     49     * Constructs a new {@code PreferencesReader}.
     50     * @param defaults true when reading from the cache file for default preferences,
     51     * false for the regular preferences config file
     52     */
     53    public PreferencesReader(boolean defaults) {
     54        this.defaults = defaults;
     55    }
    4356
    4457    /**
     
    111124        while (true) {
    112125            if (event == XMLStreamConstants.START_ELEMENT) {
     126                String topLevelElementName = defaults ? "preferences-defaults" : "preferences";
     127                String localName = parser.getLocalName();
     128                if (!topLevelElementName.equals(localName)) {
     129                    throw new XMLStreamException(tr("Expected element ''{0}'', but got ''{1}''", topLevelElementName, localName), parser.getLocation());
     130                }
    113131                try {
    114132                    version = Integer.parseInt(parser.getAttributeValue(null, "version"));
     
    138156                switch(localName) {
    139157                case "tag":
    140                     settings.put(parser.getAttributeValue(null, "key"), new StringSetting(parser.getAttributeValue(null, "value")));
     158                    Setting setting;
     159                    if (defaults && isNil()) {
     160                        setting = new StringSetting(null);
     161                    } else {
     162                        String value = parser.getAttributeValue(null, "value");
     163                        if (value == null) {
     164                            throw new XMLStreamException(tr("value expected"), parser.getLocation());
     165                        }
     166                        setting = new StringSetting(value);
     167                    }
     168                    if (defaults) {
     169                        setting.setTime(Math.round(Double.parseDouble(parser.getAttributeValue(null, "time"))));
     170                    }
     171                    settings.put(parser.getAttributeValue(null, "key"), setting);
    141172                    jumpToEnd();
    142173                    break;
    143174                case "list":
    144                 case "collection":
    145175                case "lists":
    146176                case "maps":
     
    169199    private void parseToplevelList() throws XMLStreamException {
    170200        String key = parser.getAttributeValue(null, "key");
     201        Long time = null;
     202        if (defaults) {
     203            time = Math.round(Double.parseDouble(parser.getAttributeValue(null, "time")));
     204        }
    171205        String name = parser.getLocalName();
    172206
     
    174208        List<List<String>> lists = null;
    175209        List<Map<String, String>> maps = null;
    176         while (true) {
    177             int event = parser.next();
    178             if (event == XMLStreamConstants.START_ELEMENT) {
    179                 String localName = parser.getLocalName();
    180                 switch(localName) {
    181                 case "entry":
    182                     if (entries == null) {
    183                         entries = new ArrayList<>();
     210        if (defaults && isNil()) {
     211            Setting setting;
     212            switch (name) {
     213                case "lists":
     214                    setting = new ListListSetting(null);
     215                    break;
     216                case "maps":
     217                    setting = new MapListSetting(null);
     218                    break;
     219                default:
     220                    setting = new ListSetting(null);
     221                    break;
     222            }
     223            setting.setTime(time);
     224            settings.put(key, setting);
     225            jumpToEnd();
     226        } else {
     227            while (true) {
     228                int event = parser.next();
     229                if (event == XMLStreamConstants.START_ELEMENT) {
     230                    String localName = parser.getLocalName();
     231                    switch(localName) {
     232                    case "entry":
     233                        if (entries == null) {
     234                            entries = new ArrayList<>();
     235                        }
     236                        entries.add(parser.getAttributeValue(null, "value"));
     237                        jumpToEnd();
     238                        break;
     239                    case "list":
     240                        if (lists == null) {
     241                            lists = new ArrayList<>();
     242                        }
     243                        lists.add(parseInnerList());
     244                        break;
     245                    case "map":
     246                        if (maps == null) {
     247                            maps = new ArrayList<>();
     248                        }
     249                        maps.add(parseMap());
     250                        break;
     251                    default:
     252                        throwException("Unexpected element: "+localName);
    184253                    }
    185                     entries.add(parser.getAttributeValue(null, "value"));
    186                     jumpToEnd();
    187                     break;
    188                 case "list":
    189                     if (lists == null) {
    190                         lists = new ArrayList<>();
    191                     }
    192                     lists.add(parseInnerList());
    193                     break;
    194                 case "map":
    195                     if (maps == null) {
    196                         maps = new ArrayList<>();
    197                     }
    198                     maps.add(parseMap());
    199                     break;
    200                 default:
    201                     throwException("Unexpected element: "+localName);
    202                 }
    203             } else if (event == XMLStreamConstants.END_ELEMENT) {
    204                 break;
    205             }
    206         }
    207         if (entries != null) {
    208             settings.put(key, new ListSetting(Collections.unmodifiableList(entries)));
    209         } else if (lists != null) {
    210             settings.put(key, new ListListSetting(Collections.unmodifiableList(lists)));
    211         } else if (maps != null) {
    212             settings.put(key, new MapListSetting(Collections.unmodifiableList(maps)));
    213         } else {
    214             if ("lists".equals(name)) {
    215                 settings.put(key, new ListListSetting(Collections.<List<String>>emptyList()));
    216             } else if ("maps".equals(name)) {
    217                 settings.put(key, new MapListSetting(Collections.<Map<String, String>>emptyList()));
     254                } else if (event == XMLStreamConstants.END_ELEMENT) {
     255                    break;
     256                }
     257            }
     258            Setting setting;
     259            if (entries != null) {
     260                setting = new ListSetting(Collections.unmodifiableList(entries));
     261            } else if (lists != null) {
     262                setting = new ListListSetting(Collections.unmodifiableList(lists));
     263            } else if (maps != null) {
     264                setting = new MapListSetting(Collections.unmodifiableList(maps));
    218265            } else {
    219                 settings.put(key, new ListSetting(Collections.<String>emptyList()));
    220             }
     266                switch (name) {
     267                    case "lists":
     268                        setting = new ListListSetting(Collections.<List<String>>emptyList());
     269                        break;
     270                    case "maps":
     271                        setting = new MapListSetting(Collections.<Map<String, String>>emptyList());
     272                        break;
     273                    default:
     274                        setting = new ListSetting(Collections.<String>emptyList());
     275                        break;
     276                }
     277            }
     278            if (defaults) {
     279                setting.setTime(time);
     280            }
     281            settings.put(key, setting);
    221282        }
    222283    }
     
    258319    }
    259320
     321    /**
     322     * Check if the current element is nil (meaning the value of the setting is null).
     323     * @return true, if the current element is nil
     324     * @see https://msdn.microsoft.com/en-us/library/2b314yt2(v=vs.85).aspx
     325     */
     326    private boolean isNil() {
     327        String nil = parser.getAttributeValue(XSI_NS, "nil");
     328        return "true".equals(nil) || "1".equals(nil);
     329    }
     330
     331    /**
     332     * Throw RuntimeException with line and column number.
     333     *
     334     * Only use this for errors that should not be possible after schema validation.
     335     * @param msg the error message
     336     */
    260337    private void throwException(String msg) {
    261338        throw new RuntimeException(msg + tr(" (at line {0}, column {1})",
  • trunk/src/org/openstreetmap/josm/data/preferences/Setting.java

    r9759 r9821  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.preferences;
     3
     4import org.openstreetmap.josm.data.Preferences;
    35
    46/**
     
    4648     */
    4749    Setting<T> getNullInstance();
     50
     51    /**
     52     * Set the time for this setting.
     53     *
     54     * For default preferences. They are saved in a cache file. Keeping the
     55     * time allows to discard very old default settings.
     56     * @param time the time in seconds since epoch
     57     */
     58    void setTime(Long time);
     59
     60    /**
     61     * Get the time for this setting.
     62     * @return the time for this setting
     63     * @see #setTime(java.lang.Long)
     64     */
     65    Long getTime();
     66
     67    /**
     68     * Mark setting as new.
     69     *
     70     * For default preferences. A setting is marked as new, if it has been seen
     71     * in the current session.
     72     * Methods like {@link Preferences#get(java.lang.String, java.lang.String)},
     73     * can be called from different parts of the code with the same key. In this case,
     74     * the supplied default value must match. However, this is only an error if the mismatching
     75     * default value has been seen in the same session (and not loaded from cache).
     76     * @param isNew true, if it is new
     77     */
     78    void setNew(boolean isNew);
     79
     80    /**
     81     * Return if the setting has been marked as new.
     82     * @return true, if the setting has been marked as new
     83     * @see #setNew(boolean)
     84     */
     85    boolean isNew();
    4886}
Note: See TracChangeset for help on using the changeset viewer.