Changeset 1690 in josm for trunk/src/org/openstreetmap/josm/io
- Timestamp:
- 2009-06-23T22:03:37+02:00 (17 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/io
- Files:
-
- 1 added
- 2 edited
-
MultiFetchServerObjectReader.java (added)
-
OsmApi.java (modified) (4 diffs)
-
OsmReader.java (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/io/OsmApi.java
r1688 r1690 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.EventQueue; 6 7 import java.io.BufferedReader; 7 8 import java.io.BufferedWriter; … … 323 324 } 324 325 notifyStatusMessage(tr("Uploading...")); 326 setAutoProgressIndication(true); 325 327 326 328 String diff = duv.getDocument(); … … 330 332 } catch(Exception e) { 331 333 throw new OsmTransferException(e); 334 } finally { 335 setAutoProgressIndication(false); 332 336 } 333 337 … … 481 485 Main.pleaseWaitDlg.progress.setValue(current + delta); 482 486 } 487 488 489 protected void setAutoProgressIndication(final boolean enabled) { 490 EventQueue.invokeLater( 491 new Runnable() { 492 public void run() { 493 Main.pleaseWaitDlg.setIndeterminate(enabled); 494 } 495 } 496 ); 497 } 483 498 } -
trunk/src/org/openstreetmap/josm/io/OsmReader.java
r1677 r1690 9 9 import java.util.ArrayList; 10 10 import java.util.Collection; 11 import java.util.Date; 11 12 import java.util.HashMap; 13 import java.util.HashSet; 12 14 import java.util.LinkedList; 13 15 import java.util.Map; 16 import java.util.Set; 14 17 import java.util.Map.Entry; 15 18 … … 29 32 import org.openstreetmap.josm.data.osm.Way; 30 33 import org.openstreetmap.josm.data.osm.visitor.AddVisitor; 31 import org.openstreetmap.josm.data.osm.visitor.Visitor;32 34 import org.openstreetmap.josm.gui.PleaseWaitDialog; 33 35 import org.openstreetmap.josm.tools.DateUtils; … … 49 51 public class OsmReader { 50 52 51 // static long tagsN = 0; 52 // static long nodesN = 0; 53 // static long waysN = 0; 54 // static long relationsN = 0; 55 // static long membersN = 0; 56 57 static InputStream currSource; 58 59 /** 60 * This is used as (readonly) source for finding missing references when not transferred in the 61 * file. 62 */ 63 private DataSet references; 64 65 /** 66 * The dataset to add parsed objects to. 67 */ 68 private DataSet ds = new DataSet(); 69 public DataSet getDs() { return ds; } 70 71 /** 72 * Record warnings. If there were any data inconsistencies, append 73 * a newline-terminated string. 74 */ 75 private String parseNotes = new String(); 76 private int parseNotesCount = 0; 77 public String getParseNotes() { 78 return parseNotes; 79 } 80 81 /** 82 * The visitor to use to add the data to the set. 83 */ 84 private AddVisitor adder = new AddVisitor(ds); 85 86 /** 87 * All read nodes after phase 1. 88 */ 89 private Map<Long, Node> nodes = new HashMap<Long, Node>(); 90 91 // TODO: What the hack? Is this really from me? Please, clean this up! 92 private static class OsmPrimitiveData extends OsmPrimitive { 93 @Override public void visit(Visitor visitor) {} 94 public int compareTo(OsmPrimitive o) {return 0;} 95 96 public void copyTo(OsmPrimitive osm) { 97 osm.id = id; 98 osm.keys = keys; 99 osm.modified = modified; 100 osm.selected = selected; 101 osm.deleted = deleted; 102 osm.setTimestamp(getTimestamp()); 103 osm.user = user; 104 osm.visible = visible; 105 osm.version = version; 106 osm.mappaintStyle = null; 107 } 108 } 109 110 /** 111 * Used as a temporary storage for relation members, before they 112 * are resolved into pointers to real objects. 113 */ 114 private static class RelationMemberData { 115 public String type; 116 public long id; 117 public RelationMember relationMember; 118 } 119 120 /** 121 * Data structure for the remaining way objects 122 */ 123 private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>(); 124 125 /** 126 * Data structure for relation objects 127 */ 128 private Map<OsmPrimitiveData, Collection<RelationMemberData>> relations = new HashMap<OsmPrimitiveData, Collection<RelationMemberData>>(); 129 130 private class Parser extends DefaultHandler { 131 /** 132 * The current osm primitive to be read. 133 */ 134 private OsmPrimitive current; 135 private String generator; 136 private Map<String, String> keys = new HashMap<String, String>(); 137 // int n = 0; 138 139 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 140 try { 141 // if(n%100000 == 0) { 142 // try { 143 // FileInputStream fis = (FileInputStream)currSource; 144 // FileChannel channel = fis.getChannel(); 145 // double perc = (((double)channel.position()) / ((double)channel.size()) * 100.0); 146 // System.out.format(" " + (int)perc + "%%"); 147 // } 148 // catch(java.lang.ClassCastException cce) { 149 // } 150 // catch(IOException e) { 151 // System.out.format("Error reading file position " + e); 152 // } 153 // } 154 // n++; 155 156 if (qName.equals("osm")) { 157 if (atts == null) 158 throw new SAXException(tr("Unknown version")); 159 String v = atts.getValue("version"); 160 if (v == null) 161 throw new SAXException(tr("Version number missing from OSM data")); 162 if (!(v.equals("0.5") || v.equals("0.6"))) 163 throw new SAXException(tr("Unknown version: {0}", v)); 164 // save generator attribute for later use when creating DataSource objects 165 generator = atts.getValue("generator"); 166 ds.version = v; 167 168 } else if (qName.equals("bounds")) { 169 // new style bounds. 170 String minlon = atts.getValue("minlon"); 171 String minlat = atts.getValue("minlat"); 172 String maxlon = atts.getValue("maxlon"); 173 String maxlat = atts.getValue("maxlat"); 174 String origin = atts.getValue("origin"); 175 if (minlon != null && maxlon != null && minlat != null && maxlat != null) { 176 if (origin == null) origin = generator; 177 Bounds bounds = new Bounds( 178 new LatLon(Double.parseDouble(minlat), Double.parseDouble(minlon)), 179 new LatLon(Double.parseDouble(maxlat), Double.parseDouble(maxlon))); 180 DataSource src = new DataSource(bounds, origin); 181 ds.dataSources.add(src); 182 } 53 /** 54 * This is used as (readonly) source for finding missing references when not transferred in the 55 * file. 56 */ 57 private DataSet references; 58 59 /** 60 * The dataset to add parsed objects to. 61 */ 62 private DataSet ds = new DataSet(); 63 public DataSet getDs() { return ds; } 64 65 /** 66 * Record warnings. If there were any data inconsistencies, append 67 * a newline-terminated string. 68 */ 69 private String parseNotes = new String(); 70 private int parseNotesCount = 0; 71 public String getParseNotes() { 72 return parseNotes; 73 } 74 75 /** the list of ids of skipped {@see Way}s, i.e. ways which referred to nodes 76 * not included in the parsed data 77 */ 78 private Set<Long> skippedWayIds = new HashSet<Long>(); 79 80 /** 81 * The visitor to use to add the data to the set. 82 */ 83 private AddVisitor adder = new AddVisitor(ds); 84 85 /** 86 * All read nodes after phase 1. 87 */ 88 private Map<Long, Node> nodes = new HashMap<Long, Node>(); 89 90 91 private static class OsmPrimitiveData { 92 public long id = 0; 93 public Map<String,String> keys = new HashMap<String, String>(); 94 public boolean modified = false; 95 public boolean selected = false; 96 public boolean deleted = false; 97 public Date timestamp = new Date(); 98 public User user = null; 99 public boolean visible = true; 100 public int version = -1; 101 public LatLon latlon = new LatLon(0,0); 102 103 public void copyTo(OsmPrimitive osm) { 104 osm.id = id; 105 osm.keys = keys; 106 osm.modified = modified; 107 osm.selected = selected; 108 osm.deleted = deleted; 109 osm.setTimestamp(timestamp); 110 osm.user = user; 111 osm.visible = visible; 112 osm.version = version; 113 osm.mappaintStyle = null; 114 } 115 116 public Node createNode() { 117 Node node = new Node(latlon); 118 copyTo(node); 119 return node; 120 } 121 122 public Way createWay() { 123 Way way = new Way(id); 124 copyTo(way); 125 return way; 126 } 127 128 public Relation createRelation() { 129 Relation rel = new Relation(id); 130 copyTo(rel); 131 return rel; 132 } 133 } 134 135 /** 136 * Used as a temporary storage for relation members, before they 137 * are resolved into pointers to real objects. 138 */ 139 private static class RelationMemberData { 140 public String type; 141 public long id; 142 public RelationMember relationMember; 143 } 144 145 /** 146 * Data structure for the remaining way objects 147 */ 148 private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>(); 149 150 /** 151 * Data structure for relation objects 152 */ 153 private Map<OsmPrimitiveData, Collection<RelationMemberData>> relations = new HashMap<OsmPrimitiveData, Collection<RelationMemberData>>(); 154 155 private class Parser extends DefaultHandler { 156 /** 157 * The current osm primitive to be read. 158 */ 159 private OsmPrimitiveData current; 160 private String generator; 161 162 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 163 try { 164 if (qName.equals("osm")) { 165 if (atts == null) 166 throw new SAXException(tr("Unknown version")); 167 String v = atts.getValue("version"); 168 if (v == null) 169 throw new SAXException(tr("Version number missing from OSM data")); 170 if (!(v.equals("0.5") || v.equals("0.6"))) 171 throw new SAXException(tr("Unknown version: {0}", v)); 172 // save generator attribute for later use when creating DataSource objects 173 generator = atts.getValue("generator"); 174 ds.version = v; 175 176 } else if (qName.equals("bounds")) { 177 // new style bounds. 178 String minlon = atts.getValue("minlon"); 179 String minlat = atts.getValue("minlat"); 180 String maxlon = atts.getValue("maxlon"); 181 String maxlat = atts.getValue("maxlat"); 182 String origin = atts.getValue("origin"); 183 if (minlon != null && maxlon != null && minlat != null && maxlat != null) { 184 if (origin == null) { 185 origin = generator; 186 } 187 Bounds bounds = new Bounds( 188 new LatLon(Double.parseDouble(minlat), Double.parseDouble(minlon)), 189 new LatLon(Double.parseDouble(maxlat), Double.parseDouble(maxlon))); 190 DataSource src = new DataSource(bounds, origin); 191 ds.dataSources.add(src); 192 } 183 193 184 194 // ---- PARSING NODES AND WAYS ---- 185 195 186 } else if (qName.equals("node")) { 187 // nodesN++; 188 current = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon"))); 189 readCommon(atts, current); 190 nodes.put(current.id, (Node)current); 191 } else if (qName.equals("way")) { 192 // waysN++; 193 current = new OsmPrimitiveData(); 194 readCommon(atts, current); 195 ways.put((OsmPrimitiveData)current, new ArrayList<Long>()); 196 } else if (qName.equals("nd")) { 197 Collection<Long> list = ways.get(current); 198 if (list == null) 199 throw new SAXException(tr("Found <nd> element in non-way.")); 200 long id = getLong(atts, "ref"); 201 if (id == 0) 202 throw new SAXException(tr("<nd> has zero ref")); 203 list.add(id); 196 } else if (qName.equals("node")) { 197 current = new OsmPrimitiveData(); 198 current.latlon = new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")); 199 readCommon(atts, current); 200 } else if (qName.equals("way")) { 201 current = new OsmPrimitiveData(); 202 readCommon(atts, current); 203 ways.put(current, new ArrayList<Long>()); 204 } else if (qName.equals("nd")) { 205 Collection<Long> list = ways.get(current); 206 if (list == null) 207 throw new SAXException(tr("Found <nd> element in non-way.")); 208 long id = getLong(atts, "ref"); 209 if (id == 0) 210 throw new SAXException(tr("<nd> has zero ref")); 211 list.add(id); 204 212 205 213 // ---- PARSING RELATIONS ---- 206 214 207 } else if (qName.equals("relation")) { 208 current = new OsmPrimitiveData(); 209 readCommon(atts, current); 210 relations.put((OsmPrimitiveData)current, new LinkedList<RelationMemberData>()); 211 } else if (qName.equals("member")) { 212 Collection<RelationMemberData> list = relations.get(current); 213 if (list == null) 214 throw new SAXException(tr("Found <member> element in non-relation.")); 215 RelationMemberData emd = new RelationMemberData(); 216 emd.relationMember = new RelationMember(); 217 String value = atts.getValue("ref"); 218 if (value == null) { 219 throw new SAXException(tr("Missing attribute \"ref\" on member in relation {0}",current.id)); 220 } 221 try { 222 emd.id = Long.parseLong(value); 223 } catch(NumberFormatException e) { 224 throw new SAXException(tr("Illegal value for attribute \"ref\" on member in relation {0}, got {1}", Long.toString(current.id),value)); 225 } 226 value = atts.getValue("type"); 227 if (value == null) { 228 throw new SAXException(tr("Missing attribute \"type\" on member {0} in relation {1}", Long.toString(emd.id), Long.toString(current.id))); 229 } 230 if (! (value.equals("way") || value.equals("node") || value.equals("relation"))) { 231 throw new SAXException(tr("Unexpected \"type\" on member {0} in relation {1}, got {2}.", Long.toString(emd.id), Long.toString(current.id), value)); 232 } 233 emd.type= value; 234 value = atts.getValue("role"); 235 emd.relationMember.role = value; 236 237 if (emd.id == 0) 238 throw new SAXException(tr("Incomplete <member> specification with ref=0")); 239 240 list.add(emd); 215 } else if (qName.equals("relation")) { 216 current = new OsmPrimitiveData(); 217 readCommon(atts, current); 218 relations.put(current, new LinkedList<RelationMemberData>()); 219 } else if (qName.equals("member")) { 220 Collection<RelationMemberData> list = relations.get(current); 221 if (list == null) 222 throw new SAXException(tr("Found <member> element in non-relation.")); 223 RelationMemberData emd = new RelationMemberData(); 224 emd.relationMember = new RelationMember(); 225 String value = atts.getValue("ref"); 226 if (value == null) 227 throw new SAXException(tr("Missing attribute \"ref\" on member in relation {0}",current.id)); 228 try { 229 emd.id = Long.parseLong(value); 230 } catch(NumberFormatException e) { 231 throw new SAXException(tr("Illegal value for attribute \"ref\" on member in relation {0}, got {1}", Long.toString(current.id),value)); 232 } 233 value = atts.getValue("type"); 234 if (value == null) 235 throw new SAXException(tr("Missing attribute \"type\" on member {0} in relation {1}", Long.toString(emd.id), Long.toString(current.id))); 236 if (! (value.equals("way") || value.equals("node") || value.equals("relation"))) 237 throw new SAXException(tr("Unexpected \"type\" on member {0} in relation {1}, got {2}.", Long.toString(emd.id), Long.toString(current.id), value)); 238 emd.type= value; 239 value = atts.getValue("role"); 240 emd.relationMember.role = value; 241 242 if (emd.id == 0) 243 throw new SAXException(tr("Incomplete <member> specification with ref=0")); 244 245 list.add(emd); 241 246 242 247 // ---- PARSING TAGS (applicable to all objects) ---- 243 248 244 } else if (qName.equals("tag")) { 245 // tagsN++; 246 String key = atts.getValue("k"); 247 String internedKey = keys.get(key); 248 if (internedKey == null) { 249 internedKey = key; 250 keys.put(key, key); 251 } 252 current.put(internedKey, atts.getValue("v")); 253 } 254 } catch (NumberFormatException x) { 255 x.printStackTrace(); // SAXException does not chain correctly 256 throw new SAXException(x.getMessage(), x); 257 } catch (NullPointerException x) { 258 x.printStackTrace(); // SAXException does not chain correctly 259 throw new SAXException(tr("NullPointerException, possibly some missing tags."), x); 260 } 261 } 262 263 private double getDouble(Attributes atts, String value) { 264 return Double.parseDouble(atts.getValue(value)); 265 } 266 } 267 268 /** 269 * Read out the common attributes from atts and put them into this.current. 270 */ 271 void readCommon(Attributes atts, OsmPrimitive current) throws SAXException { 272 current.id = getLong(atts, "id"); 273 if (current.id == 0) 274 throw new SAXException(tr("Illegal object with id=0")); 275 276 String time = atts.getValue("timestamp"); 277 if (time != null && time.length() != 0) { 278 current.setTimestamp(DateUtils.fromString(time)); 279 } 280 281 // user attribute added in 0.4 API 282 String user = atts.getValue("user"); 283 if (user != null) { 284 // do not store literally; get object reference for string 285 current.user = User.get(user); 286 } 287 288 // uid attribute added in 0.6 API 289 String uid = atts.getValue("uid"); 290 if (uid != null) { 291 if (current.user != null) { 292 current.user.uid = uid; 293 } 294 } 295 296 // visible attribute added in 0.4 API 297 String visible = atts.getValue("visible"); 298 if (visible != null) { 299 current.visible = Boolean.parseBoolean(visible); 300 } 301 302 String version = atts.getValue("version"); 303 current.version = 0; 304 if (version != null) { 305 try { 306 current.version = Integer.parseInt(version); 307 } catch(NumberFormatException e) { 308 throw new SAXException(tr("Illegal value for attribute \"version\" on OSM primitive with id {0}, got {1}", Long.toString(current.id), version)); 309 } 310 } else { 311 // version expected for OSM primitives with an id assigned by the server (id > 0), since API 0.6 312 // 313 if (current.id > 0 && ds.version != null && ds.version.equals("0.6")) { 314 throw new SAXException(tr("Missing attribute \"version\" on OSM primitive with id {0}", Long.toString(current.id))); 315 } 316 } 317 318 String action = atts.getValue("action"); 319 if (action == null) 320 return; 321 if (action.equals("delete")) 322 current.delete(true); 323 else if (action.startsWith("modify")) 324 current.modified = true; 325 } 326 private long getLong(Attributes atts, String value) throws SAXException { 327 String s = atts.getValue(value); 328 if (s == null) 329 throw new SAXException(tr("Missing required attribute \"{0}\".",value)); 330 return Long.parseLong(s); 331 } 332 333 private Node findNode(long id) { 334 Node n = nodes.get(id); 335 if (n != null) 336 return n; 337 for (Node node : references.nodes) 338 if (node.id == id) 339 return node; 340 // TODO: This has to be changed to support multiple layers. 341 for (Node node : Main.ds.nodes) 342 if (node.id == id) 343 return new Node(node); 344 return null; 345 } 346 347 private void createWays() { 348 for (Entry<OsmPrimitiveData, Collection<Long>> e : ways.entrySet()) { 349 Way w = new Way(); 350 boolean failed = false; 351 for (long id : e.getValue()) { 352 Node n = findNode(id); 353 if (n == null) { 354 /* don't report ALL of them, just a few */ 355 if (parseNotesCount++ < 6) { 356 parseNotes += tr("Skipping a way because it includes a node that doesn''t exist: {0}\n", id); 357 } else if (parseNotesCount == 6) { 358 parseNotes += "...\n"; 359 } 360 failed = true; 361 break; 362 } 363 w.nodes.add(n); 364 } 365 if (failed) continue; 366 e.getKey().copyTo(w); 367 adder.visit(w); 368 } 369 370 } 371 372 /** 373 * Return the Way object with the given id, or null if it doesn't 374 * exist yet. This method only looks at ways stored in the data set. 375 * 376 * @param id 377 * @return way object or null 378 */ 379 private Way findWay(long id) { 380 for (Way wy : Main.ds.ways) 381 if (wy.id == id) 382 return wy; 383 return null; 384 } 385 386 /** 387 * Return the Relation object with the given id, or null if it doesn't 388 * exist yet. This method only looks at relations stored in the data set. 389 * 390 * @param id 391 * @return relation object or null 392 */ 393 private Relation findRelation(long id) { 394 for (Relation e : ds.relations) 395 if (e.id == id) 396 return e; 397 for (Relation e : Main.ds.relations) 398 if (e.id == id) 399 return e; 400 return null; 401 } 402 403 /** 404 * Create relations. This is slightly different than n/s/w because 405 * unlike other objects, relations may reference other relations; it 406 * is not guaranteed that a referenced relation will have been created 407 * before it is referenced. So we have to create all relations first, 408 * and populate them later. 409 */ 410 private void createRelations() { 411 412 // pass 1 - create all relations 413 for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) { 414 Relation en = new Relation(); 415 e.getKey().copyTo(en); 416 adder.visit(en); 417 } 418 419 // Cache the ways here for much better search performance 420 HashMap<Long, Way> hm = new HashMap<Long, Way>(10000); 421 for (Way wy : ds.ways) 249 } else if (qName.equals("tag")) { 250 String key = atts.getValue("k"); 251 String value = atts.getValue("v"); 252 current.keys.put(key,value); 253 } 254 } catch (NumberFormatException x) { 255 x.printStackTrace(); // SAXException does not chain correctly 256 throw new SAXException(x.getMessage(), x); 257 } catch (NullPointerException x) { 258 x.printStackTrace(); // SAXException does not chain correctly 259 throw new SAXException(tr("NullPointerException, possibly some missing tags."), x); 260 } 261 } 262 263 @Override 264 public void endElement(String uri, String localName, String qName) throws SAXException { 265 if (qName.equals("node")) { 266 nodes.put(current.id, current.createNode()); 267 } 268 } 269 270 private double getDouble(Attributes atts, String value) { 271 return Double.parseDouble(atts.getValue(value)); 272 } 273 } 274 275 /** 276 * Read out the common attributes from atts and put them into this.current. 277 */ 278 void readCommon(Attributes atts, OsmPrimitiveData current) throws SAXException { 279 current.id = getLong(atts, "id"); 280 if (current.id == 0) 281 throw new SAXException(tr("Illegal object with id=0")); 282 283 String time = atts.getValue("timestamp"); 284 if (time != null && time.length() != 0) { 285 current.timestamp = DateUtils.fromString(time); 286 } 287 288 // user attribute added in 0.4 API 289 String user = atts.getValue("user"); 290 if (user != null) { 291 // do not store literally; get object reference for string 292 current.user = User.get(user); 293 } 294 295 // uid attribute added in 0.6 API 296 String uid = atts.getValue("uid"); 297 if (uid != null) { 298 if (current.user != null) { 299 current.user.uid = uid; 300 } 301 } 302 303 // visible attribute added in 0.4 API 304 String visible = atts.getValue("visible"); 305 if (visible != null) { 306 current.visible = Boolean.parseBoolean(visible); 307 } 308 309 String version = atts.getValue("version"); 310 current.version = 0; 311 if (version != null) { 312 try { 313 current.version = Integer.parseInt(version); 314 } catch(NumberFormatException e) { 315 throw new SAXException(tr("Illegal value for attribute \"version\" on OSM primitive with id {0}, got {1}", Long.toString(current.id), version)); 316 } 317 } else { 318 // version expected for OSM primitives with an id assigned by the server (id > 0), since API 0.6 319 // 320 if (current.id > 0 && ds.version != null && ds.version.equals("0.6")) 321 throw new SAXException(tr("Missing attribute \"version\" on OSM primitive with id {0}", Long.toString(current.id))); 322 } 323 324 String action = atts.getValue("action"); 325 if (action == null) 326 return; 327 if (action.equals("delete")) { 328 current.deleted = true; 329 } else if (action.startsWith("modify")) { 330 current.modified = true; 331 } 332 } 333 private long getLong(Attributes atts, String value) throws SAXException { 334 String s = atts.getValue(value); 335 if (s == null) 336 throw new SAXException(tr("Missing required attribute \"{0}\".",value)); 337 return Long.parseLong(s); 338 } 339 340 private Node findNode(long id) { 341 Node n = nodes.get(id); 342 if (n != null) 343 return n; 344 for (Node node : references.nodes) 345 if (node.id == id) 346 return node; 347 // TODO: This has to be changed to support multiple layers. 348 for (Node node : Main.ds.nodes) 349 if (node.id == id) 350 return new Node(node); 351 return null; 352 } 353 354 protected void createWays() { 355 for (Entry<OsmPrimitiveData, Collection<Long>> e : ways.entrySet()) { 356 Way w = new Way(); 357 boolean failed = false; 358 for (long id : e.getValue()) { 359 Node n = findNode(id); 360 if (n == null) { 361 /* don't report ALL of them, just a few */ 362 if (parseNotesCount++ < 6) { 363 parseNotes += tr("Skipping a way because it includes a node that doesn''t exist: {0}\n", id); 364 } else if (parseNotesCount == 6) { 365 parseNotes += "...\n"; 366 } 367 failed = true; 368 break; 369 } 370 w.nodes.add(n); 371 } 372 if (failed) { 373 skippedWayIds.add(e.getKey().id); 374 continue; 375 } 376 e.getKey().copyTo(w); 377 adder.visit(w); 378 } 379 380 } 381 382 /** 383 * Return the Way object with the given id, or null if it doesn't 384 * exist yet. This method only looks at ways stored in the data set. 385 * 386 * @param id 387 * @return way object or null 388 */ 389 private Way findWay(long id) { 390 for (Way wy : Main.ds.ways) 391 if (wy.id == id) 392 return wy; 393 return null; 394 } 395 396 /** 397 * Return the Relation object with the given id, or null if it doesn't 398 * exist yet. This method only looks at relations stored in the data set. 399 * 400 * @param id 401 * @return relation object or null 402 */ 403 private Relation findRelation(long id) { 404 for (Relation e : ds.relations) 405 if (e.id == id) 406 return e; 407 for (Relation e : Main.ds.relations) 408 if (e.id == id) 409 return e; 410 return null; 411 } 412 413 /** 414 * Create relations. This is slightly different than n/s/w because 415 * unlike other objects, relations may reference other relations; it 416 * is not guaranteed that a referenced relation will have been created 417 * before it is referenced. So we have to create all relations first, 418 * and populate them later. 419 */ 420 private void createRelations() { 421 422 // pass 1 - create all relations 423 for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) { 424 Relation en = new Relation(); 425 e.getKey().copyTo(en); 426 adder.visit(en); 427 } 428 429 // Cache the ways here for much better search performance 430 HashMap<Long, Way> hm = new HashMap<Long, Way>(10000); 431 for (Way wy : ds.ways) { 422 432 hm.put(wy.id, wy); 423 424 // pass 2 - sort out members 425 for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) { 426 Relation en = findRelation(e.getKey().id); 427 if (en == null) throw new Error("Failed to create relation " + e.getKey().id); 428 429 for (RelationMemberData emd : e.getValue()) { 430 RelationMember em = emd.relationMember; 431 if (emd.type.equals("node")) { 432 em.member = findNode(emd.id); 433 if (em.member == null) { 434 em.member = new Node(emd.id); 435 adder.visit((Node)em.member); 436 } 437 } else if (emd.type.equals("way")) { 438 em.member = hm.get(emd.id); 439 if (em.member == null) 440 em.member = findWay(emd.id); 441 if (em.member == null) { 442 em.member = new Way(emd.id); 443 adder.visit((Way)em.member); 444 } 445 } else if (emd.type.equals("relation")) { 446 em.member = findRelation(emd.id); 447 if (em.member == null) { 448 em.member = new Relation(emd.id); 449 adder.visit((Relation)em.member); 450 } 451 } else { 452 // this is an error. 453 } 454 en.members.add(em); 455 } 456 } 457 hm = null; 458 } 459 460 /** 461 * Parse the given input source and return the dataset. 462 * @param ref The dataset that is search in for references first. If 463 * the Reference is not found here, Main.ds is searched and a copy of the 464 * element found there is returned. 465 */ 466 public static DataSet parseDataSet(InputStream source, DataSet ref, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException { 467 return parseDataSetOsm(source, ref, pleaseWaitDlg).ds; 468 } 469 470 public static OsmReader parseDataSetOsm(InputStream source, DataSet ref, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException { 471 OsmReader osm = new OsmReader(); 472 osm.references = ref == null ? new DataSet() : ref; 473 474 currSource = source; 475 476 // phase 1: Parse nodes and read in raw ways 477 InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8")); 478 try { 479 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, osm.new Parser()); 480 } catch (ParserConfigurationException e1) { 481 e1.printStackTrace(); // broken SAXException chaining 482 throw new SAXException(e1); 483 } 484 485 Main.pleaseWaitDlg.currentAction.setText(tr("Prepare OSM data...")); 486 Main.pleaseWaitDlg.setIndeterminate(true); 487 488 // System.out.println("Parser finished: Tags " + tagsN + " Nodes " + nodesN + " Ways " + waysN + 489 // " Relations " + relationsN + " Members " + membersN); 490 491 for (Node n : osm.nodes.values()) 492 osm.adder.visit(n); 493 494 try { 495 osm.createWays(); 496 osm.createRelations(); 497 } catch (NumberFormatException e) { 498 e.printStackTrace(); 499 throw new SAXException(tr("Ill-formed node id")); 500 } 501 502 // clear all negative ids (new to this file) 503 for (OsmPrimitive o : osm.ds.allPrimitives()) 504 if (o.id < 0) 505 o.id = 0; 506 507 // System.out.println("Data loaded!"); 508 Main.pleaseWaitDlg.setIndeterminate(false); 509 Main.pleaseWaitDlg.progress.setValue(0); 510 511 return osm; 512 } 433 } 434 435 // pass 2 - sort out members 436 for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) { 437 Relation en = findRelation(e.getKey().id); 438 if (en == null) throw new Error("Failed to create relation " + e.getKey().id); 439 440 for (RelationMemberData emd : e.getValue()) { 441 RelationMember em = emd.relationMember; 442 if (emd.type.equals("node")) { 443 em.member = findNode(emd.id); 444 if (em.member == null) { 445 em.member = new Node(emd.id); 446 adder.visit((Node)em.member); 447 } 448 } else if (emd.type.equals("way")) { 449 em.member = hm.get(emd.id); 450 if (em.member == null) { 451 em.member = findWay(emd.id); 452 } 453 if (em.member == null) { 454 em.member = new Way(emd.id); 455 adder.visit((Way)em.member); 456 } 457 } else if (emd.type.equals("relation")) { 458 em.member = findRelation(emd.id); 459 if (em.member == null) { 460 em.member = new Relation(emd.id); 461 adder.visit((Relation)em.member); 462 } 463 } else { 464 // this is an error. 465 } 466 en.members.add(em); 467 } 468 } 469 hm = null; 470 } 471 472 /** 473 * Parse the given input source and return the dataset. 474 * @param ref The dataset that is search in for references first. If 475 * the Reference is not found here, Main.ds is searched and a copy of the 476 * element found there is returned. 477 */ 478 public static DataSet parseDataSet(InputStream source, DataSet ref, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException { 479 return parseDataSetOsm(source, ref, pleaseWaitDlg).ds; 480 } 481 482 public static OsmReader parseDataSetOsm(InputStream source, DataSet ref, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException { 483 OsmReader osm = new OsmReader(); 484 osm.references = ref == null ? new DataSet() : ref; 485 486 // phase 1: Parse nodes and read in raw ways 487 InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8")); 488 try { 489 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, osm.new Parser()); 490 } catch (ParserConfigurationException e1) { 491 e1.printStackTrace(); // broken SAXException chaining 492 throw new SAXException(e1); 493 } 494 495 Main.pleaseWaitDlg.currentAction.setText(tr("Prepare OSM data...")); 496 Main.pleaseWaitDlg.setIndeterminate(true); 497 498 for (Node n : osm.nodes.values()) { 499 osm.adder.visit(n); 500 } 501 502 try { 503 osm.createWays(); 504 osm.createRelations(); 505 } catch (NumberFormatException e) { 506 e.printStackTrace(); 507 throw new SAXException(tr("Ill-formed node id")); 508 } 509 510 // clear all negative ids (new to this file) 511 for (OsmPrimitive o : osm.ds.allPrimitives()) 512 if (o.id < 0) { 513 o.id = 0; 514 } 515 516 Main.pleaseWaitDlg.setIndeterminate(false); 517 Main.pleaseWaitDlg.progress.setValue(0); 518 519 return osm; 520 } 521 522 /** 523 * replies a set of ids of skipped {@see Way}s, i.e. ways which were included in the downloaded 524 * data but which referred to nodes <strong>not</strong> available in the downloaded data 525 * 526 * @return the set of ids 527 */ 528 public Set<Long> getSkippedWayIds() { 529 return skippedWayIds; 530 } 513 531 }
Note:
See TracChangeset
for help on using the changeset viewer.
