source: josm/trunk/src/org/openstreetmap/josm/io/OsmWriter.java@ 2474

Last change on this file since 2474 was 2381, checked in by jttt, 14 years ago

Change most occurrences of Dataset.nodes/ways/relations with getNodes()/../.. or addPrimitive

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import java.io.PrintWriter;
5import java.util.HashMap;
6import java.util.Map.Entry;
7
8import org.openstreetmap.josm.data.coor.CoordinateFormat;
9import org.openstreetmap.josm.data.osm.Changeset;
10import org.openstreetmap.josm.data.osm.DataSet;
11import org.openstreetmap.josm.data.osm.DataSource;
12import org.openstreetmap.josm.data.osm.Node;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
15import org.openstreetmap.josm.data.osm.Relation;
16import org.openstreetmap.josm.data.osm.RelationMember;
17import org.openstreetmap.josm.data.osm.Tagged;
18import org.openstreetmap.josm.data.osm.Way;
19import org.openstreetmap.josm.data.osm.visitor.Visitor;
20import org.openstreetmap.josm.tools.DateUtils;
21
22/**
23 * Save the dataset into a stream as osm intern xml format. This is not using any
24 * xml library for storing.
25 * @author imi
26 */
27public class OsmWriter extends XmlWriter implements Visitor {
28
29 public final String DEFAULT_API_VERSION = "0.6";
30
31 /**
32 * The counter for newly created objects. Starts at -1 and goes down.
33 */
34 private long newIdCounter = -1;
35
36 /**
37 * All newly created ids and their primitive that uses it. This is a back reference
38 * map to allow references to use the correnct primitives.
39 */
40 public HashMap<OsmPrimitive, Long> usedNewIds = new HashMap<OsmPrimitive, Long>();
41
42 private boolean osmConform;
43 private boolean withBody = true;
44 private String version;
45 private Changeset changeset;
46
47 public OsmWriter(PrintWriter out, boolean osmConform, String version) {
48 super(out);
49 this.osmConform = osmConform;
50 this.version = (version == null ? DEFAULT_API_VERSION : version);
51 }
52
53 public void setWithBody(boolean wb) {
54 this.withBody = wb;
55 }
56 public void setChangeset(Changeset cs) {
57 this.changeset = cs;
58 }
59 public void setVersion(String v) {
60 this.version = v;
61 }
62
63 public void header() {
64 out.println("<?xml version='1.0' encoding='UTF-8'?>");
65 out.print("<osm version='");
66 out.print(version);
67 out.println("' generator='JOSM'>");
68 }
69 public void footer() {
70 out.println("</osm>");
71 }
72
73 public void writeContent(DataSet ds) {
74 for (Node n : ds.getNodes()) {
75 if (shouldWrite(n)) {
76 visit(n);
77 }
78 }
79 for (Way w : ds.getWays()) {
80 if (shouldWrite(w)) {
81 visit(w);
82 }
83 }
84 for (Relation e : ds.getRelations()) {
85 if (shouldWrite(e)) {
86 visit(e);
87 }
88 }
89 }
90
91 private boolean shouldWrite(OsmPrimitive osm) {
92 return !osm.isNew() || !osm.isDeleted();
93 }
94
95 public void writeDataSources(DataSet ds) {
96 for (DataSource s : ds.dataSources) {
97 out.println(" <bounds minlat='"
98 + s.bounds.getMin().lat()+"' minlon='"
99 + s.bounds.getMin().lon()+"' maxlat='"
100 + s.bounds.getMax().lat()+"' maxlon='"
101 + s.bounds.getMax().lon()
102 +"' origin='"+XmlWriter.encode(s.origin)+"' />");
103 }
104 }
105
106 public void visit(Node n) {
107 if (n.incomplete) return;
108 addCommon(n, "node");
109 out.print(" lat='"+n.getCoor().lat()+"' lon='"+n.getCoor().lon()+"'");
110 if (!withBody) {
111 out.println("/>");
112 } else {
113 addTags(n, "node", true);
114 }
115 }
116
117 public void visit(Way w) {
118 if (w.incomplete) return;
119 addCommon(w, "way");
120 if (!withBody) {
121 out.println("/>");
122 } else {
123 out.println(">");
124 for (Node n : w.getNodes()) {
125 out.println(" <nd ref='"+getUsedId(n)+"' />");
126 }
127 addTags(w, "way", false);
128 }
129 }
130
131 public void visit(Relation e) {
132 if (e.incomplete) return;
133 addCommon(e, "relation");
134 if (!withBody) {
135 out.println("/>");
136 } else {
137 out.println(">");
138 for (RelationMember em : e.getMembers()) {
139 out.print(" <member type='");
140 out.print(OsmPrimitiveType.from(em.getMember()).getAPIName());
141 out.println("' ref='"+getUsedId(em.getMember())+"' role='" +
142 XmlWriter.encode(em.getRole()) + "' />");
143 }
144 addTags(e, "relation", false);
145 }
146 }
147
148 public void visit(Changeset cs) {
149 out.print(" <changeset ");
150 out.print(" id='"+cs.getId()+"'");
151 if (cs.getUser() != null) {
152 out.print(" user='"+cs.getUser().getName() +"'");
153 out.print(" uid='"+cs.getUser().getId() +"'");
154 }
155 if (cs.getCreatedAt() != null) {
156 out.print(" created_at='"+DateUtils.fromDate(cs.getCreatedAt()) +"'");
157 }
158 if (cs.getClosedAt() != null) {
159 out.print(" closed_at='"+DateUtils.fromDate(cs.getClosedAt()) +"'");
160 }
161 out.print(" open='"+ (cs.isOpen() ? "true" : "false") +"'");
162 if (cs.getMin() != null) {
163 out.print(" min_lon='"+ cs.getMin().lonToString(CoordinateFormat.DECIMAL_DEGREES) +"'");
164 out.print(" min_lat='"+ cs.getMin().latToString(CoordinateFormat.DECIMAL_DEGREES) +"'");
165 }
166 if (cs.getMax() != null) {
167 out.print(" max_lon='"+ cs.getMin().lonToString(CoordinateFormat.DECIMAL_DEGREES) +"'");
168 out.print(" max_lat='"+ cs.getMin().latToString(CoordinateFormat.DECIMAL_DEGREES) +"'");
169 }
170 out.println(">");
171 addTags(cs, "changeset", false); // also writes closing </changeset>
172 }
173
174 /**
175 * Return the id for the given osm primitive (may access the usedId map)
176 */
177 private long getUsedId(OsmPrimitive osm) {
178 if (!osm.isNew())
179 return osm.getId();
180 if (usedNewIds.containsKey(osm))
181 return usedNewIds.get(osm);
182 usedNewIds.put(osm, newIdCounter);
183 return osmConform ? 0 : newIdCounter--;
184 }
185
186 private void addTags(Tagged osm, String tagname, boolean tagOpen) {
187 if (osm.hasKeys()) {
188 if (tagOpen) {
189 out.println(">");
190 }
191 for (Entry<String, String> e : osm.getKeys().entrySet()) {
192 if ((osm instanceof Changeset) || !("created_by".equals(e.getKey()))) {
193 out.println(" <tag k='"+ XmlWriter.encode(e.getKey()) +
194 "' v='"+XmlWriter.encode(e.getValue())+ "' />");
195 }
196 }
197 out.println(" </" + tagname + ">");
198 } else if (tagOpen) {
199 out.println(" />");
200 } else {
201 out.println(" </" + tagname + ">");
202 }
203 }
204
205 /**
206 * Add the common part as the form of the tag as well as the XML attributes
207 * id, action, user, and visible.
208 */
209 private void addCommon(OsmPrimitive osm, String tagname) {
210 long id = getUsedId(osm);
211 out.print(" <"+tagname);
212 if (id != 0) {
213 out.print(" id='"+getUsedId(osm)+"'");
214 }
215 if (!osmConform) {
216 String action = null;
217 if (osm.isDeleted()) {
218 action = "delete";
219 } else if (osm.isModified()) {
220 action = "modify";
221 }
222 if (action != null) {
223 out.print(" action='"+action+"'");
224 }
225 }
226 if (!osm.isTimestampEmpty()) {
227 out.print(" timestamp='"+DateUtils.fromDate(osm.getTimestamp())+"'");
228 }
229 // user and visible added with 0.4 API
230 if (osm.getUser() != null) {
231 if(osm.getUser().isLocalUser()) {
232 out.print(" user='"+XmlWriter.encode(osm.getUser().getName())+"'");
233 } else if (osm.getUser().isOsmUser()) {
234 // uid added with 0.6
235 out.print(" uid='"+ osm.getUser().getId()+"'");
236 out.print(" user='"+XmlWriter.encode(osm.getUser().getName())+"'");
237 }
238 }
239 out.print(" visible='"+osm.isVisible()+"'");
240 if (osm.getVersion() != 0) {
241 out.print(" version='"+osm.getVersion()+"'");
242 }
243 if (this.changeset != null && this.changeset.getId() != 0) {
244 out.print(" changeset='"+this.changeset.getId()+"'" );
245 }
246 }
247
248 public void close() {
249 out.close();
250 }
251
252 public void flush() {
253 out.flush();
254 }
255}
Note: See TracBrowser for help on using the repository browser.