// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.data.preferences; import java.io.PrintWriter; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Version; import org.openstreetmap.josm.io.XmlWriter; /** * Write preferences to XML. * @since 9823 */ public class PreferencesWriter extends XmlWriter implements SettingVisitor { private final boolean noPassword; private final boolean defaults; private String key; /** * Construct new {@code PreferencesWriter}. * @param out the {@link PrintWriter} * @param noPassword if password must be excluded * @param defaults true, if default values are converted to XML, false for regular preferences */ public PreferencesWriter(PrintWriter out, boolean noPassword, boolean defaults) { super(out); this.noPassword = noPassword; this.defaults = defaults; } /** * Write preferences. * * @param settings preferences settings to write */ public void write(Collection<Map.Entry<String, Setting<?>>> settings) { write(settings.stream()); } /** * Write preferences. * * @param settings preferences settings to write as stream. */ public void write(Stream<Map.Entry<String, Setting<?>>> settings) { out.write(String.format("<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n")); String rootElement = defaults ? "preferences-defaults" : "preferences"; out.write(String.format("<%s xmlns='%s/preferences-1.0'", rootElement, Main.getXMLBase())); if (defaults) { out.write(" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'"); } out.write(String.format(" version='%d'>%n", Version.getInstance().getVersion())); settings.forEachOrdered(e -> { setKey(e.getKey()); e.getValue().visit(this); }); out.write(String.format("</%s>%n", rootElement)); } private void setKey(String key) { this.key = key; } private void addTime(Setting<?> setting) { if (defaults) { out.write("' time='" + Optional.ofNullable(setting.getTime()).orElseThrow(IllegalStateException::new)); } } private void addDefaults() { out.write(String.format("' xsi:nil='true'/>%n")); } @Override public void visit(StringSetting setting) { if (noPassword && "osm-server.password".equals(key)) return; // do not store plain password. out.write(" <tag key='" + XmlWriter.encode(key)); addTime(setting); if (setting.getValue() != null) { out.write(String.format("' value='%s'/>%n", XmlWriter.encode(setting.getValue()))); } else if (defaults) { addDefaults(); } else { throw new IllegalArgumentException(setting.toString()); } } @Override public void visit(ListSetting setting) { out.write(" <list key='" + XmlWriter.encode(key)); addTime(setting); if (setting.getValue() != null) { out.write(String.format("'>%n")); for (String s : setting.getValue()) { out.write(String.format(" <entry value='%s'/>%n", XmlWriter.encode(s))); } out.write(String.format(" </list>%n")); } else if (defaults) { addDefaults(); } else { throw new IllegalArgumentException(setting.toString()); } } @Override public void visit(ListListSetting setting) { out.write(" <lists key='" + XmlWriter.encode(key)); addTime(setting); if (setting.getValue() != null) { out.write(String.format("'>%n")); for (List<String> list : setting.getValue()) { out.write(String.format(" <list>%n")); for (String s : list) { out.write(String.format(" <entry value='%s'/>%n", encode(s))); } out.write(String.format(" </list>%n")); } out.write(String.format(" </lists>%n")); } else if (defaults) { addDefaults(); } else { throw new IllegalArgumentException(setting.toString()); } } @Override public void visit(MapListSetting setting) { out.write(" <maps key='" + encode(key)); addTime(setting); if (setting.getValue() != null) { out.write(String.format("'>%n")); for (Map<String, String> struct : setting.getValue()) { out.write(String.format(" <map>%n")); for (Map.Entry<String, String> e : struct.entrySet()) { out.write(String.format(" <tag key='%s' value='%s'/>%n", encode(e.getKey()), encode(e.getValue()))); } out.write(String.format(" </map>%n")); } out.write(String.format(" </maps>%n")); } else if (defaults) { addDefaults(); } else { throw new IllegalArgumentException(setting.toString()); } } }