001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.session; 003 004import java.awt.Component; 005import java.awt.GridBagLayout; 006import java.io.IOException; 007import java.io.OutputStream; 008import java.io.OutputStreamWriter; 009import java.io.PrintWriter; 010import java.io.Writer; 011import java.nio.charset.StandardCharsets; 012import java.time.Instant; 013import java.util.Collection; 014import java.util.Collections; 015 016import javax.swing.JLabel; 017import javax.swing.JPanel; 018import javax.swing.SwingConstants; 019 020import org.openstreetmap.josm.data.gpx.GpxData; 021import org.openstreetmap.josm.gui.MainApplication; 022import org.openstreetmap.josm.gui.layer.Layer; 023import org.openstreetmap.josm.gui.layer.markerlayer.Marker; 024import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; 025import org.openstreetmap.josm.io.GpxWriter; 026import org.openstreetmap.josm.io.session.SessionWriter.ExportSupport; 027import org.openstreetmap.josm.tools.GBC; 028import org.w3c.dom.Element; 029 030/** 031 * Session exporter for {@link MarkerLayer}. 032 * @since 5684 033 */ 034public class MarkerSessionExporter extends AbstractSessionExporter<MarkerLayer> { 035 036 private Instant metaTime; 037 038 /** 039 * Constructs a new {@code MarkerSessionExporter}. 040 * @param layer marker layer to export 041 */ 042 public MarkerSessionExporter(MarkerLayer layer) { // NO_UCD (unused code) 043 super(layer); 044 } 045 046 @Override 047 public Collection<Layer> getDependencies() { 048 Layer gpxLayer = layer.fromLayer; 049 if (gpxLayer != null && MainApplication.getLayerManager().containsLayer(gpxLayer)) 050 return Collections.singleton(gpxLayer); 051 return Collections.emptySet(); 052 } 053 054 @Override 055 public Component getExportPanel() { 056 final JPanel p = new JPanel(new GridBagLayout()); 057 export.setSelected(true); 058 final JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEADING); 059 lbl.setToolTipText(layer.getToolTipText()); 060 lbl.setLabelFor(export); 061 p.add(export, GBC.std()); 062 p.add(lbl, GBC.std()); 063 p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL)); 064 return p; 065 } 066 067 @Override 068 public boolean requiresZip() { 069 return true; 070 } 071 072 @Override 073 public Element export(ExportSupport support) throws IOException { 074 Element layerEl = support.createElement("layer"); 075 layerEl.setAttribute("type", "markers"); 076 layerEl.setAttribute("version", "0.1"); 077 078 Element file = support.createElement("file"); 079 layerEl.appendChild(file); 080 081 String zipPath = "layers/" + String.format("%02d", support.getLayerIndex()) + "/data.gpx"; 082 file.appendChild(support.createTextNode(zipPath)); 083 addDataFile(support.getOutputStreamZip(zipPath)); 084 085 return layerEl; 086 } 087 088 @SuppressWarnings("resource") 089 protected void addDataFile(OutputStream out) { 090 Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); 091 MarkerWriter w = new MarkerWriter(new PrintWriter(writer)); 092 if (metaTime != null) { 093 w.setMetaTime(metaTime); 094 } 095 w.write(layer); 096 w.flush(); 097 } 098 099 protected void setMetaTime(Instant metaTime) { 100 this.metaTime = metaTime; 101 } 102 103 /** 104 * Writes GPX file from marker data. 105 */ 106 public static class MarkerWriter extends GpxWriter { 107 108 /** 109 * Constructs a new {@code MarkerWriter}. 110 * @param out The output writer 111 */ 112 public MarkerWriter(PrintWriter out) { 113 super(out); 114 } 115 116 /** 117 * Writes the given markers data. 118 * @param layer The layer data to write 119 */ 120 public void write(MarkerLayer layer) { 121 GpxData data = new GpxData(); 122 layer.data.getLayerPrefs().forEach((k, v) -> { 123 if (k != null && k.indexOf("markers.") == 0) { 124 data.getLayerPrefs().put(k, v); 125 } 126 }); 127 data.put(GpxData.META_DESC, "exported JOSM marker layer"); 128 for (Marker m : layer.data) { 129 data.waypoints.add(m.convertToWayPoint()); 130 } 131 super.write(data); 132 } 133 } 134}