240 lines
8.2 KiB
Java
240 lines
8.2 KiB
Java
/*
|
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
|
*
|
|
* 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.oscim.database.mapfile.header;
|
|
|
|
import java.io.IOException;
|
|
|
|
import org.oscim.core.BoundingBox;
|
|
import org.oscim.core.Tag;
|
|
import org.oscim.database.IMapDatabase.OpenResult;
|
|
import org.oscim.database.mapfile.ReadBuffer;
|
|
|
|
final class RequiredFields {
|
|
/**
|
|
* Magic byte at the beginning of a valid binary map file.
|
|
*/
|
|
private static final String BINARY_OSM_MAGIC_BYTE = "mapsforge binary OSM";
|
|
|
|
/**
|
|
* Maximum size of the file header in bytes.
|
|
*/
|
|
private static final int HEADER_SIZE_MAX = 1000000;
|
|
|
|
/**
|
|
* Minimum size of the file header in bytes.
|
|
*/
|
|
private static final int HEADER_SIZE_MIN = 70;
|
|
|
|
/**
|
|
* The name of the Mercator projection as stored in the file header.
|
|
*/
|
|
private static final String MERCATOR = "Mercator";
|
|
|
|
/**
|
|
* A single whitespace character.
|
|
*/
|
|
private static final char SPACE = ' ';
|
|
|
|
/**
|
|
* Version of the map file format which is supported by this implementation.
|
|
*/
|
|
private static final int FILE_VERSION_3 = 3;
|
|
private static final int FILE_VERSION_4 = 4;
|
|
|
|
/**
|
|
* The maximum latitude values in microdegrees.
|
|
*/
|
|
static final int LATITUDE_MAX = 90000000;
|
|
|
|
/**
|
|
* The minimum latitude values in microdegrees.
|
|
*/
|
|
static final int LATITUDE_MIN = -90000000;
|
|
|
|
/**
|
|
* The maximum longitude values in microdegrees.
|
|
*/
|
|
static final int LONGITUDE_MAX = 180000000;
|
|
|
|
/**
|
|
* The minimum longitude values in microdegrees.
|
|
*/
|
|
static final int LONGITUDE_MIN = -180000000;
|
|
|
|
static OpenResult readBoundingBox(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the minimum latitude (4 bytes)
|
|
int minLatitude = readBuffer.readInt();
|
|
if (minLatitude < LATITUDE_MIN || minLatitude > LATITUDE_MAX) {
|
|
return new OpenResult("invalid minimum latitude: " + minLatitude);
|
|
}
|
|
|
|
// get and check the minimum longitude (4 bytes)
|
|
int minLongitude = readBuffer.readInt();
|
|
if (minLongitude < LONGITUDE_MIN || minLongitude > LONGITUDE_MAX) {
|
|
return new OpenResult("invalid minimum longitude: " + minLongitude);
|
|
}
|
|
|
|
// get and check the maximum latitude (4 bytes)
|
|
int maxLatitude = readBuffer.readInt();
|
|
if (maxLatitude < LATITUDE_MIN || maxLatitude > LATITUDE_MAX) {
|
|
return new OpenResult("invalid maximum latitude: " + maxLatitude);
|
|
}
|
|
|
|
// get and check the maximum longitude (4 bytes)
|
|
int maxLongitude = readBuffer.readInt();
|
|
if (maxLongitude < LONGITUDE_MIN || maxLongitude > LONGITUDE_MAX) {
|
|
return new OpenResult("invalid maximum longitude: " + maxLongitude);
|
|
}
|
|
|
|
// check latitude and longitude range
|
|
if (minLatitude > maxLatitude) {
|
|
return new OpenResult("invalid latitude range: " + minLatitude + SPACE + maxLatitude);
|
|
} else if (minLongitude > maxLongitude) {
|
|
return new OpenResult("invalid longitude range: " + minLongitude + SPACE + maxLongitude);
|
|
}
|
|
|
|
mapFileInfoBuilder.boundingBox = new BoundingBox(minLatitude, minLongitude, maxLatitude,
|
|
maxLongitude);
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readFileSize(ReadBuffer readBuffer, long fileSize,
|
|
MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the file size (8 bytes)
|
|
long headerFileSize = readBuffer.readLong();
|
|
if (headerFileSize != fileSize) {
|
|
return new OpenResult("invalid file size: " + headerFileSize);
|
|
}
|
|
mapFileInfoBuilder.fileSize = fileSize;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readFileVersion(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the file version (4 bytes)
|
|
int fileVersion = readBuffer.readInt();
|
|
if (fileVersion != FILE_VERSION_3 && fileVersion != FILE_VERSION_4) {
|
|
return new OpenResult("unsupported file version: " + fileVersion);
|
|
}
|
|
mapFileInfoBuilder.fileVersion = fileVersion;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readMagicByte(ReadBuffer readBuffer) throws IOException {
|
|
// read the the magic byte and the file header size into the buffer
|
|
int magicByteLength = BINARY_OSM_MAGIC_BYTE.length();
|
|
if (!readBuffer.readFromFile(magicByteLength + 4)) {
|
|
return new OpenResult("reading magic byte has failed");
|
|
}
|
|
|
|
// get and check the magic byte
|
|
String magicByte = readBuffer.readUTF8EncodedString(magicByteLength);
|
|
if (!BINARY_OSM_MAGIC_BYTE.equals(magicByte)) {
|
|
return new OpenResult("invalid magic byte: " + magicByte);
|
|
}
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readMapDate(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the the map date (8 bytes)
|
|
long mapDate = readBuffer.readLong();
|
|
// is the map date before 2010-01-10 ?
|
|
if (mapDate < 1200000000000L) {
|
|
return new OpenResult("invalid map date: " + mapDate);
|
|
}
|
|
mapFileInfoBuilder.mapDate = mapDate;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readPoiTags(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the number of POI tags (2 bytes)
|
|
int numberOfPoiTags = readBuffer.readShort();
|
|
if (numberOfPoiTags < 0) {
|
|
return new OpenResult("invalid number of POI tags: " + numberOfPoiTags);
|
|
}
|
|
|
|
Tag[] poiTags = new Tag[numberOfPoiTags];
|
|
for (int currentTagId = 0; currentTagId < numberOfPoiTags; ++currentTagId) {
|
|
// get and check the POI tag
|
|
String tag = readBuffer.readUTF8EncodedString();
|
|
if (tag == null) {
|
|
return new OpenResult("POI tag must not be null: " + currentTagId);
|
|
}
|
|
poiTags[currentTagId] = new Tag(tag);
|
|
}
|
|
mapFileInfoBuilder.poiTags = poiTags;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readProjectionName(ReadBuffer readBuffer,
|
|
MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the projection name
|
|
String projectionName = readBuffer.readUTF8EncodedString();
|
|
if (!MERCATOR.equals(projectionName)) {
|
|
return new OpenResult("unsupported projection: " + projectionName);
|
|
}
|
|
mapFileInfoBuilder.projectionName = projectionName;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readRemainingHeader(ReadBuffer readBuffer) throws IOException {
|
|
// get and check the size of the remaining file header (4 bytes)
|
|
int remainingHeaderSize = readBuffer.readInt();
|
|
if (remainingHeaderSize < HEADER_SIZE_MIN || remainingHeaderSize > HEADER_SIZE_MAX) {
|
|
return new OpenResult("invalid remaining header size: " + remainingHeaderSize);
|
|
}
|
|
|
|
// read the header data into the buffer
|
|
if (!readBuffer.readFromFile(remainingHeaderSize)) {
|
|
return new OpenResult("reading header data has failed: " + remainingHeaderSize);
|
|
}
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readTilePixelSize(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the tile pixel size (2 bytes)
|
|
int tilePixelSize = readBuffer.readShort();
|
|
// if (tilePixelSize != Tile.SIZE) {
|
|
// return new FileOpenResult("unsupported tile pixel size: " + tilePixelSize);
|
|
// }
|
|
mapFileInfoBuilder.tilePixelSize = tilePixelSize;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
static OpenResult readWayTags(ReadBuffer readBuffer, MapFileInfoBuilder mapFileInfoBuilder) {
|
|
// get and check the number of way tags (2 bytes)
|
|
int numberOfWayTags = readBuffer.readShort();
|
|
if (numberOfWayTags < 0) {
|
|
return new OpenResult("invalid number of way tags: " + numberOfWayTags);
|
|
}
|
|
|
|
Tag[] wayTags = new Tag[numberOfWayTags];
|
|
|
|
for (int currentTagId = 0; currentTagId < numberOfWayTags; ++currentTagId) {
|
|
// get and check the way tag
|
|
String tag = readBuffer.readUTF8EncodedString();
|
|
if (tag == null) {
|
|
return new OpenResult("way tag must not be null: " + currentTagId);
|
|
}
|
|
wayTags[currentTagId] = new Tag(tag);
|
|
}
|
|
mapFileInfoBuilder.wayTags = wayTags;
|
|
return OpenResult.SUCCESS;
|
|
}
|
|
|
|
private RequiredFields() {
|
|
throw new IllegalStateException();
|
|
}
|
|
}
|