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

Last change on this file since 3734 was 3336, checked in by stoecker, 14 years ago

#close #5135 - allow undeleting without recreating object - patch by Upliner

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