From c02a7820fa41f1d5cc30f0e52015cd33be9a41ba Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Fri, 8 May 2020 11:29:36 +0300 Subject: [PATCH 1/5] custom poi types cache db --- .../main/java/net/osmand/osm/MapPoiTypes.java | 13 +- .../src/net/osmand/plus/AppInitializer.java | 15 +- .../net/osmand/plus/OsmandApplication.java | 5 + .../download/ui/LocalIndexesFragment.java | 1 + OsmAnd/src/net/osmand/plus/poi/PoiHelper.java | 303 ++++++++++++++++++ .../plus/resources/ResourceManager.java | 1 + .../search/QuickSearchCustomPoiFragment.java | 8 + 7 files changed, 328 insertions(+), 18 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/poi/PoiHelper.java diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java b/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java index 6635c77936..ef2e05d851 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java @@ -33,6 +33,7 @@ public class MapPoiTypes { private static final Log log = PlatformUtil.getLog(MapRenderingTypes.class); private String resourceName; private List categories = new ArrayList(); + private List createdCategories = new ArrayList(); private PoiCategory otherCategory; private PoiCategory otherMapCategory; @@ -299,6 +300,7 @@ public class MapPoiTypes { lastCategory.setTopVisible(true); } categories.add(lastCategory); + createdCategories.add(lastCategory); return lastCategory; } return otherCategory; @@ -919,10 +921,11 @@ public class MapPoiTypes { } } + public List getCreatedCategories() { + return createdCategories; + } - - - - - + public void clearCreatedCategories(){ + createdCategories.clear(); + } } diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 6159afb6f5..b4e108db79 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -21,7 +21,6 @@ import net.osmand.IProgress; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.aidl.OsmandAidlApi; -import net.osmand.binary.BinaryMapIndexReader; import net.osmand.map.OsmandRegions; import net.osmand.map.OsmandRegions.RegionTranslation; import net.osmand.map.WorldRegion; @@ -43,6 +42,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.poi.PoiFiltersHelper; +import net.osmand.plus.poi.PoiHelper; import net.osmand.plus.quickaction.QuickActionRegistry; import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.NativeOsmandLibrary; @@ -482,17 +482,6 @@ public class AppInitializer implements IProgress { }); } - private void readPoiTypesFromMap() { - final BinaryMapIndexReader[] currentFile = app.resourceManager.getPoiSearchFiles(); - for (BinaryMapIndexReader r : currentFile) { - try { - r.initCategories(); - } catch (IOException e) { - LOG.error("Error while read poi types from map " + e); - } - } - } - public void onCreateApplication() { // always update application mode to default OsmandSettings osmandSettings = app.getSettings(); @@ -550,6 +539,7 @@ public class AppInitializer implements IProgress { app.lockHelper = startupInit(new LockHelper(app), LockHelper.class); app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class); app.quickActionRegistry = startupInit(new QuickActionRegistry(app.getSettings()), QuickActionRegistry.class); + app.poiHelper = startupInit(new PoiHelper(app), PoiHelper.class); initOpeningHoursParser(); @@ -741,7 +731,6 @@ public class AppInitializer implements IProgress { initPoiTypes(); notifyEvent(InitEvents.POI_TYPES_INITIALIZED); app.resourceManager.reloadIndexesOnStart(this, warnings); - readPoiTypesFromMap(); // native depends on renderers initNativeCore(); diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index 1fa5479b2f..e09f27a57e 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -61,6 +61,7 @@ import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.poi.PoiFiltersHelper; +import net.osmand.plus.poi.PoiHelper; import net.osmand.plus.quickaction.QuickActionRegistry; import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.resources.ResourceManager; @@ -146,6 +147,7 @@ public class OsmandApplication extends MultiDexApplication { SettingsHelper settingsHelper; GpxDbHelper gpxDbHelper; QuickActionRegistry quickActionRegistry; + PoiHelper poiHelper; private Resources localizedResources; @@ -331,6 +333,9 @@ public class OsmandApplication extends MultiDexApplication { return poiFilters; } + public PoiHelper getPoiHelper() { + return poiHelper; + } public GpxSelectionHelper getSelectedGpxHelper() { return selectedGpxHelper; diff --git a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java index cffef21b6e..d76ca7dc12 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java @@ -632,6 +632,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement } else { a.newDownloadIndexes(); } + getMyApplication().getPoiHelper().readPoiTypesFromMapAsync(); } } diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java new file mode 100644 index 0000000000..7917cb16bc --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java @@ -0,0 +1,303 @@ +package net.osmand.plus.poi; + + +import android.annotation.SuppressLint; +import android.os.AsyncTask; + +import androidx.annotation.NonNull; + +import net.osmand.PlatformUtil; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.osm.MapPoiTypes; +import net.osmand.osm.PoiCategory; +import net.osmand.osm.PoiType; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.activities.LocalIndexHelper; +import net.osmand.plus.activities.LocalIndexInfo; +import net.osmand.plus.api.SQLiteAPI; +import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; + +import org.apache.commons.logging.Log; +import org.json.JSONArray; +import org.json.JSONException; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PoiHelper { + + private static final Log LOG = PlatformUtil.getLog(PoiHelper.class); + private OsmandApplication app; + private PoiDbHelper helper; + private Map files; + private Map> categories; + + public PoiHelper(OsmandApplication app) { + this.app = app; + helper = new PoiDbHelper(app); + } + + public Map getFiles() { + if (files == null) { + files = new HashMap<>(); + files = helper.getFiles(helper.getReadableDatabase()); + helper.close(); + } + return files; + } + + public Map> getCategories() { + if (categories == null) { + categories = new HashMap<>(); + categories = helper.getCategories(helper.getReadableDatabase()); + helper.close(); + } + return categories; + } + + public void readPoiTypesFromMap() { + LocalIndexHelper localIndexHelper = new LocalIndexHelper(app); + List localMapsIndexes = localIndexHelper.getLocalFullMaps(new AbstractLoadLocalIndexTask() { + @Override + public void loadFile(LocalIndexInfo... loaded) { + } + }); + Map savedFiles = getFiles(); + if (savedFiles.size() == localMapsIndexes.size()) { + for (LocalIndexInfo info : localMapsIndexes) { + File f = new File(info.getPathToData()); + String name = f.getName(); + long date = f.lastModified(); + if (!savedFiles.containsKey(name) || savedFiles.get(name) != date) { + initCategoriesFromFiles(); + replaceSavedFiles(localMapsIndexes); + return; + } + } + } else { + initCategoriesFromFiles(); + replaceSavedFiles(localMapsIndexes); + return; + } + readCategoriesFromDb(); + } + + @SuppressLint("StaticFieldLeak") + public void readPoiTypesFromMapAsync() { + new AsyncTask() { + + @Override + protected Void doInBackground(Void... voids) { + app.getPoiTypes().init(); + readPoiTypesFromMap(); + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + private void readCategoriesFromDb() { + for (Map.Entry> entry : getCategories().entrySet()) { + PoiCategory poiCategory = app.getPoiTypes().getPoiCategoryByName(entry.getKey(), true); + for (String s : entry.getValue()) { + PoiType poiType = new PoiType(MapPoiTypes.getDefault(), poiCategory, null, s); + List filters = new ArrayList<>(); + for (PoiType poi : poiCategory.getPoiTypes()) { + filters.add(poi.getKeyName()); + } + if (!filters.contains(s)) { + poiCategory.getPoiTypes().add(poiType); + } + } + } + } + + private void replaceSavedFiles(List localMapsIndexes) { + helper.deleteFilesTable(helper.getWritableDatabase()); + for (LocalIndexInfo info : localMapsIndexes) { + File f = new File(info.getPathToData()); + helper.addFile(f, helper.getWritableDatabase()); + } + } + + private void initCategoriesFromFiles() { + app.getPoiTypes().clearCreatedCategories(); + final BinaryMapIndexReader[] currentFile = app.getResourceManager().getPoiSearchFiles(); + for (BinaryMapIndexReader r : currentFile) { + try { + r.initCategories(); + } catch (IOException e) { + LOG.error("Error while read poi types from map " + e); + } + } + replaceSavedCategories(app.getPoiTypes().getCreatedCategories()); + } + + private void replaceSavedCategories(List poiCategories) { + helper.deletePoiTypesTable(helper.getWritableDatabase()); + for (PoiCategory category : poiCategories) { + helper.addCategory(category, helper.getWritableDatabase()); + } + } + + public class PoiDbHelper { + + private static final String DATABASE_NAME = "poi_types_cache"; + private static final int DATABASE_VERSION = 1; + + private static final String FILES_TABLE_NAME = "files"; + private static final String FILE_NAME = "name"; + private static final String FILE_DATE = "date"; + + private static final String FILES_TABLE_CREATE = "CREATE TABLE " + + FILES_TABLE_NAME + " (" + + FILE_NAME + ", " + + FILE_DATE + ");"; + + private static final String POI_TYPES_TABLE_NAME = "poi_types"; + private static final String POI_CATEGORY = "category"; + private static final String POI_SUBCATEGORIES = "subcategories"; + + private static final String POI_TYPES_TABLE_CREATE = "CREATE TABLE " + + POI_TYPES_TABLE_NAME + " (" + + POI_CATEGORY + ", " + + POI_SUBCATEGORIES + ");"; + + private OsmandApplication context; + private SQLiteAPI.SQLiteConnection conn; + + PoiDbHelper(OsmandApplication context) { + this.context = context; + } + + public SQLiteAPI.SQLiteConnection getWritableDatabase() { + return openConnection(false); + } + + public void close() { + if (conn != null) { + conn.close(); + conn = null; + } + } + + public SQLiteAPI.SQLiteConnection getReadableDatabase() { + return openConnection(true); + } + + private SQLiteAPI.SQLiteConnection openConnection(boolean readonly) { + conn = context.getSQLiteAPI().getOrCreateDatabase(DATABASE_NAME, readonly); + if (conn.getVersion() < DATABASE_VERSION) { + if (readonly) { + conn.close(); + conn = context.getSQLiteAPI().getOrCreateDatabase(DATABASE_NAME, false); + } + int version = conn.getVersion(); + conn.setVersion(DATABASE_VERSION); + if (version == 0) { + onCreate(conn); + } + } + return conn; + } + + public void onCreate(SQLiteAPI.SQLiteConnection conn) { + conn.execSQL(FILES_TABLE_CREATE); + conn.execSQL(POI_TYPES_TABLE_CREATE); + } + + protected void addFile(File f, SQLiteAPI.SQLiteConnection db) { + if (db != null) { + db.execSQL("INSERT INTO " + FILES_TABLE_NAME + " VALUES (?, ?)", + new Object[]{f.getName(), f.lastModified()}); + } + } + + protected void deleteFilesTable(SQLiteAPI.SQLiteConnection db) { + if (db != null) { + db.execSQL("DELETE FROM " + FILES_TABLE_NAME); + } + } + + protected void deletePoiTypesTable(SQLiteAPI.SQLiteConnection db) { + if (db != null) { + db.execSQL("DELETE FROM " + POI_TYPES_TABLE_NAME); + } + } + + protected void addCategory(PoiCategory poiCategory, SQLiteAPI.SQLiteConnection db) { + if (db != null) { + db.execSQL("INSERT INTO " + POI_TYPES_TABLE_NAME + " VALUES (?, ?)", + new Object[]{poiCategory.getKeyName(), getSubCategoriesJson(poiCategory.getPoiTypes())}); + } + } + + protected Map getFiles(SQLiteAPI.SQLiteConnection conn) { + Map files = new HashMap<>(); + if (conn != null) { + SQLiteAPI.SQLiteCursor query = conn.rawQuery("SELECT " + + FILE_NAME + ", " + + FILE_DATE + + " FROM " + + FILES_TABLE_NAME, null); + if (query != null && query.moveToFirst()) { + do { + String fileName = query.getString(0); + Long date = query.getLong(1); + files.put(fileName, date); + } while (query.moveToNext()); + } + if (query != null) { + query.close(); + } + } + return files; + } + + protected Map> getCategories(SQLiteAPI.SQLiteConnection conn) { + Map> categories = new HashMap<>(); + if (conn != null) { + SQLiteAPI.SQLiteCursor query = conn.rawQuery("SELECT " + + POI_CATEGORY + ", " + + POI_SUBCATEGORIES + + " FROM " + + POI_TYPES_TABLE_NAME, null); + if (query != null && query.moveToFirst()) { + do { + String categoryName = query.getString(0); + List subCategories = getSubCategories(query.getString(1)); + categories.put(categoryName, subCategories); + } while (query.moveToNext()); + } + if (query != null) { + query.close(); + } + } + return categories; + } + + private List getSubCategories(@NonNull String json) { + List subCategories = new ArrayList<>(); + try { + JSONArray jsonArray = new JSONArray(json); + for (int i = 0; i < jsonArray.length(); i++) { + subCategories.add(jsonArray.optString(i)); + } + } catch (JSONException e) { + LOG.error("Error parsing subCategories json: " + e); + } + return subCategories; + } + + private String getSubCategoriesJson(@NonNull List poiTypes) { + JSONArray jsonArray = new JSONArray(); + for (PoiType subCategory : poiTypes) { + jsonArray.put(subCategory.getKeyName()); + } + return jsonArray.toString(); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index 1a4be8a631..bb442aa337 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -757,6 +757,7 @@ public class ResourceManager { for (ResourceListener l : resourceListeners) { l.onMapsIndexed(); } + context.getPoiHelper().readPoiTypesFromMap(); return warnings; } diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchCustomPoiFragment.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchCustomPoiFragment.java index 9bac75a198..4bdfcf9642 100644 --- a/OsmAnd/src/net/osmand/plus/search/QuickSearchCustomPoiFragment.java +++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchCustomPoiFragment.java @@ -43,6 +43,8 @@ import net.osmand.plus.render.RenderingIcons; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -90,6 +92,12 @@ public class QuickSearchCustomPoiFragment extends DialogFragment { this.nightMode = app.getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_DARK_THEME; setStyle(STYLE_NO_FRAME, nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme); poiCategoryList = app.getPoiTypes().getCategories(false); + Collections.sort(poiCategoryList, new Comparator() { + @Override + public int compare(PoiCategory poiCategory, PoiCategory t1) { + return poiCategory.getTranslation().compareTo(t1.getTranslation()); + } + }); } @Override From bb6980ff2db59b24dde5795532292b1cd57b6ae7 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Tue, 12 May 2020 16:16:43 +0300 Subject: [PATCH 2/5] corrections --- OsmAnd/src/net/osmand/plus/poi/PoiHelper.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java index 7917cb16bc..1aa368b6c1 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java @@ -43,18 +43,14 @@ public class PoiHelper { public Map getFiles() { if (files == null) { - files = new HashMap<>(); - files = helper.getFiles(helper.getReadableDatabase()); - helper.close(); + files = helper.getFiles(); } return files; } public Map> getCategories() { if (categories == null) { - categories = new HashMap<>(); - categories = helper.getCategories(helper.getReadableDatabase()); - helper.close(); + categories = helper.getCategories(); } return categories; } @@ -235,8 +231,9 @@ public class PoiHelper { } } - protected Map getFiles(SQLiteAPI.SQLiteConnection conn) { + protected Map getFiles() { Map files = new HashMap<>(); + SQLiteAPI.SQLiteConnection conn = getReadableDatabase(); if (conn != null) { SQLiteAPI.SQLiteCursor query = conn.rawQuery("SELECT " + FILE_NAME + ", " + @@ -254,11 +251,13 @@ public class PoiHelper { query.close(); } } + close(); return files; } - protected Map> getCategories(SQLiteAPI.SQLiteConnection conn) { + protected Map> getCategories() { Map> categories = new HashMap<>(); + SQLiteAPI.SQLiteConnection conn = getReadableDatabase(); if (conn != null) { SQLiteAPI.SQLiteCursor query = conn.rawQuery("SELECT " + POI_CATEGORY + ", " + @@ -276,6 +275,7 @@ public class PoiHelper { query.close(); } } + close(); return categories; } From 165d1430e3e081d8b76c6a34bab6428647836861 Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Tue, 12 May 2020 17:39:03 +0300 Subject: [PATCH 3/5] refactor PoiHelper --- OsmAnd/src/net/osmand/plus/poi/PoiHelper.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java index 1aa368b6c1..9934d41ff8 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java @@ -112,11 +112,14 @@ public class PoiHelper { } private void replaceSavedFiles(List localMapsIndexes) { - helper.deleteFilesTable(helper.getWritableDatabase()); + files.clear(); + helper.deleteFilesTable(); for (LocalIndexInfo info : localMapsIndexes) { File f = new File(info.getPathToData()); - helper.addFile(f, helper.getWritableDatabase()); + helper.addFile(f); + files.put(f.getName(), f.lastModified()); } + helper.close(); } private void initCategoriesFromFiles() { @@ -133,10 +136,21 @@ public class PoiHelper { } private void replaceSavedCategories(List poiCategories) { - helper.deletePoiTypesTable(helper.getWritableDatabase()); + categories.clear(); + helper.deletePoiTypesTable(); for (PoiCategory category : poiCategories) { - helper.addCategory(category, helper.getWritableDatabase()); + helper.addCategory(category); + categories.put(category.getKeyName(), getSubCategoriesFilters(category.getPoiTypes())); } + helper.close(); + } + + private List getSubCategoriesFilters(List poiTypeList) { + List filters = new ArrayList<>(); + for (PoiType poiType : poiTypeList) { + filters.add(poiType.getKeyName()); + } + return filters; } public class PoiDbHelper { @@ -205,26 +219,30 @@ public class PoiHelper { conn.execSQL(POI_TYPES_TABLE_CREATE); } - protected void addFile(File f, SQLiteAPI.SQLiteConnection db) { + protected void addFile(File f) { + SQLiteAPI.SQLiteConnection db = getReadableDatabase(); if (db != null) { db.execSQL("INSERT INTO " + FILES_TABLE_NAME + " VALUES (?, ?)", new Object[]{f.getName(), f.lastModified()}); } } - protected void deleteFilesTable(SQLiteAPI.SQLiteConnection db) { + protected void deleteFilesTable() { + SQLiteAPI.SQLiteConnection db = getReadableDatabase(); if (db != null) { db.execSQL("DELETE FROM " + FILES_TABLE_NAME); } } - protected void deletePoiTypesTable(SQLiteAPI.SQLiteConnection db) { + protected void deletePoiTypesTable() { + SQLiteAPI.SQLiteConnection db = getReadableDatabase(); if (db != null) { db.execSQL("DELETE FROM " + POI_TYPES_TABLE_NAME); } } - protected void addCategory(PoiCategory poiCategory, SQLiteAPI.SQLiteConnection db) { + protected void addCategory(PoiCategory poiCategory) { + SQLiteAPI.SQLiteConnection db = getReadableDatabase(); if (db != null) { db.execSQL("INSERT INTO " + POI_TYPES_TABLE_NAME + " VALUES (?, ?)", new Object[]{poiCategory.getKeyName(), getSubCategoriesJson(poiCategory.getPoiTypes())}); From 3a800d252053003f3f408d8b60319194fe31788a Mon Sep 17 00:00:00 2001 From: veliymolfar Date: Mon, 18 May 2020 11:24:41 +0300 Subject: [PATCH 4/5] refactor poi cache db --- .../osmand/binary/BinaryMapIndexReader.java | 2 +- .../binary/BinaryMapPoiReaderAdapter.java | 12 +- .../main/java/net/osmand/osm/MapPoiTypes.java | 10 - .../main/java/net/osmand/osm/PoiFilter.java | 9 +- .../src/net/osmand/plus/AppInitializer.java | 2 - .../net/osmand/plus/OsmandApplication.java | 6 - .../download/ui/LocalIndexesFragment.java | 1 - .../net/osmand/plus/poi/PoiFiltersHelper.java | 141 +++++++- OsmAnd/src/net/osmand/plus/poi/PoiHelper.java | 321 ------------------ .../AmenityIndexRepositoryBinary.java | 55 ++- .../plus/resources/ResourceManager.java | 34 +- 11 files changed, 221 insertions(+), 372 deletions(-) delete mode 100644 OsmAnd/src/net/osmand/plus/poi/PoiHelper.java diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java index 33553bc779..c7f2d9d095 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapIndexReader.java @@ -1421,7 +1421,7 @@ public class BinaryMapIndexReader { return addressIndexes; } - protected List getPoiIndexes() { + public List getPoiIndexes() { return poiIndexes; } diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java index a004d013dc..aa51de0c4b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -229,17 +229,7 @@ public class BinaryMapPoiReaderAdapter { region.subcategories.add(new ArrayList()); break; case OsmandOdb.OsmAndCategoryTable.SUBCATEGORIES_FIELD_NUMBER: - String subCat = codedIS.readString().intern(); - PoiCategory lastCat = poiTypes.getPoiCategoryByName(region.categories.get(region.categories.size() - 1)); - PoiType poiType = new PoiType(MapPoiTypes.getDefault(), lastCat, null, subCat); - List filters = new ArrayList<>(); - for (PoiType poi : lastCat.getPoiTypes()) { - filters.add(poi.getKeyName()); - } - if (!filters.contains(subCat)) { - lastCat.getPoiTypes().add(poiType); - } - region.subcategories.get(region.subcategories.size() - 1).add(subCat); + region.subcategories.get(region.subcategories.size() - 1).add(codedIS.readString().intern()); break; default: skipUnknownField(t); diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java b/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java index ef2e05d851..00f254c816 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/MapPoiTypes.java @@ -33,7 +33,6 @@ public class MapPoiTypes { private static final Log log = PlatformUtil.getLog(MapRenderingTypes.class); private String resourceName; private List categories = new ArrayList(); - private List createdCategories = new ArrayList(); private PoiCategory otherCategory; private PoiCategory otherMapCategory; @@ -300,7 +299,6 @@ public class MapPoiTypes { lastCategory.setTopVisible(true); } categories.add(lastCategory); - createdCategories.add(lastCategory); return lastCategory; } return otherCategory; @@ -920,12 +918,4 @@ public class MapPoiTypes { return pat.isText(); } } - - public List getCreatedCategories() { - return createdCategories; - } - - public void clearCreatedCategories(){ - createdCategories.clear(); - } } diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java b/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java index a4d2a79396..fbd75275b1 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java @@ -69,5 +69,12 @@ public class PoiFilter extends AbstractPoiType { public List getPoiTypes() { return poiTypes; } - + + public List getPoiTypesKeys() { + List filters = new ArrayList<>(); + for (PoiType p : poiTypes) { + filters.add(p.keyName); + } + return filters; + } } diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 4c8c1a51af..379e2e7486 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -44,7 +44,6 @@ import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.poi.PoiFiltersHelper; -import net.osmand.plus.poi.PoiHelper; import net.osmand.plus.quickaction.QuickActionRegistry; import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.NativeOsmandLibrary; @@ -547,7 +546,6 @@ public class AppInitializer implements IProgress { app.lockHelper = startupInit(new LockHelper(app), LockHelper.class); app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class); app.quickActionRegistry = startupInit(new QuickActionRegistry(app.getSettings()), QuickActionRegistry.class); - app.poiHelper = startupInit(new PoiHelper(app), PoiHelper.class); initOpeningHoursParser(); diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index a79b8bbcc3..dac859100c 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -62,7 +62,6 @@ import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.poi.PoiFiltersHelper; -import net.osmand.plus.poi.PoiHelper; import net.osmand.plus.quickaction.QuickActionRegistry; import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.resources.ResourceManager; @@ -148,7 +147,6 @@ public class OsmandApplication extends MultiDexApplication { SettingsHelper settingsHelper; GpxDbHelper gpxDbHelper; QuickActionRegistry quickActionRegistry; - PoiHelper poiHelper; private Resources localizedResources; @@ -335,10 +333,6 @@ public class OsmandApplication extends MultiDexApplication { return poiFilters; } - public PoiHelper getPoiHelper() { - return poiHelper; - } - public GpxSelectionHelper getSelectedGpxHelper() { return selectedGpxHelper; } diff --git a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java index c61b95f898..bbb0f694e9 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/LocalIndexesFragment.java @@ -632,7 +632,6 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement } else { a.newDownloadIndexes(); } - getMyApplication().getPoiHelper().readPoiTypesFromMapAsync(); } } diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java index b708b4afd6..9d8f4940d0 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiFiltersHelper.java @@ -3,7 +3,10 @@ package net.osmand.plus.poi; import android.os.Bundle; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.util.Pair; +import net.osmand.PlatformUtil; import net.osmand.osm.AbstractPoiType; import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; @@ -12,12 +15,18 @@ import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; +import net.osmand.plus.api.SQLiteAPI; import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; import net.osmand.plus.api.SQLiteAPI.SQLiteStatement; import net.osmand.plus.wikipedia.WikipediaPoiMenu; import net.osmand.util.Algorithms; +import org.apache.commons.logging.Log; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -36,6 +45,7 @@ import static net.osmand.osm.MapPoiTypes.WIKI_PLACE; public class PoiFiltersHelper { + private static final Log LOG = PlatformUtil.getLog(PoiFiltersHelper.class); private final OsmandApplication application; private NominatimPoiFilter nominatimPOIFilter; @@ -625,6 +635,33 @@ public class PoiFiltersHelper { } } + @Nullable + public Pair>> getCacheByResourceName(String fileName) { + Pair>> cache = null; + PoiFilterDbHelper helper = openDbHelper(); + if (helper != null) { + cache = helper.getCacheByResourceName(helper.getReadableDatabase(), fileName); + helper.close(); + } + return cache; + } + + public void updateCacheForResource(String fileName, long lastModified, Map> categories) { + PoiFilterDbHelper helper = openDbHelper(); + if (helper != null) { + helper.updateCacheForResource(helper.getReadableDatabase(), fileName, lastModified, categories); + helper.close(); + } + } + + public void insertCacheForResource(String fileName, long lastModified, Map> categories) { + PoiFilterDbHelper helper = openDbHelper(); + if (helper != null) { + helper.insertCacheForResource(helper.getReadableDatabase(), fileName, lastModified, categories); + helper.close(); + } + } + private void saveSelectedPoiFilters() { Set filters = new HashSet<>(); for (Set template : selectedPoiFilters.values()) { @@ -641,7 +678,7 @@ public class PoiFiltersHelper { private static final int FALSE_INT = 0; public static final String DATABASE_NAME = "poi_filters"; - private static final int DATABASE_VERSION = 6; + private static final int DATABASE_VERSION = 7; private static final String FILTER_NAME = "poi_filters"; private static final String FILTER_COL_NAME = "name"; @@ -669,6 +706,20 @@ public class PoiFiltersHelper { CATEGORIES_COL_CATEGORY + ", " + CATEGORIES_COL_SUBCATEGORY + ");"; + private static final String POI_TYPES_CACHE_NAME = "poi_types_cache"; + private static final String MAP_FILE_NAME = "map_name"; + private static final String MAP_FILE_DATE = "map_date"; + private static final String CACHED_POI_CATEGORIES = "cached_categories"; + + private static final String POI_CACHE_TABLE_CREATE = "CREATE TABLE " + + POI_TYPES_CACHE_NAME + " (" + + MAP_FILE_NAME + ", " + + MAP_FILE_DATE + ", " + + CACHED_POI_CATEGORIES + ");"; + + private static final String CATEGORY_KEY = "category"; + private static final String SUB_CATEGORIES_KEY = "sub_categories"; + private OsmandApplication context; private SQLiteConnection conn; private MapPoiTypes mapPoiTypes; @@ -714,6 +765,7 @@ public class PoiFiltersHelper { public void onCreate(SQLiteConnection conn) { conn.execSQL(FILTER_TABLE_CREATE); conn.execSQL(CATEGORIES_TABLE_CREATE); + conn.execSQL(POI_CACHE_TABLE_CREATE); } @@ -725,6 +777,9 @@ public class PoiFiltersHelper { conn.execSQL("ALTER TABLE " + FILTER_NAME + " ADD " + FILTER_COL_HISTORY + " int DEFAULT " + FALSE_INT); conn.execSQL("ALTER TABLE " + FILTER_NAME + " ADD " + FILTER_COL_DELETED + " int DEFAULT " + FALSE_INT); } + if (oldVersion < 7) { + conn.execSQL(POI_CACHE_TABLE_CREATE); + } } private void deleteOldFilters(SQLiteConnection conn) { @@ -887,5 +942,89 @@ public class PoiFiltersHelper { db.execSQL("DELETE FROM " + FILTER_NAME + " WHERE " + FILTER_COL_ID + " = ?", new Object[]{key}); db.execSQL("DELETE FROM " + CATEGORIES_NAME + " WHERE " + CATEGORIES_FILTER_ID + " = ?", new Object[]{key}); } + + @Nullable + protected Pair>> getCacheByResourceName(SQLiteConnection db, String fileName) { + Pair>> cache = null; + if (db != null) { + SQLiteAPI.SQLiteCursor query = db.rawQuery("SELECT " + + MAP_FILE_DATE + ", " + + CACHED_POI_CATEGORIES + + " FROM " + + POI_TYPES_CACHE_NAME + + " WHERE " + MAP_FILE_NAME + " = ?", new String[]{fileName}); + if (query != null && query.moveToFirst()) { + long lastModified = query.getLong(0); + Map> categories = getCategories(query.getString(1)); + cache = new Pair<>(lastModified, categories); + } + if (query != null) { + query.close(); + } + db.close(); + } + return cache; + } + + private Map> getCategories(String json) { + Map> categories = new HashMap<>(); + try { + JSONArray jsonArray = new JSONArray(json); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + String category = jsonObject.optString(CATEGORY_KEY); + List subCategories = getSubCategories(jsonObject.optString(SUB_CATEGORIES_KEY)); + categories.put(category, subCategories); + } + } catch (JSONException e) { + LOG.error("Error parsing categories: " + e); + } + return categories; + } + + protected void updateCacheForResource(SQLiteConnection db, String fileName, long lastModified, Map> categories) { + try { + db.execSQL("UPDATE " + POI_TYPES_CACHE_NAME + " SET " + + MAP_FILE_DATE + " = ?, " + + CACHED_POI_CATEGORIES + " = ? " + + "WHERE " + MAP_FILE_NAME + " = ?", + new Object[]{lastModified, getCategoriesJson(categories), fileName}); + } catch (JSONException e) { + LOG.error("Error converting category to json: " + e); + } + } + + protected void insertCacheForResource(SQLiteConnection db, String fileName, long lastModified, Map> categories) { + try { + db.execSQL("INSERT INTO " + POI_TYPES_CACHE_NAME + " VALUES(?,?,?)", + new Object[]{fileName, lastModified, getCategoriesJson(categories)}); + } catch (JSONException e) { + LOG.error("Error converting category to json: " + e); + } + } + + private String getCategoriesJson(Map> categories) throws JSONException { + JSONArray json = new JSONArray(); + for (Map.Entry> entry : categories.entrySet()) { + JSONObject jsonObject = new JSONObject(); + JSONArray subCategories = new JSONArray(); + for (String subCategory : entry.getValue()) { + subCategories.put(subCategory); + } + jsonObject.put(CATEGORY_KEY, entry.getKey()); + jsonObject.put(SUB_CATEGORIES_KEY, subCategories); + json.put(jsonObject); + } + return json.toString(); + } + + private List getSubCategories(@NonNull String json) throws JSONException { + List subCategories = new ArrayList<>(); + JSONArray jsonArray = new JSONArray(json); + for (int i = 0; i < jsonArray.length(); i++) { + subCategories.add(jsonArray.optString(i)); + } + return subCategories; + } } } diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java b/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java deleted file mode 100644 index 9934d41ff8..0000000000 --- a/OsmAnd/src/net/osmand/plus/poi/PoiHelper.java +++ /dev/null @@ -1,321 +0,0 @@ -package net.osmand.plus.poi; - - -import android.annotation.SuppressLint; -import android.os.AsyncTask; - -import androidx.annotation.NonNull; - -import net.osmand.PlatformUtil; -import net.osmand.binary.BinaryMapIndexReader; -import net.osmand.osm.MapPoiTypes; -import net.osmand.osm.PoiCategory; -import net.osmand.osm.PoiType; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.activities.LocalIndexHelper; -import net.osmand.plus.activities.LocalIndexInfo; -import net.osmand.plus.api.SQLiteAPI; -import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; - -import org.apache.commons.logging.Log; -import org.json.JSONArray; -import org.json.JSONException; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class PoiHelper { - - private static final Log LOG = PlatformUtil.getLog(PoiHelper.class); - private OsmandApplication app; - private PoiDbHelper helper; - private Map files; - private Map> categories; - - public PoiHelper(OsmandApplication app) { - this.app = app; - helper = new PoiDbHelper(app); - } - - public Map getFiles() { - if (files == null) { - files = helper.getFiles(); - } - return files; - } - - public Map> getCategories() { - if (categories == null) { - categories = helper.getCategories(); - } - return categories; - } - - public void readPoiTypesFromMap() { - LocalIndexHelper localIndexHelper = new LocalIndexHelper(app); - List localMapsIndexes = localIndexHelper.getLocalFullMaps(new AbstractLoadLocalIndexTask() { - @Override - public void loadFile(LocalIndexInfo... loaded) { - } - }); - Map savedFiles = getFiles(); - if (savedFiles.size() == localMapsIndexes.size()) { - for (LocalIndexInfo info : localMapsIndexes) { - File f = new File(info.getPathToData()); - String name = f.getName(); - long date = f.lastModified(); - if (!savedFiles.containsKey(name) || savedFiles.get(name) != date) { - initCategoriesFromFiles(); - replaceSavedFiles(localMapsIndexes); - return; - } - } - } else { - initCategoriesFromFiles(); - replaceSavedFiles(localMapsIndexes); - return; - } - readCategoriesFromDb(); - } - - @SuppressLint("StaticFieldLeak") - public void readPoiTypesFromMapAsync() { - new AsyncTask() { - - @Override - protected Void doInBackground(Void... voids) { - app.getPoiTypes().init(); - readPoiTypesFromMap(); - return null; - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - - private void readCategoriesFromDb() { - for (Map.Entry> entry : getCategories().entrySet()) { - PoiCategory poiCategory = app.getPoiTypes().getPoiCategoryByName(entry.getKey(), true); - for (String s : entry.getValue()) { - PoiType poiType = new PoiType(MapPoiTypes.getDefault(), poiCategory, null, s); - List filters = new ArrayList<>(); - for (PoiType poi : poiCategory.getPoiTypes()) { - filters.add(poi.getKeyName()); - } - if (!filters.contains(s)) { - poiCategory.getPoiTypes().add(poiType); - } - } - } - } - - private void replaceSavedFiles(List localMapsIndexes) { - files.clear(); - helper.deleteFilesTable(); - for (LocalIndexInfo info : localMapsIndexes) { - File f = new File(info.getPathToData()); - helper.addFile(f); - files.put(f.getName(), f.lastModified()); - } - helper.close(); - } - - private void initCategoriesFromFiles() { - app.getPoiTypes().clearCreatedCategories(); - final BinaryMapIndexReader[] currentFile = app.getResourceManager().getPoiSearchFiles(); - for (BinaryMapIndexReader r : currentFile) { - try { - r.initCategories(); - } catch (IOException e) { - LOG.error("Error while read poi types from map " + e); - } - } - replaceSavedCategories(app.getPoiTypes().getCreatedCategories()); - } - - private void replaceSavedCategories(List poiCategories) { - categories.clear(); - helper.deletePoiTypesTable(); - for (PoiCategory category : poiCategories) { - helper.addCategory(category); - categories.put(category.getKeyName(), getSubCategoriesFilters(category.getPoiTypes())); - } - helper.close(); - } - - private List getSubCategoriesFilters(List poiTypeList) { - List filters = new ArrayList<>(); - for (PoiType poiType : poiTypeList) { - filters.add(poiType.getKeyName()); - } - return filters; - } - - public class PoiDbHelper { - - private static final String DATABASE_NAME = "poi_types_cache"; - private static final int DATABASE_VERSION = 1; - - private static final String FILES_TABLE_NAME = "files"; - private static final String FILE_NAME = "name"; - private static final String FILE_DATE = "date"; - - private static final String FILES_TABLE_CREATE = "CREATE TABLE " + - FILES_TABLE_NAME + " (" + - FILE_NAME + ", " + - FILE_DATE + ");"; - - private static final String POI_TYPES_TABLE_NAME = "poi_types"; - private static final String POI_CATEGORY = "category"; - private static final String POI_SUBCATEGORIES = "subcategories"; - - private static final String POI_TYPES_TABLE_CREATE = "CREATE TABLE " + - POI_TYPES_TABLE_NAME + " (" + - POI_CATEGORY + ", " + - POI_SUBCATEGORIES + ");"; - - private OsmandApplication context; - private SQLiteAPI.SQLiteConnection conn; - - PoiDbHelper(OsmandApplication context) { - this.context = context; - } - - public SQLiteAPI.SQLiteConnection getWritableDatabase() { - return openConnection(false); - } - - public void close() { - if (conn != null) { - conn.close(); - conn = null; - } - } - - public SQLiteAPI.SQLiteConnection getReadableDatabase() { - return openConnection(true); - } - - private SQLiteAPI.SQLiteConnection openConnection(boolean readonly) { - conn = context.getSQLiteAPI().getOrCreateDatabase(DATABASE_NAME, readonly); - if (conn.getVersion() < DATABASE_VERSION) { - if (readonly) { - conn.close(); - conn = context.getSQLiteAPI().getOrCreateDatabase(DATABASE_NAME, false); - } - int version = conn.getVersion(); - conn.setVersion(DATABASE_VERSION); - if (version == 0) { - onCreate(conn); - } - } - return conn; - } - - public void onCreate(SQLiteAPI.SQLiteConnection conn) { - conn.execSQL(FILES_TABLE_CREATE); - conn.execSQL(POI_TYPES_TABLE_CREATE); - } - - protected void addFile(File f) { - SQLiteAPI.SQLiteConnection db = getReadableDatabase(); - if (db != null) { - db.execSQL("INSERT INTO " + FILES_TABLE_NAME + " VALUES (?, ?)", - new Object[]{f.getName(), f.lastModified()}); - } - } - - protected void deleteFilesTable() { - SQLiteAPI.SQLiteConnection db = getReadableDatabase(); - if (db != null) { - db.execSQL("DELETE FROM " + FILES_TABLE_NAME); - } - } - - protected void deletePoiTypesTable() { - SQLiteAPI.SQLiteConnection db = getReadableDatabase(); - if (db != null) { - db.execSQL("DELETE FROM " + POI_TYPES_TABLE_NAME); - } - } - - protected void addCategory(PoiCategory poiCategory) { - SQLiteAPI.SQLiteConnection db = getReadableDatabase(); - if (db != null) { - db.execSQL("INSERT INTO " + POI_TYPES_TABLE_NAME + " VALUES (?, ?)", - new Object[]{poiCategory.getKeyName(), getSubCategoriesJson(poiCategory.getPoiTypes())}); - } - } - - protected Map getFiles() { - Map files = new HashMap<>(); - SQLiteAPI.SQLiteConnection conn = getReadableDatabase(); - if (conn != null) { - SQLiteAPI.SQLiteCursor query = conn.rawQuery("SELECT " + - FILE_NAME + ", " + - FILE_DATE + - " FROM " + - FILES_TABLE_NAME, null); - if (query != null && query.moveToFirst()) { - do { - String fileName = query.getString(0); - Long date = query.getLong(1); - files.put(fileName, date); - } while (query.moveToNext()); - } - if (query != null) { - query.close(); - } - } - close(); - return files; - } - - protected Map> getCategories() { - Map> categories = new HashMap<>(); - SQLiteAPI.SQLiteConnection conn = getReadableDatabase(); - if (conn != null) { - SQLiteAPI.SQLiteCursor query = conn.rawQuery("SELECT " + - POI_CATEGORY + ", " + - POI_SUBCATEGORIES + - " FROM " + - POI_TYPES_TABLE_NAME, null); - if (query != null && query.moveToFirst()) { - do { - String categoryName = query.getString(0); - List subCategories = getSubCategories(query.getString(1)); - categories.put(categoryName, subCategories); - } while (query.moveToNext()); - } - if (query != null) { - query.close(); - } - } - close(); - return categories; - } - - private List getSubCategories(@NonNull String json) { - List subCategories = new ArrayList<>(); - try { - JSONArray jsonArray = new JSONArray(json); - for (int i = 0; i < jsonArray.length(); i++) { - subCategories.add(jsonArray.optString(i)); - } - } catch (JSONException e) { - LOG.error("Error parsing subCategories json: " + e); - } - return subCategories; - } - - private String getSubCategoriesJson(@NonNull List poiTypes) { - JSONArray jsonArray = new JSONArray(); - for (PoiType subCategory : poiTypes) { - jsonArray.put(subCategory.getKeyName()); - } - return jsonArray.toString(); - } - } -} diff --git a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java index 4c57457588..59d60a5872 100644 --- a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java +++ b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java @@ -1,6 +1,7 @@ package net.osmand.plus.resources; import androidx.annotation.Nullable; +import androidx.core.util.Pair; import net.osmand.Location; import net.osmand.PlatformUtil; @@ -9,8 +10,12 @@ import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader.MapIndex; import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.BinaryMapPoiReaderAdapter; import net.osmand.data.Amenity; +import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.poi.PoiFiltersHelper; import net.osmand.plus.resources.ResourceManager.BinaryMapReaderResource; import net.osmand.plus.resources.ResourceManager.BinaryMapReaderResourceType; import net.osmand.util.MapUtils; @@ -18,18 +23,66 @@ import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { private final static Log log = PlatformUtil.getLog(AmenityIndexRepositoryBinary.class); private BinaryMapReaderResource resource; + private MapPoiTypes poiTypes; + private Map> poiCategories = new HashMap<>(); - public AmenityIndexRepositoryBinary(BinaryMapReaderResource resource) { + public AmenityIndexRepositoryBinary(BinaryMapReaderResource resource, OsmandApplication app) { this.resource = resource; + poiTypes = app.getPoiTypes(); + checkCachedCategories(app.getPoiFilters()); + } + + public Map> getPoiCategories() { + return poiCategories; + } + + private void checkCachedCategories(PoiFiltersHelper poiFiltersHelper) { + String fileName = resource.getFileName(); + long lastModified = resource.getFileLastModified(); + Pair>> cache = poiFiltersHelper.getCacheByResourceName(fileName); + if (cache == null || cache.first != null && cache.first != lastModified) { + try { + BinaryMapIndexReader reader = getOpenFile(); + if (reader != null) { + reader.initCategories(); + List regions = reader.getPoiIndexes(); + for (BinaryMapPoiReaderAdapter.PoiRegion region : regions) { + List categories = region.getCategories(); + List> subCategories = region.getSubcategories(); + for (int i = 0; i < categories.size(); i++) { + PoiCategory poiCategory = poiTypes.getPoiCategoryByName(categories.get(i)); + Set filters = new HashSet<>(subCategories.get(i)); + List keys = poiCategory.getPoiTypesKeys(); + filters.removeAll(keys); + if (!filters.isEmpty()) { + poiCategories.put(categories.get(i), new ArrayList<>(filters)); + } + } + } + if (cache == null) { + poiFiltersHelper.insertCacheForResource(fileName, lastModified, poiCategories); + } else { + poiFiltersHelper.updateCacheForResource(fileName, lastModified, poiCategories); + } + } + } catch (IOException e) { + log.error("Error initializing categories ", e); + } + } else if (cache.second != null) { + poiCategories = cache.second; + } } @Nullable diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index bb442aa337..47462618c4 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -32,6 +32,7 @@ import net.osmand.map.MapTileDownloader.DownloadRequest; import net.osmand.map.OsmandRegions; import net.osmand.osm.MapPoiTypes; import net.osmand.osm.PoiCategory; +import net.osmand.osm.PoiType; import net.osmand.plus.AppInitializer; import net.osmand.plus.AppInitializer.InitEvents; import net.osmand.plus.OsmandApplication; @@ -152,6 +153,10 @@ public class ResourceManager { return filename.getName(); } + public long getFileLastModified() { + return filename.lastModified(); + } + // should not use methods to read from file! @Nullable public BinaryMapIndexReader getShallowReader() { @@ -735,7 +740,7 @@ public class ResourceManager { resource.setUseForPublicTransport(true); } if (mapReader.containsPoiData()) { - amenityRepositories.put(f.getName(), new AmenityIndexRepositoryBinary(resource)); + amenityRepositories.put(f.getName(), new AmenityIndexRepositoryBinary(resource, context)); } } } catch (SQLiteException e) { @@ -746,6 +751,17 @@ public class ResourceManager { warnings.add(MessageFormat.format(context.getString(R.string.version_index_is_big_for_memory), f.getName())); } } + for (AmenityIndexRepository repo : amenityRepositories.values()) { + Map> categories = ((AmenityIndexRepositoryBinary) repo).getPoiCategories(); + if (!categories.isEmpty()) { + for (Map.Entry> entry : categories.entrySet()) { + PoiCategory poiCategory = context.getPoiTypes().getPoiCategoryByName(entry.getKey(), true); + for (String s : entry.getValue()) { + poiCategory.addPoiType(new PoiType(MapPoiTypes.getDefault(), poiCategory, null, s)); + } + } + } + } log.debug("All map files initialized " + (System.currentTimeMillis() - val) + " ms"); if (files.size() > 0 && (!indCache.exists() || indCache.canWrite())) { try { @@ -757,7 +773,6 @@ public class ResourceManager { for (ResourceListener l : resourceListeners) { l.onMapsIndexed(); } - context.getPoiHelper().readPoiTypesFromMap(); return warnings; } @@ -1123,21 +1138,6 @@ public class ResourceManager { return readers.toArray(new BinaryMapIndexReader[readers.size()]); } - public BinaryMapIndexReader[] getPoiSearchFiles() { - Collection fileReaders = getFileReaders(); - List readers = new ArrayList<>(fileReaders.size()); - for (BinaryMapReaderResource r : fileReaders) { - BinaryMapIndexReader shallowReader = r.getShallowReader(); - if (shallowReader != null && shallowReader.containsPoiData()) { - BinaryMapIndexReader reader = r.getReader(BinaryMapReaderResourceType.POI); - if (reader != null) { - readers.add(reader); - } - } - } - return readers.toArray(new BinaryMapIndexReader[readers.size()]); - } - public Map getIndexFileNames() { return new LinkedHashMap(indexFileNames); } From c906fcab5b28e7c000ad4bc0308f9e34e8d741b1 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Mon, 18 May 2020 15:20:30 +0200 Subject: [PATCH 5/5] Small refactoring --- .../main/java/net/osmand/osm/PoiFilter.java | 7 -- .../AmenityIndexRepositoryBinary.java | 79 +++++++++++-------- .../plus/resources/ResourceManager.java | 2 +- 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java b/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java index fbd75275b1..6d628e29d3 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/PoiFilter.java @@ -70,11 +70,4 @@ public class PoiFilter extends AbstractPoiType { return poiTypes; } - public List getPoiTypesKeys() { - List filters = new ArrayList<>(); - for (PoiType p : poiTypes) { - filters.add(p.keyName); - } - return filters; - } } diff --git a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java index 59d60a5872..930012f998 100644 --- a/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java +++ b/OsmAnd/src/net/osmand/plus/resources/AmenityIndexRepositoryBinary.java @@ -26,17 +26,15 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { private final static Log log = PlatformUtil.getLog(AmenityIndexRepositoryBinary.class); private BinaryMapReaderResource resource; private MapPoiTypes poiTypes; - private Map> poiCategories = new HashMap<>(); + private Map> deltaPoiCategories = new HashMap<>(); public AmenityIndexRepositoryBinary(BinaryMapReaderResource resource, OsmandApplication app) { this.resource = resource; @@ -44,8 +42,8 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { checkCachedCategories(app.getPoiFilters()); } - public Map> getPoiCategories() { - return poiCategories; + public Map> getDeltaPoiCategories() { + return deltaPoiCategories; } private void checkCachedCategories(PoiFiltersHelper poiFiltersHelper) { @@ -53,35 +51,54 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { long lastModified = resource.getFileLastModified(); Pair>> cache = poiFiltersHelper.getCacheByResourceName(fileName); if (cache == null || cache.first != null && cache.first != lastModified) { + deltaPoiCategories = new HashMap<>(); try { BinaryMapIndexReader reader = getOpenFile(); if (reader != null) { reader.initCategories(); List regions = reader.getPoiIndexes(); for (BinaryMapPoiReaderAdapter.PoiRegion region : regions) { - List categories = region.getCategories(); - List> subCategories = region.getSubcategories(); - for (int i = 0; i < categories.size(); i++) { - PoiCategory poiCategory = poiTypes.getPoiCategoryByName(categories.get(i)); - Set filters = new HashSet<>(subCategories.get(i)); - List keys = poiCategory.getPoiTypesKeys(); - filters.removeAll(keys); - if (!filters.isEmpty()) { - poiCategories.put(categories.get(i), new ArrayList<>(filters)); - } - } + calculateDeltaSubcategories(region); } if (cache == null) { - poiFiltersHelper.insertCacheForResource(fileName, lastModified, poiCategories); + poiFiltersHelper.insertCacheForResource(fileName, lastModified, deltaPoiCategories); } else { - poiFiltersHelper.updateCacheForResource(fileName, lastModified, poiCategories); + poiFiltersHelper.updateCacheForResource(fileName, lastModified, deltaPoiCategories); } } } catch (IOException e) { log.error("Error initializing categories ", e); } } else if (cache.second != null) { - poiCategories = cache.second; + deltaPoiCategories = cache.second; + } + } + + private void calculateDeltaSubcategories(BinaryMapPoiReaderAdapter.PoiRegion region) { + List categories = region.getCategories(); + List> subCategories = region.getSubcategories(); + for (int i = 0; i < categories.size(); i++) { + String categoryName = categories.get(i); + + PoiCategory poiCategory = poiTypes.getPoiCategoryByName(categoryName); + List deltaSubCategories = null; + for (List subList : subCategories) { + for (String subCategory : subList) { + if (poiCategory.getPoiTypeByKeyName(subCategory) != null) { + if (deltaSubCategories == null) { + deltaSubCategories = new ArrayList<>(); + } + deltaSubCategories.add(subCategory); + } + } + } + if (deltaSubCategories != null) { + if(deltaPoiCategories.containsKey(categoryName)) { + deltaPoiCategories.get(categoryName).addAll(deltaSubCategories); + } else { + deltaPoiCategories.put(categoryName, deltaSubCategories); + } + } } } @@ -107,8 +124,8 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { BinaryMapIndexReader reader = getOpenFile(); return reader != null && reader.containsPoiData(left31, top31, right31, bottom31); } - - + + public synchronized Map> searchAmenityCategoriesByName(String query, Map> map) { try { BinaryMapIndexReader reader = getOpenFile(); @@ -118,12 +135,12 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { } return map; } - - + + public synchronized List searchAmenitiesByName(int x, int y, int l, int t, int r, int b, String query, ResultMatcher resulMatcher) { long now = System.currentTimeMillis(); List amenities = Collections.emptyList(); - SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(x, y, query, l, r, t, b,resulMatcher); + SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(x, y, query, l, r, t, b, resulMatcher); try { BinaryMapIndexReader index = getOpenFile(); if (index != null) { @@ -143,10 +160,10 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { } return amenities; } - + @Override - public synchronized List searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, - final SearchPoiTypeFilter filter, ResultMatcher matcher) { + public synchronized List searchAmenities(int stop, int sleft, int sbottom, int sright, int zoom, + final SearchPoiTypeFilter filter, ResultMatcher matcher) { long now = System.currentTimeMillis(); SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(sleft, sright, stop, sbottom, zoom, filter, matcher); @@ -171,7 +188,7 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { long now = System.currentTimeMillis(); List result = null; SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(locations, radius, - filter, matcher ); + filter, matcher); try { BinaryMapIndexReader reader = getOpenFile(); if (reader != null) { @@ -182,10 +199,10 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository { return result; } if (log.isDebugEnabled() && result != null) { - log.debug(String.format("Search done in %s ms found %s.", (System.currentTimeMillis() - now), result.size())); //$NON-NLS-1$ + log.debug(String.format("Search done in %s ms found %s.", (System.currentTimeMillis() - now), result.size())); //$NON-NLS-1$ } return result; - + } - + } diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index 47462618c4..44a50c880c 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -752,7 +752,7 @@ public class ResourceManager { } } for (AmenityIndexRepository repo : amenityRepositories.values()) { - Map> categories = ((AmenityIndexRepositoryBinary) repo).getPoiCategories(); + Map> categories = ((AmenityIndexRepositoryBinary) repo).getDeltaPoiCategories(); if (!categories.isEmpty()) { for (Map.Entry> entry : categories.entrySet()) { PoiCategory poiCategory = context.getPoiTypes().getPoiCategoryByName(entry.getKey(), true);