source: josm/trunk/src/org/openstreetmap/josm/io/GpxWriter.java@ 7242

Last change on this file since 7242 was 7082, checked in by Don-vip, 10 years ago

see #8465 - replace Utils.UTF_8 by StandardCharsets.UTF_8, new in Java 7

  • Property svn:eol-style set to native
File size: 9.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.BufferedWriter;
7import java.io.OutputStream;
8import java.io.OutputStreamWriter;
9import java.io.PrintWriter;
10import java.nio.charset.StandardCharsets;
11import java.util.Collection;
12import java.util.Map;
13import java.util.Map.Entry;
14
15import javax.xml.XMLConstants;
16
17import org.openstreetmap.josm.data.Bounds;
18import org.openstreetmap.josm.data.coor.LatLon;
19import org.openstreetmap.josm.data.gpx.Extensions;
20import org.openstreetmap.josm.data.gpx.GpxConstants;
21import org.openstreetmap.josm.data.gpx.GpxData;
22import org.openstreetmap.josm.data.gpx.GpxLink;
23import org.openstreetmap.josm.data.gpx.GpxRoute;
24import org.openstreetmap.josm.data.gpx.GpxTrack;
25import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
26import org.openstreetmap.josm.data.gpx.IWithAttributes;
27import org.openstreetmap.josm.data.gpx.WayPoint;
28
29/**
30 * Writes GPX files from GPX data or OSM data.
31 */
32public class GpxWriter extends XmlWriter implements GpxConstants {
33
34 public GpxWriter(PrintWriter out) {
35 super(out);
36 }
37
38 public GpxWriter(OutputStream out) {
39 super(new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))));
40 }
41
42 private GpxData data;
43 private String indent = "";
44
45 private static final int WAY_POINT = 0;
46 private static final int ROUTE_POINT = 1;
47 private static final int TRACK_POINT = 2;
48
49 public void write(GpxData data) {
50 this.data = data;
51 // We write JOSM specific meta information into gpx 'extensions' elements.
52 // In particular it is noted whether the gpx data is from the OSM server
53 // (so the rendering of clouds of anonymous TrackPoints can be improved)
54 // and some extra synchronization info for export of AudioMarkers.
55 // It is checked in advance, if any extensions are used, so we know whether
56 // a namespace declaration is necessary.
57 boolean hasExtensions = data.fromServer;
58 if (!hasExtensions) {
59 for (WayPoint wpt : data.waypoints) {
60 Extensions extensions = (Extensions) wpt.get(META_EXTENSIONS);
61 if (extensions != null && !extensions.isEmpty()) {
62 hasExtensions = true;
63 break;
64 }
65 }
66 }
67
68 out.println("<?xml version='1.0' encoding='UTF-8'?>");
69 out.println("<gpx version=\"1.1\" creator=\"JOSM GPX export\" xmlns=\"http://www.topografix.com/GPX/1/1\"\n" +
70 (hasExtensions ? String.format(" xmlns:josm=\"%s\"%n", JOSM_EXTENSIONS_NAMESPACE_URI) : "") +
71 " xmlns:xsi=\""+XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI+"\" \n" +
72 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">");
73 indent = " ";
74 writeMetaData();
75 writeWayPoints();
76 writeRoutes();
77 writeTracks();
78 out.print("</gpx>");
79 out.flush();
80 }
81
82 private void writeAttr(IWithAttributes obj) {
83 for (String key : WPT_KEYS) {
84 if (key.equals(META_LINKS)) {
85 @SuppressWarnings("unchecked")
86 Collection<GpxLink> lValue = (Collection<GpxLink>) obj.getCollection(key);
87 if (lValue != null) {
88 for (GpxLink link : lValue) {
89 gpxLink(link);
90 }
91 }
92 } else if (key.equals(META_EXTENSIONS)) {
93 Extensions extensions = (Extensions) obj.get(key);
94 if (extensions != null) {
95 gpxExtensions(extensions);
96 }
97 } else {
98 String value = obj.getString(key);
99 if (value != null) {
100 simpleTag(key, value);
101 }
102 }
103 }
104 }
105
106 @SuppressWarnings("unchecked")
107 private void writeMetaData() {
108 Map<String, Object> attr = data.attr;
109 openln("metadata");
110
111 // write the description
112 if (attr.containsKey(META_DESC)) {
113 simpleTag("desc", (String)attr.get(META_DESC));
114 }
115
116 // write the author details
117 if (attr.containsKey(META_AUTHOR_NAME)
118 || attr.containsKey(META_AUTHOR_EMAIL)) {
119 openln("author");
120 // write the name
121 simpleTag("name", (String) attr.get(META_AUTHOR_NAME));
122 // write the email address
123 if (attr.containsKey(META_AUTHOR_EMAIL)) {
124 String[] tmp = ((String)attr.get(META_AUTHOR_EMAIL)).split("@");
125 if (tmp.length == 2) {
126 inline("email", "id=\"" + tmp[0] + "\" domain=\""+tmp[1]+"\"");
127 }
128 }
129 // write the author link
130 gpxLink((GpxLink) attr.get(META_AUTHOR_LINK));
131 closeln("author");
132 }
133
134 // write the copyright details
135 if (attr.containsKey(META_COPYRIGHT_LICENSE)
136 || attr.containsKey(META_COPYRIGHT_YEAR)) {
137 openAtt("copyright", "author=\""+ attr.get(META_COPYRIGHT_AUTHOR) +"\"");
138 if (attr.containsKey(META_COPYRIGHT_YEAR)) {
139 simpleTag("year", (String) attr.get(META_COPYRIGHT_YEAR));
140 }
141 if (attr.containsKey(META_COPYRIGHT_LICENSE)) {
142 simpleTag("license", encode((String) attr.get(META_COPYRIGHT_LICENSE)));
143 }
144 closeln("copyright");
145 }
146
147 // write links
148 if (attr.containsKey(META_LINKS)) {
149 for (GpxLink link : (Collection<GpxLink>) attr.get(META_LINKS)) {
150 gpxLink(link);
151 }
152 }
153
154 // write keywords
155 if (attr.containsKey(META_KEYWORDS)) {
156 simpleTag("keywords", (String)attr.get(META_KEYWORDS));
157 }
158
159 Bounds bounds = data.recalculateBounds();
160 if (bounds != null) {
161 String b = "minlat=\"" + bounds.getMinLat() + "\" minlon=\"" + bounds.getMinLon() +
162 "\" maxlat=\"" + bounds.getMaxLat() + "\" maxlon=\"" + bounds.getMaxLon() + "\"" ;
163 inline("bounds", b);
164 }
165
166 if (data.fromServer) {
167 openln("extensions");
168 simpleTag("josm:from-server", "true");
169 closeln("extensions");
170 }
171
172 closeln("metadata");
173 }
174
175 private void writeWayPoints() {
176 for (WayPoint pnt : data.waypoints) {
177 wayPoint(pnt, WAY_POINT);
178 }
179 }
180
181 private void writeRoutes() {
182 for (GpxRoute rte : data.routes) {
183 openln("rte");
184 writeAttr(rte);
185 for (WayPoint pnt : rte.routePoints) {
186 wayPoint(pnt, ROUTE_POINT);
187 }
188 closeln("rte");
189 }
190 }
191
192 private void writeTracks() {
193 for (GpxTrack trk : data.tracks) {
194 openln("trk");
195 writeAttr(trk);
196 for (GpxTrackSegment seg : trk.getSegments()) {
197 openln("trkseg");
198 for (WayPoint pnt : seg.getWayPoints()) {
199 wayPoint(pnt, TRACK_POINT);
200 }
201 closeln("trkseg");
202 }
203 closeln("trk");
204 }
205 }
206
207 private void openln(String tag) {
208 open(tag);
209 out.println();
210 }
211
212 private void open(String tag) {
213 out.print(indent + "<" + tag + ">");
214 indent += " ";
215 }
216
217 private void openAtt(String tag, String attributes) {
218 out.println(indent + "<" + tag + " " + attributes + ">");
219 indent += " ";
220 }
221
222 private void inline(String tag, String attributes) {
223 out.println(indent + "<" + tag + " " + attributes + "/>");
224 }
225
226 private void close(String tag) {
227 indent = indent.substring(2);
228 out.print(indent + "</" + tag + ">");
229 }
230
231 private void closeln(String tag) {
232 close(tag);
233 out.println();
234 }
235
236 /**
237 * if content not null, open tag, write encoded content, and close tag
238 * else do nothing.
239 */
240 private void simpleTag(String tag, String content) {
241 if (content != null && content.length() > 0) {
242 open(tag);
243 out.print(encode(content));
244 out.println("</" + tag + ">");
245 indent = indent.substring(2);
246 }
247 }
248
249 /**
250 * output link
251 */
252 private void gpxLink(GpxLink link) {
253 if (link != null) {
254 openAtt("link", "href=\"" + link.uri + "\"");
255 simpleTag("text", link.text);
256 simpleTag("type", link.type);
257 closeln("link");
258 }
259 }
260
261 /**
262 * output a point
263 */
264 private void wayPoint(WayPoint pnt, int mode) {
265 String type;
266 switch(mode) {
267 case WAY_POINT:
268 type = "wpt";
269 break;
270 case ROUTE_POINT:
271 type = "rtept";
272 break;
273 case TRACK_POINT:
274 type = "trkpt";
275 break;
276 default:
277 throw new RuntimeException(tr("Unknown mode {0}.", mode));
278 }
279 if (pnt != null) {
280 LatLon c = pnt.getCoor();
281 String coordAttr = "lat=\"" + c.lat() + "\" lon=\"" + c.lon() + "\"";
282 if (pnt.attr.isEmpty()) {
283 inline(type, coordAttr);
284 } else {
285 openAtt(type, coordAttr);
286 writeAttr(pnt);
287 closeln(type);
288 }
289 }
290 }
291
292 private void gpxExtensions(Extensions extensions) {
293 if (extensions != null && !extensions.isEmpty()) {
294 openln("extensions");
295 for (Entry<String, String> e : extensions.entrySet()) {
296 simpleTag("josm:" + e.getKey(), e.getValue());
297 }
298 closeln("extensions");
299 }
300 }
301}
Note: See TracBrowser for help on using the repository browser.