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

Last change on this file since 2751 was 2604, checked in by Gubaer, 14 years ago

New: JOSM reading, writing, merging changeset attribute
fixed #4090: Add changeset:* search option to JOSM's search engine

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