Ticket #6886: patchV2.diff
| File patchV2.diff, 37.6 KB (added by , 15 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
40 40 String[] importerNames = { 41 41 "org.openstreetmap.josm.io.OsmImporter", 42 42 "org.openstreetmap.josm.io.OsmGzipImporter", 43 "org.openstreetmap.josm.io.PbfImporter", 43 44 "org.openstreetmap.josm.io.GpxImporter", 44 45 "org.openstreetmap.josm.io.NMEAImporter", 45 46 "org.openstreetmap.josm.io.OsmBzip2Importer", -
src/org/openstreetmap/josm/data/coor/LatLon.java
63 63 public static boolean isValidLon(double lon) { 64 64 return lon >= -180d && lon <= 180d; 65 65 } 66 67 /** 68 * Replies true if lat is in the range [-90,90] and lon is in the range [-180,180] 69 * 70 * @return true if lat is in the range [-90,90] and lon is in the range [-180,180] 71 */ 72 public boolean isValid() { 73 return isValidLat(lat()) && isValidLon(lon()); 74 } 66 75 67 76 /** 68 77 * Replies the coordinate in degrees/minutes/seconds format -
src/org/openstreetmap/josm/io/AbstractReader.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.io; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.util.ArrayList; 7 import java.util.Collection; 8 import java.util.HashMap; 9 import java.util.List; 10 import java.util.Map; 11 12 import org.openstreetmap.josm.data.osm.Changeset; 13 import org.openstreetmap.josm.data.osm.DataSet; 14 import org.openstreetmap.josm.data.osm.Node; 15 import org.openstreetmap.josm.data.osm.OsmPrimitive; 16 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 17 import org.openstreetmap.josm.data.osm.PrimitiveId; 18 import org.openstreetmap.josm.data.osm.Relation; 19 import org.openstreetmap.josm.data.osm.RelationMember; 20 import org.openstreetmap.josm.data.osm.SimplePrimitiveId; 21 import org.openstreetmap.josm.data.osm.Way; 22 23 /** 24 * Base class for OsmReader (XML file format) and PbfReader (Protobuf file format) 25 * @author Vincent 26 * 27 */ 28 public abstract class AbstractReader { 29 30 /** 31 * Used as a temporary storage for relation members, before they 32 * are resolved into pointers to real objects. 33 */ 34 protected static class RelationMemberData { 35 public OsmPrimitiveType type; 36 public long id; 37 public String role; 38 } 39 40 /** 41 * The dataset to add parsed objects to. 42 */ 43 protected final DataSet ds = new DataSet(); 44 45 protected Changeset uploadChangeset; 46 47 /** the map from external ids to read OsmPrimitives. External ids are 48 * longs too, but in contrast to internal ids negative values are used 49 * to identify primitives unknown to the OSM server 50 */ 51 protected Map<PrimitiveId, OsmPrimitive> externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>(); 52 53 /** 54 * Data structure for the remaining way objects 55 */ 56 protected Map<Long, Collection<Long>> ways = new HashMap<Long, Collection<Long>>(); 57 58 /** 59 * Data structure for relation objects 60 */ 61 protected Map<Long, Collection<RelationMemberData>> relations = new HashMap<Long, Collection<RelationMemberData>>(); 62 63 /** 64 * Replies the parsed data set 65 * 66 * @return the parsed data set 67 */ 68 public DataSet getDataSet() { 69 return ds; 70 } 71 72 /** 73 * Processes the parsed nodes after parsing. Just adds them to 74 * the dataset 75 * 76 */ 77 private void processNodesAfterParsing() { 78 for (OsmPrimitive primitive: externalIdMap.values()) { 79 if (primitive instanceof Node) { 80 this.ds.addPrimitive(primitive); 81 } 82 } 83 } 84 85 /** 86 * Processes the ways after parsing. Rebuilds the list of nodes of each way and 87 * adds the way to the dataset 88 * 89 * @throws IllegalDataException thrown if a data integrity problem is detected 90 */ 91 private void processWaysAfterParsing() throws IllegalDataException{ 92 for (Long externalWayId: ways.keySet()) { 93 Way w = (Way)externalIdMap.get(new SimplePrimitiveId(externalWayId, OsmPrimitiveType.WAY)); 94 List<Node> wayNodes = new ArrayList<Node>(); 95 for (long id : ways.get(externalWayId)) { 96 Node n = (Node)externalIdMap.get(new SimplePrimitiveId(id, OsmPrimitiveType.NODE)); 97 if (n == null) { 98 if (id <= 0) 99 throw new IllegalDataException ( 100 tr("Way with external ID ''{0}'' includes missing node with external ID ''{1}''.", 101 externalWayId, 102 id)); 103 // create an incomplete node if necessary 104 // 105 n = (Node)ds.getPrimitiveById(id,OsmPrimitiveType.NODE); 106 if (n == null) { 107 n = new Node(id); 108 ds.addPrimitive(n); 109 } 110 } 111 if (n.isDeleted()) { 112 System.out.println(tr("Deleted node {0} is part of way {1}", id, w.getId())); 113 } else { 114 wayNodes.add(n); 115 } 116 } 117 w.setNodes(wayNodes); 118 if (w.hasIncompleteNodes()) { 119 System.out.println(tr("Way {0} with {1} nodes has incomplete nodes because at least one node was missing in the loaded data.", 120 externalWayId, w.getNodesCount())); 121 } 122 ds.addPrimitive(w); 123 } 124 } 125 126 /** 127 * Completes the parsed relations with its members. 128 * 129 * @throws IllegalDataException thrown if a data integrity problem is detected, i.e. if a 130 * relation member refers to a local primitive which wasn't available in the data 131 * 132 */ 133 private void processRelationsAfterParsing() throws IllegalDataException { 134 135 // First add all relations to make sure that when relation reference other relation, the referenced will be already in dataset 136 for (Long externalRelationId : relations.keySet()) { 137 Relation relation = (Relation) externalIdMap.get( 138 new SimplePrimitiveId(externalRelationId, OsmPrimitiveType.RELATION) 139 ); 140 ds.addPrimitive(relation); 141 } 142 143 for (Long externalRelationId : relations.keySet()) { 144 Relation relation = (Relation) externalIdMap.get( 145 new SimplePrimitiveId(externalRelationId, OsmPrimitiveType.RELATION) 146 ); 147 List<RelationMember> relationMembers = new ArrayList<RelationMember>(); 148 for (RelationMemberData rm : relations.get(externalRelationId)) { 149 OsmPrimitive primitive = null; 150 151 // lookup the member from the map of already created primitives 152 primitive = externalIdMap.get(new SimplePrimitiveId(rm.id, rm.type)); 153 154 if (primitive == null) { 155 if (rm.id <= 0) 156 // relation member refers to a primitive with a negative id which was not 157 // found in the data. This is always a data integrity problem and we abort 158 // with an exception 159 // 160 throw new IllegalDataException( 161 tr("Relation with external id ''{0}'' refers to a missing primitive with external id ''{1}''.", 162 externalRelationId, 163 rm.id)); 164 165 // member refers to OSM primitive which was not present in the parsed data 166 // -> create a new incomplete primitive and add it to the dataset 167 // 168 primitive = ds.getPrimitiveById(rm.id, rm.type); 169 if (primitive == null) { 170 switch (rm.type) { 171 case NODE: 172 primitive = new Node(rm.id); break; 173 case WAY: 174 primitive = new Way(rm.id); break; 175 case RELATION: 176 primitive = new Relation(rm.id); break; 177 default: throw new AssertionError(); // can't happen 178 } 179 180 ds.addPrimitive(primitive); 181 externalIdMap.put(new SimplePrimitiveId(rm.id, rm.type), primitive); 182 } 183 } 184 if (primitive.isDeleted()) { 185 System.out.println(tr("Deleted member {0} is used by relation {1}", primitive.getId(), relation.getId())); 186 } else { 187 relationMembers.add(new RelationMember(rm.role, primitive)); 188 } 189 } 190 relation.setMembers(relationMembers); 191 } 192 } 193 194 private void processChangesetAfterParsing() { 195 if (uploadChangeset != null) { 196 for (Map.Entry<String, String> e : uploadChangeset.getKeys().entrySet()) { 197 ds.addChangeSetTag(e.getKey(), e.getValue()); 198 } 199 } 200 } 201 202 protected final void prepareDataSet() throws IllegalDataException { 203 try { 204 ds.beginUpdate(); 205 processNodesAfterParsing(); 206 processWaysAfterParsing(); 207 processRelationsAfterParsing(); 208 processChangesetAfterParsing(); 209 } finally { 210 ds.endUpdate(); 211 } 212 } 213 } -
src/org/openstreetmap/josm/io/AllFormatsImporter.java
12 12 */ 13 13 public class AllFormatsImporter extends FileImporter { 14 14 public AllFormatsImporter() { 15 super(new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz, gpx,gpx.gz,nmea,nme,nma,log,txt,wms,jpg", "", tr("All Formats")15 super(new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,osm.pbf,gpx,gpx.gz,nmea,nme,nma,log,txt,wms,jpg", "", tr("All Formats") 16 16 + " (*.gpx *.osm *.nmea *.jpg ...)")); 17 17 } 18 18 @Override public boolean acceptFile(File pathname) { -
src/org/openstreetmap/josm/io/OsmImporter.java
42 42 protected void importData(InputStream in, final File associatedFile) throws IllegalDataException { 43 43 final DataSet dataSet = OsmReader.parseDataSet(in, NullProgressMonitor.INSTANCE); 44 44 final OsmDataLayer layer = new OsmDataLayer(dataSet, associatedFile.getName(), associatedFile); 45 addDataLayer(dataSet, layer, associatedFile.getPath()); 46 } 47 48 protected void addDataLayer(final DataSet dataSet, final OsmDataLayer layer, final String filePath) { 45 49 // FIXME: remove UI stuff from IO subsystem 46 50 // 47 51 Runnable uiStuff = new Runnable() { … … 50 54 if (dataSet.allPrimitives().isEmpty()) { 51 55 JOptionPane.showMessageDialog( 52 56 Main.parent, 53 tr("No data found in file {0}.", associatedFile.getPath()),57 tr("No data found in file {0}.", filePath), 54 58 tr("Open OSM file"), 55 59 JOptionPane.INFORMATION_MESSAGE); 56 60 } -
src/org/openstreetmap/josm/io/OsmReader.java
8 8 import java.text.MessageFormat; 9 9 import java.util.ArrayList; 10 10 import java.util.Collection; 11 import java.util.HashMap;12 import java.util.LinkedList;13 import java.util.List;14 import java.util.Map;15 11 import java.util.regex.Matcher; 16 12 import java.util.regex.Pattern; 17 13 14 import javax.xml.stream.Location; 18 15 import javax.xml.stream.XMLInputFactory; 19 import javax.xml.stream.XMLStreamReader;20 16 import javax.xml.stream.XMLStreamConstants; 21 17 import javax.xml.stream.XMLStreamException; 22 import javax.xml.stream. Location;18 import javax.xml.stream.XMLStreamReader; 23 19 24 20 import org.openstreetmap.josm.data.Bounds; 25 21 import org.openstreetmap.josm.data.coor.LatLon; … … 28 24 import org.openstreetmap.josm.data.osm.DataSource; 29 25 import org.openstreetmap.josm.data.osm.Node; 30 26 import org.openstreetmap.josm.data.osm.NodeData; 31 import org.openstreetmap.josm.data.osm.OsmPrimitive;32 27 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 33 28 import org.openstreetmap.josm.data.osm.PrimitiveData; 34 import org.openstreetmap.josm.data.osm.PrimitiveId;35 29 import org.openstreetmap.josm.data.osm.Relation; 36 30 import org.openstreetmap.josm.data.osm.RelationData; 37 import org.openstreetmap.josm.data.osm.RelationMember;38 import org.openstreetmap.josm.data.osm.SimplePrimitiveId;39 31 import org.openstreetmap.josm.data.osm.Tagged; 40 32 import org.openstreetmap.josm.data.osm.User; 41 33 import org.openstreetmap.josm.data.osm.Way; … … 52 44 * The XMLStreamReader cursor points to the start of the element, when the method is 53 45 * entered, and it must point to the end of the same element, when it is exited. 54 46 */ 55 public class OsmReader { 56 57 /** 58 * Used as a temporary storage for relation members, before they 59 * are resolved into pointers to real objects. 60 */ 61 private static class RelationMemberData { 62 public OsmPrimitiveType type; 63 public long id; 64 public String role; 65 } 66 67 /** 68 * The dataset to add parsed objects to. 69 */ 70 private DataSet ds = new DataSet(); 47 public class OsmReader extends AbstractReader { 71 48 72 49 private XMLStreamReader parser; 73 50 74 /** the map from external ids to read OsmPrimitives. External ids are75 * longs too, but in contrast to internal ids negative values are used76 * to identify primitives unknown to the OSM server77 */78 private Map<PrimitiveId, OsmPrimitive> externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>();79 80 /**81 * Data structure for the remaining way objects82 */83 private Map<Long, Collection<Long>> ways = new HashMap<Long, Collection<Long>>();84 85 /**86 * Data structure for relation objects87 */88 private Map<Long, Collection<RelationMemberData>> relations = new HashMap<Long, Collection<RelationMemberData>>();89 90 private Changeset uploadChangeset;91 92 /**93 * constructor (for private use only)94 *95 * @see #parseDataSet(InputStream, DataSet, ProgressMonitor)96 */97 private OsmReader() {98 externalIdMap = new HashMap<PrimitiveId, OsmPrimitive>();99 }100 101 51 public void setParser(XMLStreamReader parser) { 102 52 this.parser = parser; 103 53 } 104 54 105 /**106 * Replies the parsed data set107 *108 * @return the parsed data set109 */110 public DataSet getDataSet() {111 return ds;112 }113 114 55 protected void throwException(String msg) throws XMLStreamException { 115 56 throw new OsmParsingException(msg, parser.getLocation()); 116 57 } … … 136 77 parser.close(); 137 78 } 138 79 80 @SuppressWarnings("null") 139 81 private void parseOsm() throws XMLStreamException { 140 82 String v = parser.getAttributeValue(null, "version"); 141 83 if (v == null) { … … 351 293 } 352 294 } 353 295 296 @SuppressWarnings("null") 354 297 private void parseTag(Tagged t) throws XMLStreamException { 355 298 String key = parser.getAttributeValue(null, "k"); 356 299 String value = parser.getAttributeValue(null, "v"); … … 579 522 } 580 523 581 524 /** 582 * Processes the parsed nodes after parsing. Just adds them to583 * the dataset584 *585 */586 protected void processNodesAfterParsing() {587 for (OsmPrimitive primitive: externalIdMap.values()) {588 if (primitive instanceof Node) {589 this.ds.addPrimitive(primitive);590 }591 }592 }593 594 /**595 * Processes the ways after parsing. Rebuilds the list of nodes of each way and596 * adds the way to the dataset597 *598 * @throws IllegalDataException thrown if a data integrity problem is detected599 */600 protected void processWaysAfterParsing() throws IllegalDataException{601 for (Long externalWayId: ways.keySet()) {602 Way w = (Way)externalIdMap.get(new SimplePrimitiveId(externalWayId, OsmPrimitiveType.WAY));603 List<Node> wayNodes = new ArrayList<Node>();604 for (long id : ways.get(externalWayId)) {605 Node n = (Node)externalIdMap.get(new SimplePrimitiveId(id, OsmPrimitiveType.NODE));606 if (n == null) {607 if (id <= 0)608 throw new IllegalDataException (609 tr("Way with external ID ''{0}'' includes missing node with external ID ''{1}''.",610 externalWayId,611 id));612 // create an incomplete node if necessary613 //614 n = (Node)ds.getPrimitiveById(id,OsmPrimitiveType.NODE);615 if (n == null) {616 n = new Node(id);617 ds.addPrimitive(n);618 }619 }620 if (n.isDeleted()) {621 System.out.println(tr("Deleted node {0} is part of way {1}", id, w.getId()));622 } else {623 wayNodes.add(n);624 }625 }626 w.setNodes(wayNodes);627 if (w.hasIncompleteNodes()) {628 System.out.println(tr("Way {0} with {1} nodes has incomplete nodes because at least one node was missing in the loaded data.",629 externalWayId, w.getNodesCount()));630 }631 ds.addPrimitive(w);632 }633 }634 635 /**636 * Completes the parsed relations with its members.637 *638 * @throws IllegalDataException thrown if a data integrity problem is detected, i.e. if a639 * relation member refers to a local primitive which wasn't available in the data640 *641 */642 private void processRelationsAfterParsing() throws IllegalDataException {643 644 // First add all relations to make sure that when relation reference other relation, the referenced will be already in dataset645 for (Long externalRelationId : relations.keySet()) {646 Relation relation = (Relation) externalIdMap.get(647 new SimplePrimitiveId(externalRelationId, OsmPrimitiveType.RELATION)648 );649 ds.addPrimitive(relation);650 }651 652 for (Long externalRelationId : relations.keySet()) {653 Relation relation = (Relation) externalIdMap.get(654 new SimplePrimitiveId(externalRelationId, OsmPrimitiveType.RELATION)655 );656 List<RelationMember> relationMembers = new ArrayList<RelationMember>();657 for (RelationMemberData rm : relations.get(externalRelationId)) {658 OsmPrimitive primitive = null;659 660 // lookup the member from the map of already created primitives661 primitive = externalIdMap.get(new SimplePrimitiveId(rm.id, rm.type));662 663 if (primitive == null) {664 if (rm.id <= 0)665 // relation member refers to a primitive with a negative id which was not666 // found in the data. This is always a data integrity problem and we abort667 // with an exception668 //669 throw new IllegalDataException(670 tr("Relation with external id ''{0}'' refers to a missing primitive with external id ''{1}''.",671 externalRelationId,672 rm.id));673 674 // member refers to OSM primitive which was not present in the parsed data675 // -> create a new incomplete primitive and add it to the dataset676 //677 primitive = ds.getPrimitiveById(rm.id, rm.type);678 if (primitive == null) {679 switch (rm.type) {680 case NODE:681 primitive = new Node(rm.id); break;682 case WAY:683 primitive = new Way(rm.id); break;684 case RELATION:685 primitive = new Relation(rm.id); break;686 default: throw new AssertionError(); // can't happen687 }688 689 ds.addPrimitive(primitive);690 externalIdMap.put(new SimplePrimitiveId(rm.id, rm.type), primitive);691 }692 }693 if (primitive.isDeleted()) {694 System.out.println(tr("Deleted member {0} is used by relation {1}", primitive.getId(), relation.getId()));695 } else {696 relationMembers.add(new RelationMember(rm.role, primitive));697 }698 }699 relation.setMembers(relationMembers);700 }701 }702 703 private void processChangesetAfterParsing() {704 if (uploadChangeset != null) {705 for (Map.Entry<String, String> e : uploadChangeset.getKeys().entrySet()) {706 ds.addChangeSetTag(e.getKey(), e.getValue());707 }708 }709 }710 711 /**712 525 * Parse the given input source and return the dataset. 713 526 * 714 527 * @param source the source input stream. Must not be null. … … 735 548 progressMonitor.worked(1); 736 549 737 550 progressMonitor.indeterminateSubTask(tr("Preparing data set...")); 738 reader.ds.beginUpdate(); 739 try { 740 reader.processNodesAfterParsing(); 741 reader.processWaysAfterParsing(); 742 reader.processRelationsAfterParsing(); 743 reader.processChangesetAfterParsing(); 744 } finally { 745 reader.ds.endUpdate(); 746 } 551 reader.prepareDataSet(); 747 552 progressMonitor.worked(1); 748 553 return reader.getDataSet(); 749 554 } catch(IllegalDataException e) { -
src/org/openstreetmap/josm/io/PbfImporter.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.io; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.io.File; 7 import java.io.InputStream; 8 9 import org.openstreetmap.josm.actions.ExtensionFileFilter; 10 import org.openstreetmap.josm.data.osm.DataSet; 11 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 12 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 13 14 /** 15 * @author Vincent 16 * 17 */ 18 public class PbfImporter extends OsmImporter { 19 20 public PbfImporter() { 21 super(new ExtensionFileFilter("osm.pbf", "osm.pbf", tr("OSM Server Files PBF compressed") + " (*.osm.pbf)")); 22 } 23 24 /* (non-Javadoc) 25 * @see org.openstreetmap.josm.io.OsmImporter#importData(java.io.InputStream, java.io.File) 26 */ 27 @Override 28 protected void importData(InputStream in, File associatedFile) throws IllegalDataException { 29 final DataSet dataSet = PbfReader.parseDataSet(in, NullProgressMonitor.INSTANCE); 30 final OsmDataLayer layer = new OsmDataLayer(dataSet, associatedFile.getName(), associatedFile); 31 addDataLayer(dataSet, layer, associatedFile.getPath()); 32 } 33 } -
src/org/openstreetmap/josm/io/PbfReader.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.io; 3 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.util.ArrayList; 9 import java.util.Collection; 10 import java.util.Date; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.Map; 14 15 import org.openstreetmap.josm.data.coor.LatLon; 16 import org.openstreetmap.josm.data.osm.DataSet; 17 import org.openstreetmap.josm.data.osm.Node; 18 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 19 import org.openstreetmap.josm.data.osm.Relation; 20 import org.openstreetmap.josm.data.osm.User; 21 import org.openstreetmap.josm.data.osm.Way; 22 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 23 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 24 import org.openstreetmap.josm.tools.CheckParameterUtil; 25 26 import crosby.binary.BinaryParser; 27 import crosby.binary.Osmformat; 28 import crosby.binary.Osmformat.DenseNodes; 29 import crosby.binary.Osmformat.HeaderBlock; 30 import crosby.binary.file.BlockInputStream; 31 import crosby.binary.file.FileBlockPosition; 32 33 /** 34 * @author Vincent 35 * 36 */ 37 public class PbfReader extends AbstractReader { 38 39 protected class PbfParser extends BinaryParser { 40 41 public IllegalDataException exception = null; 42 43 @Override 44 protected void parse(HeaderBlock header) { 45 } 46 47 /* (non-Javadoc) 48 * @see crosby.binary.BinaryParser#skipBlock(crosby.binary.file.FileBlockPosition) 49 */ 50 @Override 51 public boolean skipBlock(FileBlockPosition block) { 52 return exception != null; 53 } 54 55 protected void checkCoordinates(LatLon coor) throws IllegalDataException { 56 if (!coor.isValid()) { 57 throw new IllegalDataException(tr("Invalid coordinates: {0}", coor)); 58 } 59 } 60 61 protected void checkChangesetId(long id) throws IllegalDataException { 62 if (id > Integer.MAX_VALUE) { 63 throw new IllegalDataException(tr("Invalid changeset id: {0}", id)); 64 } 65 } 66 67 protected void checkTimestamp(long timestamp) throws IllegalDataException { 68 if (timestamp < 0) { 69 throw new IllegalDataException(tr("Invalid timestamp: {0}", timestamp)); 70 } 71 } 72 73 @Override 74 protected void parseDense(DenseNodes nodes) { 75 if (exception == null) { 76 try { 77 int keyIndex = 0; 78 // Almost all data is DELTA coded 79 long nodeId = 0; 80 long nodeLat = 0; 81 long nodeLon = 0; 82 long changesetId = 0; 83 int uid = 0; 84 int suid = 0; 85 long timestamp = 0; 86 for (int i = 0; i < nodes.getIdCount(); i++) { 87 // Id (delta) and version (normal) 88 Node node = new Node(nodeId+=nodes.getId(i), nodes.getDenseinfo().getVersion(i)); 89 // Lat/Lon (delta) 90 node.setCoor(new LatLon(parseLat(nodeLat+=nodes.getLat(i)), parseLon(nodeLon+=nodes.getLon(i)))); 91 checkCoordinates(node.getCoor()); 92 // Changeset (delta) 93 checkChangesetId(changesetId+=nodes.getDenseinfo().getChangeset(i)); 94 node.setChangesetId((int) changesetId); 95 // User (delta) 96 node.setUser(User.createOsmUser(uid+=nodes.getDenseinfo().getUid(i), getStringById(suid+=nodes.getDenseinfo().getUserSid(i)))); 97 // Timestamp (delta) 98 checkTimestamp(timestamp+=nodes.getDenseinfo().getTimestamp(i)); 99 node.setTimestamp(new Date(timestamp)); 100 // A single table contains all keys/values of all nodes. 101 // Each node's tags are encoded in alternating <key_id> <value_id>. 102 // A single stringid of 0 delimit when the tags of a node ends and the tags of the next node begin. 103 Map<String, String> keys = new HashMap<String, String>(); 104 while (keyIndex < nodes.getKeysValsCount()) { 105 int key_id = nodes.getKeysVals(keyIndex++); 106 if (key_id == 0) { 107 break; // End of current node's tags 108 } else if (keyIndex < nodes.getKeysValsCount()) { 109 int value_id = nodes.getKeysVals(keyIndex++); 110 keys.put(getStringById(key_id), getStringById(value_id)); 111 } else { 112 throw new IllegalDataException(tr("Invalid DenseNodes key/values table")); 113 } 114 } 115 node.setKeys(keys); 116 externalIdMap.put(node.getPrimitiveId(), node); 117 } 118 } catch (IllegalDataException e) { 119 exception = e; 120 } 121 } 122 } 123 124 @Override 125 protected void parseNodes(List<Osmformat.Node> osmNodes) { 126 if (exception == null) { 127 try { 128 for (Osmformat.Node n : osmNodes) { 129 Node node = new Node(n.getId(), n.getInfo().getVersion()); 130 node.setCoor(new LatLon(parseLat(n.getLat()), parseLon(n.getLon()))); 131 checkCoordinates(node.getCoor()); 132 checkChangesetId(n.getInfo().getChangeset()); 133 node.setChangesetId((int) n.getInfo().getChangeset()); 134 node.setUser(User.createOsmUser(n.getInfo().getUid(), getStringById(n.getInfo().getUserSid()))); 135 checkTimestamp(n.getInfo().getTimestamp()); 136 node.setTimestamp(new Date(n.getInfo().getTimestamp())); 137 Map<String, String> keys = new HashMap<String, String>(); 138 for (int i=0; i<n.getKeysCount(); i++) { 139 keys.put(getStringById(n.getKeys(i)), getStringById(n.getVals(i))); 140 } 141 node.setKeys(keys); 142 externalIdMap.put(node.getPrimitiveId(), node); 143 } 144 } catch (IllegalDataException e) { 145 exception = e; 146 } 147 } 148 } 149 150 @Override 151 protected void parseWays(List<Osmformat.Way> osmWays) { 152 if (exception == null) { 153 try { 154 for (Osmformat.Way w : osmWays) { 155 Way way = new Way(w.getId(), w.getInfo().getVersion()); 156 checkChangesetId(w.getInfo().getChangeset()); 157 way.setChangesetId((int) w.getInfo().getChangeset()); 158 way.setUser(User.createOsmUser(w.getInfo().getUid(), getStringById(w.getInfo().getUserSid()))); 159 checkTimestamp(w.getInfo().getTimestamp()); 160 way.setTimestamp(new Date(w.getInfo().getTimestamp())); 161 Map<String, String> keys = new HashMap<String, String>(); 162 for (int i=0; i<w.getKeysCount(); i++) { 163 keys.put(getStringById(w.getKeys(i)), getStringById(w.getVals(i))); 164 } 165 way.setKeys(keys); 166 long previousId = 0; // Node ids are delta coded 167 Collection<Long> nodeIds = new ArrayList<Long>(); 168 for (Long id : w.getRefsList()) { 169 nodeIds.add(previousId+=id); 170 } 171 ways.put(way.getUniqueId(), nodeIds); 172 externalIdMap.put(way.getPrimitiveId(), way); 173 } 174 } catch (IllegalDataException e) { 175 exception = e; 176 } 177 } 178 } 179 180 @Override 181 protected void parseRelations(List<Osmformat.Relation> osmRels) { 182 if (exception == null) { 183 try { 184 for (Osmformat.Relation r : osmRels) { 185 Relation rel = new Relation(r.getId(), r.getInfo().getVersion()); 186 checkChangesetId(r.getInfo().getChangeset()); 187 rel.setChangesetId((int) r.getInfo().getChangeset()); 188 rel.setUser(User.createOsmUser(r.getInfo().getUid(), getStringById(r.getInfo().getUserSid()))); 189 checkTimestamp(r.getInfo().getTimestamp()); 190 rel.setTimestamp(new Date(r.getInfo().getTimestamp())); 191 Map<String, String> keys = new HashMap<String, String>(); 192 for (int i=0; i<r.getKeysCount(); i++) { 193 keys.put(getStringById(r.getKeys(i)), getStringById(r.getVals(i))); 194 } 195 rel.setKeys(keys); 196 long previousId = 0; // Member ids are delta coded 197 Collection<RelationMemberData> members = new ArrayList<RelationMemberData>(); 198 for (int i = 0; i<r.getMemidsCount(); i++) { 199 RelationMemberData rmd = new RelationMemberData(); 200 rmd.id = previousId+=r.getMemids(i); 201 rmd.role = getStringById(r.getRolesSid(i)); 202 switch (r.getTypes(i)) { 203 case NODE: 204 rmd.type = OsmPrimitiveType.NODE; 205 break; 206 case WAY: 207 rmd.type = OsmPrimitiveType.WAY; 208 break; 209 case RELATION: 210 rmd.type = OsmPrimitiveType.RELATION; 211 break; 212 } 213 members.add(rmd); 214 } 215 relations.put(rel.getUniqueId(), members); 216 externalIdMap.put(rel.getPrimitiveId(), rel); 217 } 218 } catch (IllegalDataException e) { 219 exception = e; 220 } 221 } 222 } 223 224 @Override 225 public void complete() { 226 } 227 } 228 229 private PbfParser parser = new PbfParser(); 230 231 /** 232 * Parse the given input source and return the dataset. 233 * 234 * @param source the source input stream. Must not be null. 235 * @param progressMonitor the progress monitor. If null, {@see NullProgressMonitor#INSTANCE} is assumed 236 * 237 * @return the dataset with the parsed data 238 * @throws IllegalDataException thrown if the an error was found while parsing the data from the source 239 * @throws IllegalArgumentException thrown if source is null 240 */ 241 public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException { 242 if (progressMonitor == null) { 243 progressMonitor = NullProgressMonitor.INSTANCE; 244 } 245 CheckParameterUtil.ensureParameterNotNull(source, "source"); 246 247 PbfReader reader = new PbfReader(); 248 249 try { 250 progressMonitor.beginTask(tr("Prepare OSM data...", 2)); 251 progressMonitor.indeterminateSubTask(tr("Reading OSM data...")); 252 253 reader.parse(source); 254 progressMonitor.worked(1); 255 256 progressMonitor.indeterminateSubTask(tr("Preparing data set...")); 257 reader.prepareDataSet(); 258 progressMonitor.worked(1); 259 return reader.getDataSet(); 260 } catch (IllegalDataException e) { 261 throw e; 262 } catch (Exception e) { 263 throw new IllegalDataException(e); 264 } finally { 265 progressMonitor.finishTask(); 266 } 267 } 268 269 public void parse(InputStream source) throws IOException, IllegalDataException { 270 new BlockInputStream(source, parser).process(); 271 if (parser.exception != null) { 272 throw parser.exception; 273 } 274 } 275 }
