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

Last change on this file since 5444 was 5397, checked in by bastiK, 12 years ago

fix element ordering when writing gpx (see #7927)

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
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.io.UnsupportedEncodingException;
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.List;
14import java.util.Map;
15
16import org.openstreetmap.josm.data.Bounds;
17import org.openstreetmap.josm.data.coor.LatLon;
18import org.openstreetmap.josm.data.gpx.GpxData;
19import org.openstreetmap.josm.data.gpx.GpxLink;
20import org.openstreetmap.josm.data.gpx.GpxRoute;
21import org.openstreetmap.josm.data.gpx.GpxTrack;
22import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
23import org.openstreetmap.josm.data.gpx.WayPoint;
24
25/**
26 * Writes GPX files from GPX data or OSM data.
27 */
28public class GpxWriter extends XmlWriter {
29
30 public GpxWriter(PrintWriter out) {
31 super(out);
32 }
33
34 public GpxWriter(OutputStream out) throws UnsupportedEncodingException {
35 super(new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
36 }
37
38 public GpxWriter() {
39 super(null);
40 //sorry for this one here, this will be cleaned up once the new scheme works
41 }
42
43 private GpxData data;
44 private String indent = "";
45
46 private final static int WAY_POINT = 0;
47 private final static int ROUTE_POINT = 1;
48 private final static int TRACK_POINT = 2;
49
50 public void write(GpxData data) {
51 this.data = data;
52 out.println("<?xml version='1.0' encoding='UTF-8'?>");
53 out.println("<gpx version=\"1.1\" creator=\"JOSM GPX export\" xmlns=\"http://www.topografix.com/GPX/1/1\"\n" +
54 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
55 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">");
56 indent = " ";
57 writeMetaData();
58 writeWayPoints();
59 writeRoutes();
60 writeTracks();
61 out.print("</gpx>");
62 out.flush();
63 }
64
65 public static List<String> WPT_KEYS = Arrays.asList("ele", "time", "magvar", "geoidheight",
66 "name", "cmt", "desc", "src", GpxData.META_LINKS, "sym", "number", "type",
67 "fix", "sat", "hdop", "vdop", "pdop", "ageofdgpsdata", "dgpsid");
68 @SuppressWarnings("unchecked")
69 private void writeAttr(Map<String, Object> attr) {
70 for (String key : WPT_KEYS) {
71 Object value = attr.get(key);
72 if (value != null) {
73 if (key.equals(GpxData.META_LINKS)) {
74 for (GpxLink link : (Collection<GpxLink>) value) {
75 gpxLink(link);
76 }
77 } else {
78 simpleTag(key, value.toString());
79 }
80 }
81 }
82 }
83
84 @SuppressWarnings("unchecked")
85 private void writeMetaData() {
86 Map<String, Object> attr = data.attr;
87 openln("metadata");
88
89 // write the description
90 if (attr.containsKey(GpxData.META_DESC)) {
91 simpleTag("desc", (String)attr.get(GpxData.META_DESC));
92 }
93
94 // write the author details
95 if (attr.containsKey(GpxData.META_AUTHOR_NAME)
96 || attr.containsKey(GpxData.META_AUTHOR_EMAIL)) {
97 openln("author");
98 // write the name
99 simpleTag("name", (String) attr.get(GpxData.META_AUTHOR_NAME));
100 // write the email address
101 if(attr.containsKey(GpxData.META_AUTHOR_EMAIL)) {
102 String[] tmp = ((String)attr.get(GpxData.META_AUTHOR_EMAIL)).split("@");
103 if(tmp.length == 2) {
104 inline("email", "id=\"" + tmp[0] + "\" domain=\""+tmp[1]+"\"");
105 }
106 }
107 // write the author link
108 gpxLink((GpxLink) attr.get(GpxData.META_AUTHOR_LINK));
109 closeln("author");
110 }
111
112 // write the copyright details
113 if(attr.containsKey(GpxData.META_COPYRIGHT_LICENSE)
114 || attr.containsKey(GpxData.META_COPYRIGHT_YEAR)) {
115 openAtt("copyright", "author=\""+ attr.get(GpxData.META_COPYRIGHT_AUTHOR) +"\"");
116 if(attr.containsKey(GpxData.META_COPYRIGHT_YEAR)) {
117 simpleTag("year", (String) attr.get(GpxData.META_COPYRIGHT_YEAR));
118 }
119 if(attr.containsKey(GpxData.META_COPYRIGHT_LICENSE)) {
120 simpleTag("license", encode((String) attr.get(GpxData.META_COPYRIGHT_LICENSE)));
121 }
122 closeln("copyright");
123 }
124
125 // write links
126 if(attr.containsKey(GpxData.META_LINKS)) {
127 for (GpxLink link : (Collection<GpxLink>) attr.get(GpxData.META_LINKS)) {
128 gpxLink(link);
129 }
130 }
131
132 // write keywords
133 if (attr.containsKey(GpxData.META_KEYWORDS)) {
134 simpleTag("keywords", (String)attr.get(GpxData.META_KEYWORDS));
135 }
136
137 Bounds bounds = data.recalculateBounds();
138 if(bounds != null)
139 {
140 String b = "minlat=\"" + bounds.getMin().lat() + "\" minlon=\"" + bounds.getMin().lon() +
141 "\" maxlat=\"" + bounds.getMax().lat() + "\" maxlon=\"" + bounds.getMax().lon() + "\"" ;
142 inline("bounds", b);
143 }
144
145 closeln("metadata");
146 }
147
148 private void writeWayPoints() {
149 for (WayPoint pnt : data.waypoints) {
150 wayPoint(pnt, WAY_POINT);
151 }
152 }
153
154 private void writeRoutes() {
155 for (GpxRoute rte : data.routes) {
156 openln("rte");
157 writeAttr(rte.attr);
158 for (WayPoint pnt : rte.routePoints) {
159 wayPoint(pnt, ROUTE_POINT);
160 }
161 closeln("rte");
162 }
163 }
164
165 private void writeTracks() {
166 for (GpxTrack trk : data.tracks) {
167 openln("trk");
168 writeAttr(trk.getAttributes());
169 for (GpxTrackSegment seg : trk.getSegments()) {
170 openln("trkseg");
171 for (WayPoint pnt : seg.getWayPoints()) {
172 wayPoint(pnt, TRACK_POINT);
173 }
174 closeln("trkseg");
175 }
176 closeln("trk");
177 }
178 }
179
180 private void openln(String tag) {
181 open(tag);
182 out.println();
183 }
184
185 private void open(String tag) {
186 out.print(indent + "<" + tag + ">");
187 indent += " ";
188 }
189
190 private void openAtt(String tag, String attributes) {
191 out.println(indent + "<" + tag + " " + attributes + ">");
192 indent += " ";
193 }
194
195 private void inline(String tag, String attributes) {
196 out.println(indent + "<" + tag + " " + attributes + "/>");
197 }
198
199 private void close(String tag) {
200 indent = indent.substring(2);
201 out.print(indent + "</" + tag + ">");
202 }
203
204 private void closeln(String tag) {
205 close(tag);
206 out.println();
207 }
208
209 /**
210 * if content not null, open tag, write encoded content, and close tag
211 * else do nothing.
212 */
213 private void simpleTag(String tag, String content) {
214 if (content != null && content.length() > 0) {
215 open(tag);
216 out.print(encode(content));
217 out.println("</" + tag + ">");
218 indent = indent.substring(2);
219 }
220 }
221
222 /**
223 * output link
224 */
225 private void gpxLink(GpxLink link) {
226 if (link != null) {
227 openAtt("link", "href=\"" + link.uri + "\"");
228 simpleTag("text", link.text);
229 simpleTag("type", link.type);
230 closeln("link");
231 }
232 }
233
234 /**
235 * output a point
236 */
237 private void wayPoint(WayPoint pnt, int mode) {
238 String type;
239 switch(mode) {
240 case WAY_POINT:
241 type = "wpt";
242 break;
243 case ROUTE_POINT:
244 type = "rtept";
245 break;
246 case TRACK_POINT:
247 type = "trkpt";
248 break;
249 default:
250 throw new RuntimeException(tr("Unknown mode {0}.", mode));
251 }
252 if (pnt != null) {
253 LatLon c = pnt.getCoor();
254 String coordAttr = "lat=\"" + c.lat() + "\" lon=\"" + c.lon() + "\"";
255 if (pnt.attr.isEmpty()) {
256 inline(type, coordAttr);
257 } else {
258 openAtt(type, coordAttr);
259 writeAttr(pnt.attr);
260 closeln(type);
261 }
262 }
263 }
264}
Note: See TracBrowser for help on using the repository browser.