add versioning of index files

git-svn-id: https://osmand.googlecode.com/svn/trunk@157 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-12 15:08:59 +00:00
parent 3096a83555
commit f6d509325b
10 changed files with 250 additions and 104 deletions

View file

@ -23,16 +23,12 @@ public class ToDoConstants {
public int DESCRIBE_ABOUT_AUTHORS = 8;
// TODO ANDROID
// 31. Translation.
// 32. Introduce POI predefined filters (car filter(other-fuel, transportation-car_wash, show-car) and others)
// ( 1) predefined filters, 2) choose subtype's, 3) filter by name, 4) opening hours (filter))
// [TODO database support]
// 41. POI layer over map (shows poi by selected filter) [TODO]
// 8. Enable change POI directly on map (requires OSM login)
// 33. Build transport locations. Create transport index (transport-stops) (investigate) [TODO]
// 39. Support old-versionned resources (1) odb indexes, 2) favourites table, 3) atomic settings (?)) [TODO]
// 42. Revise UI (icons/layouts). Support different devices. Add inactive/focus(!) icon versions.
// 36. Postcode search
@ -42,7 +38,7 @@ public class ToDoConstants {
// 40. Support simple vector road rendering (require new index file)
// 43. Enable poi filter by name
// 26. Show the whole street on map (when it is chosen in search activity). Possibly extend that story to show layer with streets. (?)
// 20. Implement save track/route to gpx (?)
@ -63,6 +59,8 @@ public class ToDoConstants {
// DONE ANDROID :
// 39. Support old-versionned resources (1) odb indexes, 2) favourites table, 3) atomic settings (?)) [TODO]
// 41. POI layer over map (shows poi by selected filter)
// 38. Add button in search "navigate to"
// 16. Support open street bugs api (supports viewing, deleting).
// 13. Save point as favorite & introduce favorite points dialog

View file

@ -31,10 +31,12 @@ import com.osmand.osm.Way;
public class DataIndexWriter {
private final File workingDir;
private final Region region;
private static final Log log = LogUtil.getLog(DataIndexWriter.class);
private static final int BATCH_SIZE = 1000;
public DataIndexWriter(File workingDir, Region region){
@ -70,6 +72,7 @@ public class DataIndexWriter {
assert IndexPoiTable.values().length == 8;
stat.executeUpdate(IndexConstants.generateCreateSQL(IndexPoiTable.values()));
stat.executeUpdate(IndexConstants.generateCreateIndexSQL(IndexPoiTable.values()));
stat.execute("PRAGMA user_version = " + IndexConstants.POI_TABLE_VERSION);
stat.close();
PreparedStatement prep = conn.prepareStatement(
@ -129,6 +132,7 @@ public class DataIndexWriter {
stat.executeUpdate(IndexConstants.generateCreateIndexSQL(IndexStreetNodeTable.values()));
stat.executeUpdate(IndexConstants.generateCreateSQL(IndexStreetTable.values()));
stat.executeUpdate(IndexConstants.generateCreateIndexSQL(IndexStreetTable.values()));
stat.execute("PRAGMA user_version = " + IndexConstants.ADDRESS_TABLE_VERSION);
stat.close();
PreparedStatement prepCity = conn.prepareStatement(

View file

@ -2,6 +2,9 @@ package com.osmand.data.index;
public class IndexConstants {
public final static int POI_TABLE_VERSION = 0;
public final static int ADDRESS_TABLE_VERSION = 0;
public static final String POI_INDEX_DIR = "POI/";
public static final String ADDRESS_INDEX_DIR = "Address/";

View file

@ -129,7 +129,7 @@ public class AmenityIndexRepository {
return checkCachedAmenities(topLatitude, leftLongitude, bottomLatitude, rightLongitude, zoom, filterId, toFill, false);
}
public void initialize(final IProgress progress, File file) {
public boolean initialize(final IProgress progress, File file) {
long start = System.currentTimeMillis();
if(db != null){
// close previous db
@ -137,6 +137,10 @@ public class AmenityIndexRepository {
}
db = SQLiteDatabase.openOrCreateDatabase(file, null);
name = file.getName().substring(0, file.getName().indexOf('.'));
if(db.getVersion() != IndexConstants.POI_TABLE_VERSION){
return false;
}
Cursor query = db.query(IndexPoiTable.getTable(), new String[]{"MAX(latitude)", "MAX(longitude)", "MIN(latitude)", "MIN(longitude)"}, null, null,null, null, null);
if(query.moveToFirst()){
dataTopLatitude = query.getDouble(0);
@ -148,7 +152,7 @@ public class AmenityIndexRepository {
if (log.isDebugEnabled()) {
log.debug("Initializing db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + "ms");
}
return true;
}
public synchronized void close(){

View file

@ -171,7 +171,10 @@ public class PoiFilter {
b.append(")");
return b.toString();
}
public Map<AmenityType, List<String>> getAcceptedTypes(){
return new LinkedHashMap<AmenityType, List<String>>(acceptedTypes);
}
public void selectSubTypesToAccept(AmenityType t, List<String> accept){

View file

@ -8,6 +8,9 @@ import java.util.Map;
import com.osmand.data.AmenityType;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class PoiFiltersHelper {
@ -33,7 +36,7 @@ public class PoiFiltersHelper {
return null;
}
public static List<PoiFilter> getUserDefinedDefaultFilters(Context ctx){
private static List<PoiFilter> getUserDefinedDefaultFilters(){
List<PoiFilter> filters = new ArrayList<PoiFilter>();
Map<AmenityType, List<String>> types = new LinkedHashMap<AmenityType, List<String>>();
@ -98,10 +101,12 @@ public class PoiFiltersHelper {
private static List<PoiFilter> cacheUserDefinedFilters;
public static List<PoiFilter> getUserDefinedPoiFilters(Context ctx){
if(cacheUserDefinedFilters == null){
cacheUserDefinedFilters = new ArrayList<PoiFilter>();
ctx.deleteDatabase(PoiFilterDbHelper.DATABASE_NAME);
// TODO
cacheUserDefinedFilters.addAll(getUserDefinedDefaultFilters(ctx));
cacheUserDefinedFilters = new ArrayList<PoiFilter>();
PoiFilterDbHelper helper = new PoiFilterDbHelper(ctx);
cacheUserDefinedFilters.addAll(helper.getFilters());
helper.close();
}
return cacheUserDefinedFilters;
}
@ -110,7 +115,7 @@ public class PoiFiltersHelper {
public static List<PoiFilter> getOsmDefinedPoiFilters(Context ctx){
if(cacheOsmDefinedFilters == null){
cacheOsmDefinedFilters = new ArrayList<PoiFilter>();
// for test purposes
// TODO for test purposes
cacheOsmDefinedFilters.addAll(getUserDefinedPoiFilters(ctx));
cacheOsmDefinedFilters.add(new PoiFilter(null));
for(AmenityType t : AmenityType.values()){
@ -121,90 +126,162 @@ public class PoiFiltersHelper {
}
public static boolean removePoiFilter(Context ctx, PoiFilter filter){
return false;
PoiFilterDbHelper helper = new PoiFilterDbHelper(ctx);
boolean res = helper.deleteFilter(filter);
if(res){
getUserDefinedPoiFilters(ctx).remove(filter);
}
helper.close();
return res;
}
public static boolean createPoiFilter(Context ctx, PoiFilter filter){
return false;
PoiFilterDbHelper helper = new PoiFilterDbHelper(ctx);
boolean res = helper.addFilter(filter, helper.getWritableDatabase(), false);
if(res){
getUserDefinedPoiFilters(ctx).add(filter);
}
helper.close();
return res;
}
public static boolean commitPoiFilter(Context ctx, PoiFilter filter){
return false;
public static boolean editPoiFilter(Context ctx, PoiFilter filter){
PoiFilterDbHelper helper = new PoiFilterDbHelper(ctx);
boolean res = helper.editFilter(filter);
helper.close();
return res;
}
// protected static class PoiFilterDbHelper extends SQLiteOpenHelper {
//
// private static final int DATABASE_VERSION = 1;
// private static final String POI_FILTERS_NAME = "poi_filters";
// private static final String FAVOURITE_COL_NAME = "name";
// private static final String FAVOURITE_COL_LAT = "latitude";
// private static final String FAVOURITE_COL_LON = "longitude";
// private static final String FAVOURITE_TABLE_CREATE = "CREATE TABLE " + FAVOURITE_TABLE_NAME + " (" +
// FAVOURITE_COL_NAME + " TEXT, " + FAVOURITE_COL_LAT + " double, " +
// FAVOURITE_COL_LON + " double);";
//
// PoiFilterDbHelper(Context context) {
// super(context, POI_FILTERS_NAME, null, DATABASE_VERSION);
// }
//
// public boolean addFavourite(FavouritePoint p){
// SQLiteDatabase db = getWritableDatabase();
// if(db != null){
// db.execSQL("INSERT INTO " + FAVOURITE_TABLE_NAME + " VALUES (?, ?, ?)",new Object[]{p.getName(), p.getLatitude(), p.getLongitude()});
// return true;
// }
// return false;
// }
//
// public List<FavouritePoint> getFavouritePoints(){
// SQLiteDatabase db = getReadableDatabase();
// ArrayList<FavouritePoint> list = new ArrayList<FavouritePoint>();
// if(db != null){
// Cursor query = db.rawQuery("SELECT " + FAVOURITE_COL_NAME +", " + FAVOURITE_COL_LAT +"," + FAVOURITE_COL_LON +" FROM " +
// FAVOURITE_TABLE_NAME, null);
// if(query.moveToFirst()){
// do {
// FavouritePoint p = new FavouritePoint();
// p.setName(query.getString(0));
// p.setLatitude(query.getDouble(1));
// p.setLongitude(query.getDouble(2));
// list.add(p);
// } while(query.moveToNext());
// }
// query.close();
// }
// return list;
// }
//
// public boolean editFavouriteName(FavouritePoint p, String newName){
// SQLiteDatabase db = getWritableDatabase();
// if(db != null){
// db.execSQL("UPDATE " + FAVOURITE_TABLE_NAME + " SET name = ? WHERE name = ?",new Object[]{newName, p.getName()});
// p.setName(newName);
// return true;
// }
// return false;
// }
//
// public boolean deleteFavourite(FavouritePoint p){
// SQLiteDatabase db = getWritableDatabase();
// if(db != null){
// db.execSQL("DELETE FROM " + FAVOURITE_TABLE_NAME + " WHERE name = ?",new Object[]{p.getName()});
// return true;
// }
// return false;
// }
//
//
// @Override
// public void onCreate(SQLiteDatabase db) {
// db.execSQL(FAVOURITE_TABLE_CREATE);
// }
//
// @Override
// public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// }
// }
protected static class PoiFilterDbHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "poi_filters";
private static final int DATABASE_VERSION = 1;
private static final String FILTER_NAME = "poi_filters";
private static final String FILTER_COL_NAME = "name";
private static final String FILTER_COL_ID = "id";
private static final String FILTER_COL_FILTERBYNAME = "filterbyname";
private static final String FILTER_TABLE_CREATE = "CREATE TABLE " + FILTER_NAME + " (" +
FILTER_COL_NAME + ", " + FILTER_COL_ID + ", " + FILTER_COL_FILTERBYNAME + ");";
private static final String CATEGORIES_NAME = "categories";
private static final String CATEGORIES_FILTER_ID = "filter_id";
private static final String CATEGORIES_COL_CATEGORY = "category";
private static final String CATEGORIES_COL_SUBCATEGORY = "subcategory";
private static final String CATEGORIES_TABLE_CREATE = "CREATE TABLE " + CATEGORIES_NAME + " (" +
CATEGORIES_FILTER_ID + ", " + CATEGORIES_COL_CATEGORY + ", " + CATEGORIES_COL_SUBCATEGORY + ");";
PoiFilterDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(FILTER_TABLE_CREATE);
db.execSQL(CATEGORIES_TABLE_CREATE);
List<PoiFilter> filters = getUserDefinedDefaultFilters();
for(PoiFilter f : filters){
addFilter(f, db,false);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public boolean addFilter(PoiFilter p, SQLiteDatabase db, boolean addOnlyCategories){
if(db != null){
if(!addOnlyCategories){
db.execSQL("INSERT INTO " + FILTER_NAME + " VALUES (?, ?, ?)",new Object[]{p.getName(), p.getFilterId(), p.getFilterByName()});
}
Map<AmenityType, List<String>> types = p.getAcceptedTypes();
for(AmenityType a : types.keySet()){
if(types.get(a) == null){
db.execSQL("INSERT INTO " + CATEGORIES_NAME + " VALUES (?, ?, ?)",
new Object[]{p.getFilterId(), AmenityType.valueToString(a), null});
} else {
for(String s : types.get(a)){
db.execSQL("INSERT INTO " + CATEGORIES_NAME + " VALUES (?, ?, ?)",
new Object[]{p.getFilterId(), AmenityType.valueToString(a), s});
}
}
}
return true;
}
return false;
}
public List<PoiFilter> getFilters(){
SQLiteDatabase db = getReadableDatabase();
ArrayList<PoiFilter> list = new ArrayList<PoiFilter>();
if(db != null){
Cursor query = db.rawQuery("SELECT " + CATEGORIES_FILTER_ID +", " + CATEGORIES_COL_CATEGORY +"," + CATEGORIES_COL_SUBCATEGORY +" FROM " +
CATEGORIES_NAME, null);
Map<String, Map<AmenityType, List<String>>> map = new LinkedHashMap<String, Map<AmenityType,List<String>>>();
if(query.moveToFirst()){
do {
String filterId = query.getString(0);
if(!map.containsKey(filterId)){
map.put(filterId, new LinkedHashMap<AmenityType, List<String>>());
}
Map<AmenityType, List<String>> m = map.get(filterId);
AmenityType a = AmenityType.fromString(query.getString(1));
String subCategory = query.getString(2);
if(subCategory == null){
m.put(a, null);
} else {
if(m.get(a) == null){
m.put(a, new ArrayList<String>());
}
m.get(a).add(subCategory);
}
} while(query.moveToNext());
}
query.close();
query = db.rawQuery("SELECT " + FILTER_COL_ID +", " + FILTER_COL_NAME +"," + FILTER_COL_FILTERBYNAME +" FROM " +
FILTER_NAME, null);
if(query.moveToFirst()){
do {
String filterId = query.getString(0);
if(map.containsKey(filterId)){
PoiFilter filter = new PoiFilter(query.getString(1), filterId, map.get(filterId));
filter.setFilterByName(query.getString(2));
list.add(filter);
}
} while(query.moveToNext());
}
query.close();
}
return list;
}
public boolean editFilter(PoiFilter filter) {
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
db.execSQL("DELETE FROM " + CATEGORIES_NAME + " WHERE " + CATEGORIES_FILTER_ID + " = ?",
new Object[] { filter.getFilterId() });
addFilter(filter, db, true);
db.execSQL("UPDATE " + FILTER_NAME + " SET " + FILTER_COL_FILTERBYNAME + " = ?, " + FILTER_COL_NAME + " = ? " + " WHERE "
+ FILTER_COL_ID + "= ?", new Object[] { filter.getFilterByName(), filter.getName(), filter.getFilterId() });
return true;
}
return false;
}
public boolean deleteFilter(PoiFilter p){
SQLiteDatabase db = getWritableDatabase();
if(db != null){
db.execSQL("DELETE FROM " + FILTER_NAME + " WHERE " +FILTER_COL_ID + " = ?",new Object[]{p.getFilterId()});
db.execSQL("DELETE FROM " + CATEGORIES_NAME + " WHERE " +CATEGORIES_FILTER_ID + " = ?", new Object[]{p.getFilterId()});
return true;
}
return false;
}
}
}

View file

@ -40,7 +40,7 @@ public class RegionAddressRepository {
private boolean useEnglishNames = false;
public void initialize(final IProgress progress, File file) {
public boolean initialize(final IProgress progress, File file) {
long start = System.currentTimeMillis();
if(db != null){
// close previous db
@ -48,9 +48,14 @@ public class RegionAddressRepository {
}
db = SQLiteDatabase.openOrCreateDatabase(file, null);
name = file.getName().substring(0, file.getName().indexOf('.'));
if(db.getVersion() != IndexConstants.ADDRESS_TABLE_VERSION){
return false;
}
if (log.isDebugEnabled()) {
log.debug("Initializing address db " + file.getAbsolutePath() + " " + (System.currentTimeMillis() - start) + "ms");
}
return true;
}
public void close(){

View file

@ -174,35 +174,47 @@ public class ResourceManager {
////////////////////////////////////////////// Working with indexes ////////////////////////////////////////////////
// POI INDEX //
public void indexingPoi(final IProgress progress) {
public List<String> indexingPoi(final IProgress progress) {
File file = new File(Environment.getExternalStorageDirectory(), POI_PATH);
List<String> warnings = new ArrayList<String>();
closeAmenities();
if (file.exists() && file.canRead()) {
for (File f : file.listFiles()) {
if (f.getName().endsWith(IndexConstants.POI_INDEX_EXT)) {
AmenityIndexRepository repository = new AmenityIndexRepository();
progress.startTask("Indexing poi " + f.getName(), -1);
repository.initialize(progress, f);
amenityRepositories.add(repository);
boolean initialized = repository.initialize(progress, f);
if (initialized) {
amenityRepositories.add(repository);
}else {
warnings.add("The version of index '" + f.getName() +"'is not supported");
}
}
}
}
return warnings;
}
public void indexingAddresses(final IProgress progress){
public List<String> indexingAddresses(final IProgress progress){
File file = new File(Environment.getExternalStorageDirectory(), ADDRESS_PATH);
List<String> warnings = new ArrayList<String>();
closeAddresses();
if (file.exists() && file.canRead()) {
for (File f : file.listFiles()) {
if (f.getName().endsWith(IndexConstants.ADDRESS_INDEX_EXT)) {
RegionAddressRepository repository = new RegionAddressRepository();
progress.startTask("Indexing address" + f.getName(), -1);
repository.initialize(progress, f);
addressMap.put(repository.getName(), repository);
boolean initialized = repository.initialize(progress, f);
if (initialized) {
addressMap.put(repository.getName(), repository);
} else {
warnings.add("The version of index '" + f.getName() +"'is not supported");
}
}
}
}
return warnings;
}
// //////////////////////////////////////////// Working with amenities ////////////////////////////////////////////////

View file

@ -6,6 +6,8 @@ import java.io.File;
import java.io.FileWriter;
import java.io.PrintStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
@ -24,6 +26,7 @@ import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.osmand.LogUtil;
import com.osmand.ProgressDialogImplementation;
@ -57,8 +60,10 @@ public class MainMenuActivity extends Activity {
@Override
public void run() {
try {
ResourceManager.getResourceManager().indexingPoi(impl);
ResourceManager.getResourceManager().indexingAddresses(impl);
List<String> warnings = new ArrayList<String>();
warnings.addAll(ResourceManager.getResourceManager().indexingPoi(impl));
warnings.addAll(ResourceManager.getResourceManager().indexingAddresses(impl));
showWarnings(warnings);
} finally {
dlg.dismiss();
}
@ -66,6 +71,7 @@ public class MainMenuActivity extends Activity {
});
impl.run();
applicationAlreadyStarted = true;
Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler());
long size = getPreferences(MODE_WORLD_READABLE).getLong(EXCEPTION_FILE_SIZE, 0);
@ -156,6 +162,28 @@ public class MainMenuActivity extends Activity {
startApplication();
}
protected void showWarnings(List<String> warnings) {
if (!warnings.isEmpty()) {
final StringBuilder b = new StringBuilder();
boolean f = true;
for (String w : warnings) {
if(f){
f = false;
} else {
b.append('\n');
}
b.append(w);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainMenuActivity.this, b.toString(), Toast.LENGTH_LONG).show();
}
});
}
}
protected void finishApplication(){
mNotificationManager.cancel(APP_NOTIFICATION_ID);
ResourceManager.getResourceManager().close();

View file

@ -3,6 +3,7 @@
*/
package com.osmand.activities.search;
import java.util.ArrayList;
import java.util.List;
import android.app.ListActivity;
@ -63,15 +64,13 @@ public class SearchPOIActivity extends ListActivity {
Bundle bundle = this.getIntent().getExtras();
String filterId = bundle.getString(AMENITY_FILTER);
lastKnownMapLocation = OsmandSettings.getLastKnownMapLocation(this);
filter = PoiFiltersHelper.getFilterById(this, filterId);
if (filter != null) {
amenityAdapter = new AmenityAdapter(filter.initializeNewSearch(lastKnownMapLocation.getLatitude(), lastKnownMapLocation
.getLongitude(), 40));
amenityAdapter = new AmenityAdapter(new ArrayList<Amenity>());
setListAdapter(amenityAdapter);
searchArea.setText(filter.getSearchArea());
}
// ListActivity has a ListView, which you can get with:
ListView lv = getListView();
@ -89,6 +88,19 @@ public class SearchPOIActivity extends ListActivity {
}
});
}
@Override
protected void onResume() {
super.onResume();
// TODO think where this code should be placed (onCreate() - save last search results or onResume() - search time)
lastKnownMapLocation = OsmandSettings.getLastKnownMapLocation(this);
if (filter != null) {
amenityAdapter.setNewModel(filter.initializeNewSearch(lastKnownMapLocation.getLatitude(),
lastKnownMapLocation.getLongitude(), 40));
searchPOILevel.setEnabled(filter.isSearchFurtherAvailable());
searchArea.setText(filter.getSearchArea());
}
}