Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 99 additions & 63 deletions src.java/crosby/binary/BinaryParser.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

*/

package crosby.binary;


import java.io.UncheckedIOException;
import java.util.Date;
import java.util.List;

Expand All @@ -29,109 +23,151 @@ License, or (at your option) any later version.
import crosby.binary.file.FileBlockPosition;
import crosby.binary.file.FileFormatException;

/**
* Abstract base class for parsing OpenStreetMap binary (PBF) data blocks.
* Handles decoding of OSMHeader and OSMData blocks and delegates the
* parsing of entities (nodes, ways, relations) to subclasses.
*/
public abstract class BinaryParser implements BlockReaderAdapter {

protected int granularity;
private long lat_offset;
private long lon_offset;
protected int date_granularity;
private String[] strings;

/** Take a Info protocol buffer containing a date and convert it into a java Date object */
/** Constant representing an undefined date. */
public static final Date NODATE = new Date(-1);

/**
* Convert an OSM Info protobuf timestamp to a Java {@link Date} object.
*
* @param info the OSM Info message containing timestamp
* @return a Date object, or NODATE if no timestamp is available
*/
protected Date getDate(Osmformat.Info info) {
if (info.hasTimestamp()) {
return new Date(date_granularity * info.getTimestamp());
} else
return NODATE;
if (info.hasTimestamp()) {
return new Date(date_granularity * info.getTimestamp());
} else {
return NODATE;
}
}
public static final Date NODATE = new Date(-1);

/** Get a string based on the index used.
*
* Index 0 is reserved to use as a delimiter, therefore, index 1 corresponds to the first string in the table
* @param id the index
* @return the string at the given index
/**
* Retrieve a string from the string table using its ID.
* Index 0 is reserved as a delimiter and should not be used.
*
* @param id index in the string table
* @return the corresponding string, or null if out of range
*/
protected String getStringById(int id) {
return strings[id];
if (id < 0 || id >= strings.length) {
return null;
}
return strings[id];
}


/**
* Handles a single block from the PBF file and delegates it to the appropriate parser.
*
* @param message the FileBlock message containing type and data
*/
@Override
public void handleBlock(FileBlock message) {
try {
if (message.getType().equals("OSMHeader")) {
Osmformat.HeaderBlock headerblock = Osmformat.HeaderBlock
.parseFrom(message.getData());
parse(headerblock);
} else if (message.getType().equals("OSMData")) {
Osmformat.PrimitiveBlock primblock = Osmformat.PrimitiveBlock
.parseFrom(message.getData());
parse(primblock);
if ("OSMHeader".equals(message.getType())) {
Osmformat.HeaderBlock headerBlock =
Osmformat.HeaderBlock.parseFrom(message.getData());
parse(headerBlock);
} else if ("OSMData".equals(message.getType())) {
Osmformat.PrimitiveBlock primBlock =
Osmformat.PrimitiveBlock.parseFrom(message.getData());
parse(primBlock);
}
} catch (InvalidProtocolBufferException e) {
throw new UncheckedIOException(new FileFormatException(e));
throw new FileFormatException(e);
}

}


/**
* Determines whether to skip reading a block based on its type.
*
* @param block the block position and metadata
* @return true if the block should be skipped
*/
@Override
public boolean skipBlock(FileBlockPosition block) {
// System.out.println("Seeing block of type: "+block.getType());
if (block.getType().equals("OSMData"))
return false;
if (block.getType().equals("OSMHeader"))
return false;
if ("OSMData".equals(block.getType())) return false;
if ("OSMHeader".equals(block.getType())) return false;

System.out.println("Skipped block of type: " + block.getType());
return true;
}


/** Convert a latitude value stored in a protobuf into a double, compensating for granularity and latitude offset */

/**
* Convert a latitude value stored in the protobuf into a double
* compensating for granularity and latitude offset.
*
* @param degree the stored latitude value
* @return latitude in degrees
*/
public double parseLat(long degree) {
// Support non-zero offsets. (We don't currently generate them)
return (granularity * degree + lat_offset) * .000000001;
return (granularity * degree + lat_offset) * 1e-9;
}

/** Convert a longitude value stored in a protobuf into a double, compensating for granularity and longitude offset */
/**
* Convert a longitude value stored in the protobuf into a double
* compensating for granularity and longitude offset.
*
* @param degree the stored longitude value
* @return longitude in degrees
*/
public double parseLon(long degree) {
// Support non-zero offsets. (We don't currently generate them)
return (granularity * degree + lon_offset) * .000000001;
return (granularity * degree + lon_offset) * 1e-9;
}

/** Parse a Primitive block (containing a string table, other paramaters, and PrimitiveGroups */

/**
* Parse a PrimitiveBlock (contains string table, metadata, and PrimitiveGroups)
* and dispatch each group to the appropriate parser method.
*
* @param block the OSM PrimitiveBlock
*/
public void parse(Osmformat.PrimitiveBlock block) {
Osmformat.StringTable stablemessage = block.getStringtable();
strings = new String[stablemessage.getSCount()];
Osmformat.StringTable stringTable = block.getStringtable();
strings = new String[stringTable.getSCount()];

for (int i = 0; i < strings.length; i++) {
strings[i] = stablemessage.getS(i).toStringUtf8();
strings[i] = stringTable.getS(i).toStringUtf8();
}

granularity = block.getGranularity();
lat_offset = block.getLatOffset();
lon_offset = block.getLonOffset();
date_granularity = block.getDateGranularity();

for (Osmformat.PrimitiveGroup groupmessage : block
.getPrimitivegroupList()) {
for (Osmformat.PrimitiveGroup group : block.getPrimitivegroupList()) {
// Exactly one of these should trigger on each loop.
parseNodes(groupmessage.getNodesList());
parseWays(groupmessage.getWaysList());
parseRelations(groupmessage.getRelationsList());
if (groupmessage.hasDense())
parseDense(groupmessage.getDense());
parseNodes(group.getNodesList());
parseWays(group.getWaysList());
parseRelations(group.getRelationsList());
if (group.hasDense()) {
parseDense(group.getDense());
}
}
}
/** Parse a list of Relation protocol buffers and send the resulting relations to a sink. */

/** Parse a list of Relation protobufs and send the resulting relations to a sink. */
protected abstract void parseRelations(List<Osmformat.Relation> rels);
/** Parse a DenseNode protocol buffer and send the resulting nodes to a sink. */

/** Parse a DenseNodes protobuf and send the resulting nodes to a sink. */
protected abstract void parseDense(Osmformat.DenseNodes nodes);
/** Parse a list of Node protocol buffers and send the resulting nodes to a sink. */

/** Parse a list of Node protobufs and send the resulting nodes to a sink. */
protected abstract void parseNodes(List<Osmformat.Node> nodes);
/** Parse a list of Way protocol buffers and send the resulting ways to a sink. */

/** Parse a list of Way protobufs and send the resulting ways to a sink. */
protected abstract void parseWays(List<Osmformat.Way> ways);
/** Parse a header message. */
protected abstract void parse(Osmformat.HeaderBlock header);

}
/** Parse a HeaderBlock protobuf. */
protected abstract void parse(Osmformat.HeaderBlock header);
}
Loading