Opened 8 years ago

#13446 new enhancement

Preference cleanup

Reported by: michael2402 Owned by: team
Priority: normal Milestone:
Component: Core Version:
Keywords: preferences Cc:


JOSM preferences were a String->String map. They have been enhanced to be a String->whatever map.

Over the time, this system has grown to support multiple data types by converting them to strings.
This includes:

Type direct access proxy access notes
String pref.get(String) new StringProperty()
Boolean pref.getBoolean(String) new BooleanProperty() no type hints
Boolean pref.getInteger(String) new IntegerProperty() no type hints
Boolean pref.getDouble(String) new DoubleProperty() no type hints
Boolean pref.getLong(String) new LongProperty() no type hints
Color pref.getColor(String) new ColorProperty() type identified by start with color.
Collection<String> pref.getCollection(String) ListSetting class
Collection<Collection<String>> pref.getArray(String) ListListSetting class
Object (Struct) serializeStruct - See @pref annotation
List<Object> (Structs) getListOfStructs - See @pref annotation

The interface to all those types differs a lot.

I propose:

  1. Remove all public access to the Setting classes -> Make them internal.
  2. Support only those internal Setting classes:
    • StringSetting (represented as simple string)
    • ListSetting<? extends Setting> ([0...n-1] -> value map)
    • MapSetting<? extends Setting> (name -> value map)
  3. Replace ListListSetting by ListSetting<ListSetting<StringSetting>>
  4. Use setting classes during writing/reading the xml file only.
  5. Do not expose the string representation of settings to the user. No more Main.pref.get() calls. No more matching-the-default-values, since we can store the property objects as constants.
  6. Replace all public access using ..Property objects.
  7. Do type check in the Property objects when registering them.
  8. Store the Property objects in a knownProperties map. They already contain the default value and the type information.

So we could replace this code:

        List<ImageryPreferenceEntry> entries = new ArrayList<>();
        for (ImageryInfo info : layers) {
            entries.add(new ImageryPreferenceEntry(info));
        Main.pref.putListOfStructs("imagery.entries", entries, ImageryPreferenceEntry.class);
        // Use the builder pattern here
        // Uses ListCompoundProperty and MapCompoundProperty internally
        CompoundProperty<List<Map<String, String>> pref ="imagery.entries");
        // expects List<Map<String, String>>
                .map(info -> new ImageryPreferenceEntry(info))
                .map(Preferences::serializeStruct) // < can be moved to utility class

We can also move the serilaization to a Property object:

        // Use the builder pattern here
        // Uses ListCompoundProperty and MapCompoundProperty internally
        CompoundProperty<List<ImageryPreferenceEntry> pref = CompoundProperty.serialized(ImageryPreferenceEntry.class).list().for("imagery.entries");
        // expects List<Map<String, String>>

Next example:

        return Main.pref.getCollection("imagery.layers.sites", Arrays.asList(DEFAULT_LAYER_SITES));
        return CompoundProperty.list().for("imagery.layers.sites", Arrays.asList(DEFAULT_LAYER_SITES)).get();

Next example:

    private static volatile Collection<String> uninteresting;
    public static Collection<String> getUninterestingKeys() {
        if (uninteresting == null) {
            List<String> l = ...
            uninteresting = Main.pref.getCollection("tags.uninteresting", l);
        return uninteresting;
    private static UNINTERESTING = CompoundProperty.list().for("tags.uninteresting", l).get().cached();

    public static Collection<String> getUninterestingKeys() {
        return UNINTERESTING.get();

Attachments (0)

Change History (0)

Modify Ticket

Change Properties
Set your email in Preferences
as new The owner will remain team.
as The resolution will be set. Next status will be 'closed'.
to The owner will be changed from team to the specified user.
Next status will be 'needinfo'. The owner will be changed from team to michael2402.
as duplicate The resolution will be set to duplicate. Next status will be 'closed'. The specified ticket will be cross-referenced with this ticket.
The owner will be changed from team to anonymous. Next status will be 'assigned'.

Add Comment

E-mail address and name can be saved in the Preferences .
Note: See TracTickets for help on using tickets.