source: osm/applications/editors/josm/plugins/CommandLine/src/CommandLine/OsmToCmd.java@ 25038

Last change on this file since 25038 was 25038, checked in by hind, 13 years ago

CommandLine.jar and some quickfixes

File size: 13.3 KB
Line 
1package CommandLine;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.io.InputStream;
6import java.util.ArrayList;
7import java.util.HashMap;
8import java.util.LinkedList;
9import java.util.List;
10import java.util.Map;
11
12import javax.xml.parsers.ParserConfigurationException;
13import javax.xml.parsers.SAXParserFactory;
14
15import org.openstreetmap.josm.Main;
16import org.openstreetmap.josm.command.AddCommand;
17import org.openstreetmap.josm.command.ChangeCommand;
18import org.openstreetmap.josm.command.ChangeNodesCommand;
19import org.openstreetmap.josm.command.Command;
20import org.openstreetmap.josm.command.DeleteCommand;
21import org.openstreetmap.josm.data.coor.LatLon;
22import org.openstreetmap.josm.data.osm.*;
23import org.openstreetmap.josm.io.IllegalDataException;
24import org.openstreetmap.josm.io.OsmDataParsingException;
25import org.openstreetmap.josm.io.UTFInputStreamReader;
26import org.openstreetmap.josm.tools.DateUtils;
27
28import org.xml.sax.Attributes;
29import org.xml.sax.InputSource;
30import org.xml.sax.Locator;
31import org.xml.sax.SAXException;
32import org.xml.sax.SAXParseException;
33import org.xml.sax.helpers.DefaultHandler;
34
35final class OsmToCmd {
36 private final DataSet targetDataSet;
37 private final LinkedList<Command> cmds = new LinkedList<Command>();
38 private HashMap<PrimitiveId, OsmPrimitive> externalIdMap; // Maps external ids to internal primitives
39
40 public OsmToCmd(DataSet targetDataSet, InputStream stream) throws IllegalDataException {
41 this.targetDataSet = targetDataSet;
42 externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>();
43 parseStream(stream);
44 }
45
46 private void parseStream(InputStream stream) throws IllegalDataException {
47 try {
48 InputSource inputSource = new InputSource(UTFInputStreamReader.create(stream, "UTF-8"));
49 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new Parser());
50 } catch(ParserConfigurationException e) {
51 throw new IllegalDataException(e.getMessage(), e);
52 } catch (SAXParseException e) {
53 throw new IllegalDataException(tr("Line {0} column {1}: ", e.getLineNumber(), e.getColumnNumber()) + e.getMessage(), e);
54 } catch(SAXException e) {
55 throw new IllegalDataException(e.getMessage(), e);
56 } catch(Exception e) {
57 throw new IllegalDataException(e);
58 }
59 }
60
61 public LinkedList<Command> getCommandList() {
62 return cmds;
63 }
64
65 private class Parser extends DefaultHandler {
66 private Locator locator;
67
68 @Override
69 public void setDocumentLocator(Locator locator) {
70 this.locator = locator;
71 }
72
73 protected void throwException(String msg) throws OsmDataParsingException {
74 throw new OsmDataParsingException(msg).rememberLocation(locator);
75 }
76
77 private OsmPrimitive currentPrimitive;
78 private long currentExternalId;
79 private List<Node> currentWayNodes = new ArrayList<Node>();
80 private List<RelationMember> currentRelationMembers = new ArrayList<RelationMember>();
81
82 @Override
83 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
84 try {
85 if (qName.equals("osm")) {
86 if (atts == null) {
87 throwException(tr("Missing mandatory attribute ''{0}'' of XML element {1}.", "version", "osm"));
88 }
89 String v = atts.getValue("version");
90 if (v == null) {
91 throwException(tr("Missing mandatory attribute ''{0}''.", "version"));
92 }
93 if ( !(v.equals("0.6")) ) {
94 throwException(tr("Unsupported version: {0}", v));
95 }
96
97 // ---- PARSING NODES AND WAYS ----
98
99 } else if (qName.equals("node")) {
100 Node n = new Node();
101 NodeData source = new NodeData();
102 source.setCoor(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
103 readCommon(atts, source);
104 Node target = (Node)targetDataSet.getPrimitiveById( source.getUniqueId(), source.getType() );
105
106 if (target == null || !(source.isModified() || source.isDeleted()) )
107 n.load(source);
108 else {
109 n.cloneFrom(target);
110 n.load(source);
111 }
112
113 currentPrimitive = n;
114 externalIdMap.put(source.getPrimitiveId(), (OsmPrimitive)n);
115 //System.out.println("NODE " + String.valueOf(source.getUniqueId()) + " HAS MAPPED TO INNER " + String.valueOf(n.getUniqueId()) );
116 }
117 else if (qName.equals("way")) {
118 Way w = new Way();
119 WayData source = new WayData();
120 readCommon(atts, source);
121 Way target = (Way)targetDataSet.getPrimitiveById( source.getUniqueId(), source.getType() );
122
123 if (target == null || !(source.isModified() || source.isDeleted()) )
124 w.load(source);
125 else {
126 w.cloneFrom(target);
127 w.load(source);
128 }
129
130 currentPrimitive = w;
131 currentWayNodes.clear();
132 externalIdMap.put(source.getPrimitiveId(), (OsmPrimitive)w);
133 //System.out.println("WAY " + String.valueOf(source.getUniqueId()) + " HAS MAPPED TO INNER " + String.valueOf(w.getUniqueId()) );
134 }
135 else if (qName.equals("nd")) {
136 if (atts.getValue("ref") == null)
137 throwException(tr("Missing mandatory attribute ''{0}'' on <nd> of way {1}.", "ref", currentPrimitive.getUniqueId()));
138 long id = getLong(atts, "ref");
139 if (id == 0)
140 throwException(tr("Illegal value of attribute ''ref'' of element <nd>. Got {0}.", id) );
141 //System.out.println("NODE " + String.valueOf(id) + " HAS ADDED TO WAY " + String.valueOf(currentPrimitive.getUniqueId()));
142 Node node = (Node)externalIdMap.get(new SimplePrimitiveId(id, OsmPrimitiveType.NODE));
143 if (node == null || node.isModified()) {
144 node = (Node)targetDataSet.getPrimitiveById( new SimplePrimitiveId(id, OsmPrimitiveType.NODE) );
145 if (node == null)
146 throwException(tr("Missing definition of new object with id {0}.", id));
147 }
148 currentWayNodes.add(node);
149 }
150 // ---- PARSING RELATIONS ----
151
152 else if (qName.equals("relation")) {
153 Relation r = new Relation();
154 RelationData source = new RelationData();
155 readCommon(atts, source);
156 Relation target = (Relation)targetDataSet.getPrimitiveById( source.getUniqueId(), source.getType() );
157
158 if (target == null || !(source.isModified() || source.isDeleted()) )
159 r.load(source);
160 else {
161 r.cloneFrom(target);
162 r.load(source);
163 }
164
165 currentPrimitive = r;
166 currentRelationMembers.clear();
167 externalIdMap.put(source.getPrimitiveId(), (OsmPrimitive)r);
168 //System.out.println("RELATION " + String.valueOf(source.getUniqueId()) + " HAS MAPPED TO INNER " + String.valueOf(r.getUniqueId()) );
169 }
170 else if (qName.equals("member")) {
171 if (atts.getValue("ref") == null)
172 throwException(tr("Missing mandatory attribute ''{0}'' on <member> of relation {1}.", "ref", currentPrimitive.getUniqueId()));
173 long id = getLong(atts, "ref");
174 if (id == 0)
175 throwException(tr("Illegal value of attribute ''ref'' of element <nd>. Got {0}.", id) );
176
177 OsmPrimitiveType type = OsmPrimitiveType.NODE;
178 String value = atts.getValue("type");
179 if (value == null) {
180 throwException(tr("Missing attribute ''type'' on member {0} in relation {1}.", Long.toString(id), Long.toString(currentPrimitive.getUniqueId())));
181 }
182 try {
183 type = OsmPrimitiveType.fromApiTypeName(value);
184 }
185 catch(IllegalArgumentException e) {
186 throwException(tr("Illegal value for attribute ''type'' on member {0} in relation {1}. Got {2}.", Long.toString(id), Long.toString(currentPrimitive.getUniqueId()), value));
187 }
188
189 String role = atts.getValue("role");
190
191 //System.out.println("MEMBER " + value.toUpperCase() + " " +String.valueOf(id) + " HAS ADDED TO RELATION " + String.valueOf(currentPrimitive.getUniqueId()));
192 OsmPrimitive member = externalIdMap.get(new SimplePrimitiveId(id, type));
193 if (member == null) {
194 member = targetDataSet.getPrimitiveById(new SimplePrimitiveId(id, type));
195 if (member == null)
196 throwException(tr("Missing definition of new object with id {0}.", id));
197 }
198 RelationMember relationMember = new RelationMember(role, member);
199 currentRelationMembers.add(relationMember);
200 }
201
202 // ---- PARSING TAGS (applicable to all objects) ----
203
204 else if (qName.equals("tag")) {
205 String key = atts.getValue("k");
206 String value = atts.getValue("v");
207 if (key == null || value == null) {
208 throwException(tr("Missing key or value attribute in tag."));
209 }
210 currentPrimitive.put(key.intern(), value.intern());
211 }
212 else {
213 System.out.println(tr("Undefined element ''{0}'' found in input stream. Skipping.", qName));
214 }
215 }
216 catch (Exception e) {
217 throw new SAXParseException(e.getMessage(), locator, e);
218 }
219 }
220
221 @Override
222 public void endElement(String namespaceURI, String localName, String qName) {
223 if (qName.equals("node")) {
224 if (currentPrimitive.isDeleted()) {
225 cmds.add(new DeleteCommand( targetDataSet.getPrimitiveById(currentPrimitive.getPrimitiveId()) ));
226 }
227 else if (currentPrimitive.isModified()) {
228 //System.out.println(String.valueOf(currentPrimitive.getUniqueId()) + " IS MODIFIED BY SCRIPT");
229 cmds.add(new ChangeCommand(Main.map.mapView.getEditLayer(), (Node)targetDataSet.getPrimitiveById(currentPrimitive.getPrimitiveId()), currentPrimitive));
230 }
231 else if (currentPrimitive.isNew()) {
232 cmds.add(new AddCommand(currentPrimitive));
233 }
234 }
235 else if (qName.equals("way")) {
236 ((Way)currentPrimitive).setNodes(currentWayNodes);
237 if (currentPrimitive.isDeleted()) {
238 cmds.add(new DeleteCommand( targetDataSet.getPrimitiveById(currentPrimitive.getPrimitiveId()) ));
239 }
240 else if (currentPrimitive.isModified()) {
241 cmds.add(new ChangeCommand(Main.map.mapView.getEditLayer(), (Way)targetDataSet.getPrimitiveById(currentPrimitive.getPrimitiveId()), currentPrimitive));
242 }
243 else if (currentPrimitive.isNew()) {
244 cmds.add(new AddCommand(currentPrimitive));
245 }
246 }
247 else if (qName.equals("relation")) {
248 ((Relation)currentPrimitive).setMembers(currentRelationMembers);
249 if (currentPrimitive.isDeleted()) {
250 cmds.add(new DeleteCommand( targetDataSet.getPrimitiveById(currentPrimitive.getPrimitiveId()) ));
251 }
252 else if (currentPrimitive.isModified()) {
253 cmds.add(new ChangeCommand(Main.map.mapView.getEditLayer(), (Relation)targetDataSet.getPrimitiveById(currentPrimitive.getPrimitiveId()), currentPrimitive));
254 }
255 else if (currentPrimitive.isNew()) {
256 cmds.add(new AddCommand(currentPrimitive));
257 }
258 }
259 }
260
261 private double getDouble(Attributes atts, String value) {
262 return Double.parseDouble(atts.getValue(value));
263 }
264
265 private long getLong(Attributes atts, String name) throws SAXException {
266 String value = atts.getValue(name);
267 if (value == null) {
268 throwException(tr("Missing required attribute ''{0}''.",name));
269 }
270 try {
271 return Long.parseLong(value);
272 }
273 catch(NumberFormatException e) {
274 throwException(tr("Illegal long value for attribute ''{0}''. Got ''{1}''.",name, value));
275 }
276 return 0; // should not happen
277 }
278
279 private User createUser(String uid, String name) throws SAXException {
280 if (uid == null) {
281 if (name == null)
282 return null;
283 return User.createLocalUser(name);
284 }
285 try {
286 long id = Long.parseLong(uid);
287 return User.createOsmUser(id, name);
288 }
289 catch(NumberFormatException e) {
290 throwException(tr("Illegal value for attribute ''uid''. Got ''{0}''.", uid));
291 }
292 return null;
293 }
294
295 void readCommon(Attributes atts, PrimitiveData current) throws SAXException {
296 current.setId(getLong(atts, "id"));
297 if (current.getUniqueId() == 0) {
298 throwException(tr("Illegal object with ID=0."));
299 }
300
301 String time = atts.getValue("timestamp");
302 if (time != null && time.length() != 0) {
303 current.setTimestamp(DateUtils.fromString(time));
304 }
305
306 String user = atts.getValue("user");
307 String uid = atts.getValue("uid");
308 current.setUser(createUser(uid, user));
309
310 String visible = atts.getValue("visible");
311 if (visible != null) {
312 current.setVisible(Boolean.parseBoolean(visible));
313 }
314
315 String versionString = atts.getValue("version");
316 int version = 0;
317 if (versionString != null) {
318 try {
319 version = Integer.parseInt(versionString);
320 } catch(NumberFormatException e) {
321 throwException(tr("Illegal value for attribute ''version'' on OSM primitive with ID {0}. Got {1}.", Long.toString(current.getUniqueId()), versionString));
322 }
323 }
324 current.setVersion(version);
325
326 String action = atts.getValue("action");
327 if (action == null) {
328 // do nothing
329 } else if (action.equals("delete")) {
330 current.setDeleted(true);
331 current.setModified(current.isVisible());
332 } else if (action.equals("modify")) {
333 current.setModified(true);
334 }
335
336 String v = atts.getValue("changeset");
337 if (v == null) {
338 current.setChangesetId(0);
339 } else {
340 try {
341 current.setChangesetId(Integer.parseInt(v));
342 } catch(NumberFormatException e) {
343 if (current.getUniqueId() <= 0) {
344 System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.getUniqueId()));
345 current.setChangesetId(0);
346 } else {
347 throwException(tr("Illegal value for attribute ''changeset''. Got {0}.", v));
348 }
349 }
350 if (current.getChangesetId() <=0) {
351 if (current.getUniqueId() <= 0) {
352 System.out.println(tr("Illegal value for attribute ''changeset'' on new object {1}. Got {0}. Resetting to 0.", v, current.getUniqueId()));
353 current.setChangesetId(0);
354 } else {
355 throwException(tr("Illegal value for attribute ''changeset''. Got {0}.", v));
356 }
357 }
358 }
359 }
360 }
361}
Note: See TracBrowser for help on using the repository browser.