001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.preferences.sources;
003
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.HashMap;
007import java.util.LinkedHashSet;
008import java.util.List;
009import java.util.Map;
010import java.util.Set;
011import java.util.stream.Collectors;
012
013import org.openstreetmap.josm.spi.preferences.Config;
014
015/**
016 * Helper class for specialized extensions preferences.
017 * @since 12649 (extracted from gui.preferences package)
018 */
019public abstract class SourcePrefHelper {
020
021    private final String pref;
022    protected final SourceType type;
023
024    /**
025     * Constructs a new {@code SourcePrefHelper} for the given preference key.
026     * @param pref The preference key
027     * @param type The source type
028     * @since 12825
029     */
030    public SourcePrefHelper(String pref, SourceType type) {
031        this.pref = pref;
032        this.type = type;
033    }
034
035    /**
036     * Returns the default sources provided by JOSM core.
037     * @return the default sources provided by JOSM core
038     */
039    public abstract Collection<ExtendedSourceEntry> getDefault();
040
041    /**
042     * Serializes the given source entry as a map.
043     * @param entry source entry to serialize
044     * @return map (key=value)
045     */
046    public abstract Map<String, String> serialize(SourceEntry entry);
047
048    /**
049     * Deserializes the given map as a source entry.
050     * @param entryStr map (key=value)
051     * @return source entry
052     */
053    public abstract SourceEntry deserialize(Map<String, String> entryStr);
054
055    /**
056     * Returns the list of sources.
057     * @return The list of sources
058     */
059    public List<SourceEntry> get() {
060
061        List<Map<String, String>> src = Config.getPref().getListOfMaps(pref, null);
062        if (src == null)
063            return new ArrayList<>(getDefault());
064
065        List<SourceEntry> entries = new ArrayList<>();
066        for (Map<String, String> sourcePref : src) {
067            SourceEntry e = deserialize(new HashMap<>(sourcePref));
068            if (e != null) {
069                entries.add(e);
070            }
071        }
072        return entries;
073    }
074
075    /**
076     * Saves a list of sources to JOSM preferences.
077     * @param entries list of sources
078     * @return {@code true}, if something has changed (i.e. value is different than before)
079     */
080    public boolean put(Collection<? extends SourceEntry> entries) {
081        List<Map<String, String>> setting = serializeList(entries);
082        boolean unset = Config.getPref().getListOfMaps(pref, null) == null;
083        if (unset) {
084            Collection<Map<String, String>> def = serializeList(getDefault());
085            if (setting.equals(def))
086                return false;
087        }
088        return Config.getPref().putListOfMaps(pref, setting);
089    }
090
091    private List<Map<String, String>> serializeList(Collection<? extends SourceEntry> entries) {
092        return new ArrayList<>(entries).stream().map(this::serialize).collect(Collectors.toList());
093    }
094
095    /**
096     * Returns the set of active source URLs.
097     * @return The set of active source URLs.
098     */
099    public final Set<String> getActiveUrls() {
100        Set<String> urls = new LinkedHashSet<>(); // retain order
101        for (SourceEntry e : get()) {
102            if (e.active) {
103                urls.add(e.url);
104            }
105        }
106        return urls;
107    }
108}