001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.preferences;
003
004import java.io.PrintWriter;
005import java.util.Collection;
006import java.util.List;
007import java.util.Map;
008
009import org.openstreetmap.josm.Main;
010import org.openstreetmap.josm.data.Version;
011import org.openstreetmap.josm.io.XmlWriter;
012
013/**
014 * Write preferences to XML.
015 * @since 9823
016 */
017public class PreferencesWriter extends XmlWriter implements SettingVisitor {
018    private final boolean noPassword;
019    private final boolean defaults;
020    private String key;
021
022    /**
023     * Construct new {@code PreferencesWriter}.
024     * @param out the {@link PrintWriter}
025     * @param noPassword if password must be excluded
026     * @param defaults true, if default values are converted to XML, false for regular preferences
027     */
028    public PreferencesWriter(PrintWriter out, boolean noPassword, boolean defaults) {
029        super(out);
030        this.noPassword = noPassword;
031        this.defaults = defaults;
032    }
033
034    /**
035     * Write preferences.
036     *
037     * @param settings preferences settings to write
038     */
039    public void write(Collection<Map.Entry<String, Setting<?>>> settings) {
040        out.write(String.format("<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n"));
041        String rootElement = defaults ? "preferences-defaults" : "preferences";
042        out.write(String.format("<%s xmlns='%s/preferences-1.0'", rootElement, Main.getXMLBase()));
043        if (defaults) {
044            out.write(" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'");
045        }
046        out.write(String.format(" version='%d'>%n", Version.getInstance().getVersion()));
047        for (Map.Entry<String, Setting<?>> e : settings) {
048            setKey(e.getKey());
049            e.getValue().visit(this);
050        }
051        out.write(String.format("</%s>%n", rootElement));
052    }
053
054    private void setKey(String key) {
055        this.key = key;
056    }
057
058    private void addTime(Setting<?> setting) {
059        if (defaults) {
060            Long time = setting.getTime();
061            if (time == null)
062                throw new IllegalStateException();
063            out.write("' time='" + time);
064        }
065    }
066
067    private void addDefaults() {
068        out.write(String.format("' xsi:nil='true'/>%n"));
069    }
070
071    @Override
072    public void visit(StringSetting setting) {
073        if (noPassword && "osm-server.password".equals(key))
074            return; // do not store plain password.
075        out.write("  <tag key='" + XmlWriter.encode(key));
076        addTime(setting);
077        if (setting.getValue() != null) {
078            out.write(String.format("' value='%s'/>%n", XmlWriter.encode(setting.getValue())));
079        } else if (defaults) {
080            addDefaults();
081        } else {
082            throw new NullPointerException();
083        }
084    }
085
086    @Override
087    public void visit(ListSetting setting) {
088        out.write("  <list key='" + XmlWriter.encode(key));
089        addTime(setting);
090        if (setting.getValue() != null) {
091            out.write(String.format("'>%n"));
092            for (String s : setting.getValue()) {
093                out.write(String.format("    <entry value='%s'/>%n", XmlWriter.encode(s)));
094            }
095            out.write(String.format("  </list>%n"));
096        } else if (defaults) {
097            addDefaults();
098        } else {
099            throw new NullPointerException();
100        }
101    }
102
103    @Override
104    public void visit(ListListSetting setting) {
105        out.write("  <lists key='" + XmlWriter.encode(key));
106        addTime(setting);
107        if (setting.getValue() != null) {
108            out.write(String.format("'>%n"));
109            for (List<String> list : setting.getValue()) {
110                out.write(String.format("    <list>%n"));
111                for (String s : list) {
112                    out.write(String.format("      <entry value='%s'/>%n", encode(s)));
113                }
114                out.write(String.format("    </list>%n"));
115            }
116            out.write(String.format("  </lists>%n"));
117        } else if (defaults) {
118            addDefaults();
119        } else {
120            throw new NullPointerException();
121        }
122    }
123
124    @Override
125    public void visit(MapListSetting setting) {
126        out.write("  <maps key='" + encode(key));
127        addTime(setting);
128        if (setting.getValue() != null) {
129            out.write(String.format("'>%n"));
130            for (Map<String, String> struct : setting.getValue()) {
131                out.write(String.format("    <map>%n"));
132                for (Map.Entry<String, String> e : struct.entrySet()) {
133                    out.write(String.format("      <tag key='%s' value='%s'/>%n", encode(e.getKey()), encode(e.getValue())));
134                }
135                out.write(String.format("    </map>%n"));
136            }
137            out.write(String.format("  </maps>%n"));
138        } else if (defaults) {
139            addDefaults();
140        } else {
141            throw new NullPointerException();
142        }
143    }
144}