- * This class is not thread-safe. Each thread should use its own instance.
*
* @see Specification
*/
-public class MapDatabase implements IMapDatabase {
+public class MapDatabase implements ITileDataSource {
/**
* Bitmask to extract the block offset from an index entry.
*/
@@ -66,11 +61,6 @@ public class MapDatabase implements IMapDatabase {
*/
private static final String DEBUG_SIGNATURE_WAY = "way signature: ";
- /**
- * Amount of cache blocks that the index cache should store.
- */
- private static final int INDEX_CACHE_SIZE = 64;
-
/**
* Error message for an invalid first way offset.
*/
@@ -119,8 +109,6 @@ public class MapDatabase implements IMapDatabase {
*/
private static final int POI_NUMBER_OF_TAGS_BITMASK = 0x0f;
- private static final String READ_ONLY_MODE = "r";
-
/**
* Length of the debug signature at the beginning of each block.
*/
@@ -181,9 +169,6 @@ public class MapDatabase implements IMapDatabase {
*/
private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f;
- private static IndexCache sDatabaseIndexCache;
- private static MapFileHeader sMapFileHeader;
- private static int instances = 0;
private long mFileSize;
private boolean mDebugFile;
@@ -196,23 +181,18 @@ public class MapDatabase implements IMapDatabase {
private int mTileLongitude;
private int[] mIntBuffer;
- //private final GeometryBuffer mElem = new GeometryBuffer(1 << 14, 1 << 8);
- //private final WayData mWay = new WayData();
private final MapElement mElem = new MapElement();
private int minLat, minLon;
private Tile mTile;
- private static boolean sMapExperimental;
- /*
- * (non-Javadoc)
- * @see org.oscim.map.reader.IMapDatabase#executeQuery(org.oscim.core.Tile,
- * org.oscim.map.reader.MapDatabaseCallback)
- */
+ private final MapFileTileSource mTileSource;
+
+
@Override
- public QueryResult executeQuery(MapTile tile, IMapDataSink mapDataSink) {
+ public QueryResult executeQuery(MapTile tile, ITileDataSink mapDataSink) {
- if (sMapFileHeader == null)
+ if (mTileSource.fileHeader == null)
return QueryResult.FAILED;
if (mIntBuffer == null)
@@ -222,10 +202,10 @@ public class MapDatabase implements IMapDatabase {
mTile = tile;
QueryParameters queryParameters = new QueryParameters();
- queryParameters.queryZoomLevel = sMapFileHeader
+ queryParameters.queryZoomLevel = mTileSource.fileHeader
.getQueryZoomLevel(tile.zoomLevel);
// get and check the sub-file for the query zoom level
- SubFileParameter subFileParameter = sMapFileHeader
+ SubFileParameter subFileParameter = mTileSource.fileHeader
.getSubFileParameter(queryParameters.queryZoomLevel);
if (subFileParameter == null) {
Log.w(TAG, "no sub-file for zoom level: "
@@ -243,126 +223,35 @@ public class MapDatabase implements IMapDatabase {
return QueryResult.SUCCESS;
}
- /*
- * (non-Javadoc)
- * @see org.oscim.map.reader.IMapDatabase#getMapFileInfo()
- */
- @Override
- public MapFileInfo getMapInfo() {
- if (sMapFileHeader == null) {
- throw new IllegalStateException("no map file is currently opened");
- }
- return sMapFileHeader.getMapFileInfo();
- }
+ public MapDatabase(MapFileTileSource tileSource) throws IOException {
+ mTileSource = tileSource;
+ try {
+ // open the file in read only mode
+ mInputFile = new RandomAccessFile(tileSource.mapFile, "r");
+ mFileSize = mInputFile.length();
+ mReadBuffer = new ReadBuffer(mInputFile);
- @Override
- public String getMapProjection() {
- return "WSG84";
- }
-
- /*
- * (non-Javadoc)
- * @see org.oscim.map.reader.IMapDatabase#hasOpenFile()
- */
- @Override
- public boolean isOpen() {
- return mInputFile != null;
- }
-
- /*
- * (non-Javadoc)
- * @see org.oscim.map.reader.IMapDatabase#openFile(java.io.File)
- */
- @Override
- public OpenResult open(MapOptions options) {
- try {
- if (options.get("file") == null) {
- throw new IllegalArgumentException("'file' must not be null");
+ } catch (IOException e) {
+ Log.e(TAG, e.getMessage());
+ // make sure that the file is closed
+ destroy();
+ throw new IOException();
}
-
- // make sure to close any previously opened file first
- //close();
-
- File file = new File(options.get("file"));
-
- Log.d(TAG, file.getAbsolutePath());
-
- // File file = new File(options.get("mapfile"));
-
- // check if the file exists and is readable
- if (!file.exists()) {
- return new OpenResult("file does not exist: " + file);
- } else if (!file.isFile()) {
- return new OpenResult("not a file: " + file);
- } else if (!file.canRead()) {
- return new OpenResult("cannot read file: " + file);
- }
-
- // open the file in read only mode
- mInputFile = new RandomAccessFile(file, READ_ONLY_MODE);
- mFileSize = mInputFile.length();
- mReadBuffer = new ReadBuffer(mInputFile);
-
- Log.d(TAG, "open instance " + instances + " " + file.getAbsolutePath());
- if (instances++ > 0) {
- return OpenResult.SUCCESS;
- }
-
- sMapFileHeader = new MapFileHeader();
- OpenResult openResult = sMapFileHeader.readHeader(mReadBuffer,
- mFileSize);
- if (!openResult.isSuccess()) {
- close();
- return openResult;
- }
-
- sDatabaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
- sMapExperimental = sMapFileHeader.getMapFileInfo().fileVersion == 4;
-
- Log.d(TAG, "File version: " + sMapFileHeader.getMapFileInfo().fileVersion);
- return OpenResult.SUCCESS;
- } catch (IOException e) {
- Log.e(TAG, e.getMessage());
- // make sure that the file is closed
- close();
- return new OpenResult(e.getMessage());
- }
- }
-
- /*
- * (non-Javadoc)
- * @see org.oscim.map.reader.IMapDatabase#closeFile()
- */
- @Override
- public void close() {
- if (instances == 0)
- return;
-
- instances--;
- Log.d(TAG, "close instance " + instances);
-
- if (instances > 0) {
- mReadBuffer = null;
- return;
}
- try {
- sMapFileHeader = null;
+ @Override
+ public void destroy() {
+ mReadBuffer = null;
+ if (mInputFile != null) {
- if (sDatabaseIndexCache != null) {
- sDatabaseIndexCache.destroy();
- sDatabaseIndexCache = null;
- }
-
- if (mInputFile != null) {
+ try {
mInputFile.close();
mInputFile = null;
+ } catch (IOException e) {
+ Log.e(TAG, e.getMessage());
}
-
- mReadBuffer = null;
- } catch (IOException e) {
- Log.e(TAG, e.getMessage());
}
+
}
/**
@@ -388,7 +277,7 @@ public class MapDatabase implements IMapDatabase {
*/
private void processBlock(QueryParameters queryParameters,
SubFileParameter subFileParameter,
- IMapDataSink mapDataSink) {
+ ITileDataSink mapDataSink) {
if (!processBlockSignature()) {
return;
}
@@ -442,7 +331,7 @@ public class MapDatabase implements IMapDatabase {
}
- private void processBlocks(IMapDataSink mapDataSink,
+ private void processBlocks(ITileDataSink mapDataSink,
QueryParameters queryParameters,
SubFileParameter subFileParameter) throws IOException {
boolean queryIsWater = true;
@@ -457,7 +346,7 @@ public class MapDatabase implements IMapDatabase {
long blockNumber = row * subFileParameter.blocksWidth + column;
// get the current index entry
- long currentBlockIndexEntry = sDatabaseIndexCache.getIndexEntry(
+ long currentBlockIndexEntry = mTileSource.databaseIndexCache.getIndexEntry(
subFileParameter, blockNumber);
// check if the current query would still return a water tile
@@ -484,7 +373,7 @@ public class MapDatabase implements IMapDatabase {
nextBlockPointer = subFileParameter.subFileSize;
} else {
// get and check the next block pointer
- nextBlockPointer = sDatabaseIndexCache.getIndexEntry(
+ nextBlockPointer = mTileSource.databaseIndexCache.getIndexEntry(
subFileParameter, blockNumber + 1)
& BITMASK_INDEX_OFFSET;
if (nextBlockPointer < 1
@@ -510,7 +399,7 @@ public class MapDatabase implements IMapDatabase {
Log.w(TAG, "current block size too large: " + currentBlockSize);
continue;
} else if (currentBlockPointer + currentBlockSize > mFileSize) {
- Log.w(TAG, "current block largher than file size: "
+ Log.w(TAG, "current block larger than file size: "
+ currentBlockSize);
return;
}
@@ -535,11 +424,7 @@ public class MapDatabase implements IMapDatabase {
mTileLatitude = (int) (tileLatitudeDeg * 1000000);
mTileLongitude = (int) (tileLongitudeDeg * 1000000);
- //try {
processBlock(queryParameters, subFileParameter, mapDataSink);
- //} catch (ArrayIndexOutOfBoundsException e) {
- // Log.e(TAG, e.getMessage());
- //}
}
}
@@ -584,8 +469,8 @@ public class MapDatabase implements IMapDatabase {
* @return true if the POIs could be processed successfully, false
* otherwise.
*/
- private boolean processPOIs(IMapDataSink mapDataSink, int numberOfPois) {
- Tag[] poiTags = sMapFileHeader.getMapFileInfo().poiTags;
+ private boolean processPOIs(ITileDataSink mapDataSink, int numberOfPois) {
+ Tag[] poiTags = mTileSource.fileInfo.poiTags;
Tag[] tags = null;
Tag[] curTags;
@@ -827,12 +712,12 @@ public class MapDatabase implements IMapDatabase {
* otherwise.
*/
private boolean processWays(QueryParameters queryParameters,
- IMapDataSink mapDataSink,
+ ITileDataSink mapDataSink,
int numberOfWays) {
Tag[] tags = null;
Tag[] curTags;
- Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
+ Tag[] wayTags = mTileSource.fileInfo.wayTags;
int wayDataBlocks;
@@ -840,7 +725,7 @@ public class MapDatabase implements IMapDatabase {
int stringsSize = 0;
stringOffset = 0;
- if (sMapExperimental) {
+ if (mTileSource.experimental) {
stringsSize = mReadBuffer.readUnsignedInt();
stringOffset = mReadBuffer.getBufferPosition();
mReadBuffer.skipBytes(stringsSize);
@@ -867,7 +752,7 @@ public class MapDatabase implements IMapDatabase {
if (elementCounter < 0)
return false;
- if (sMapExperimental && mReadBuffer.lastTagPosition > 0) {
+ if (mTileSource.experimental && mReadBuffer.lastTagPosition > 0) {
int pos = mReadBuffer.getBufferPosition();
mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition);
@@ -928,7 +813,7 @@ public class MapDatabase implements IMapDatabase {
System.arraycopy(tags, 0, curTags, 0, tags.length);
}
- if (sMapExperimental) {
+ if (mTileSource.experimental) {
if (hasName) {
int textPos = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
@@ -947,7 +832,6 @@ public class MapDatabase implements IMapDatabase {
} else {
if (hasName) {
String str = mReadBuffer.readUTF8EncodedString();
- Log.d(TAG, "way name: " + str);
curTags[addTag++] = new Tag(Tag.TAG_KEY_NAME, str, false);
}
if (hasHouseNr) {
@@ -1043,7 +927,7 @@ public class MapDatabase implements IMapDatabase {
|| cumulatedNumberOfWays > MAXIMUM_ZOOM_TABLE_OBJECTS) {
Log.w(TAG, "invalid cumulated number of ways in row " + row + ' '
+ cumulatedNumberOfWays);
- if (sMapFileHeader.getMapFileInfo().debugFile) {
+ if (mTileSource.fileInfo.debugFile) {
Log.w(TAG, DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
}
return null;
@@ -1056,12 +940,6 @@ public class MapDatabase implements IMapDatabase {
return zoomTable;
}
- @Override
- public void cancel() {
- // TODO Auto-generated method stub
-
- }
-
private static final double PI180 = (Math.PI / 180) / 1000000.0;
private static final double PIx4 = Math.PI * 4;
diff --git a/src/org/oscim/tilesource/mapfile/MapFileTileSource.java b/src/org/oscim/tilesource/mapfile/MapFileTileSource.java
new file mode 100644
index 00000000..4f5b9aa4
--- /dev/null
+++ b/src/org/oscim/tilesource/mapfile/MapFileTileSource.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2013 Hannes Janetzek
+ * Copyright 2013 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