Implement search by name poi categories/subcategories
This commit is contained in:
parent
89f8885aa9
commit
403c8e750a
9 changed files with 113 additions and 15 deletions
|
@ -936,9 +936,8 @@ public class BinaryMapIndexReader {
|
||||||
return req.getSearchResults();
|
return req.getSearchResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<AmenityType, List<String>> searchPoiCategoriesByName(SearchRequest<Amenity> req, Map<AmenityType, List<String>> map)
|
public Map<AmenityType, List<String>> searchPoiCategoriesByName(String query, Map<AmenityType, List<String>> map) {
|
||||||
throws IOException {
|
if (query == null || query.length() == 0) {
|
||||||
if (req.nameQuery == null || req.nameQuery.length() == 0) {
|
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
Collator collator = Collator.getInstance();
|
Collator collator = Collator.getInstance();
|
||||||
|
@ -947,12 +946,12 @@ public class BinaryMapIndexReader {
|
||||||
for(int i= 0; i< poiIndex.categories.size(); i++){
|
for(int i= 0; i< poiIndex.categories.size(); i++){
|
||||||
String cat = poiIndex.categories.get(i);
|
String cat = poiIndex.categories.get(i);
|
||||||
AmenityType catType = poiIndex.categoriesType.get(i);
|
AmenityType catType = poiIndex.categoriesType.get(i);
|
||||||
if(CollatorStringMatcher.cmatches(collator, cat, req.nameQuery, StringMatcherMode.CHECK_STARTS_FROM_SPACE)){
|
if(CollatorStringMatcher.cmatches(collator, cat, query, StringMatcherMode.CHECK_STARTS_FROM_SPACE)){
|
||||||
map.put(catType, null);
|
map.put(catType, null);
|
||||||
} else {
|
} else {
|
||||||
List<String> subcats = poiIndex.subcategories.get(i);
|
List<String> subcats = poiIndex.subcategories.get(i);
|
||||||
for(int j=0; j< subcats.size(); j++){
|
for(int j=0; j< subcats.size(); j++){
|
||||||
if(CollatorStringMatcher.cmatches(collator, subcats.get(j), req.nameQuery, StringMatcherMode.CHECK_STARTS_FROM_SPACE)){
|
if(CollatorStringMatcher.cmatches(collator, subcats.get(j), query, StringMatcherMode.CHECK_STARTS_FROM_SPACE)){
|
||||||
if(!map.containsKey(catType)){
|
if(!map.containsKey(catType)){
|
||||||
map.put(catType, new ArrayList<String>());
|
map.put(catType, new ArrayList<String>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,7 +555,6 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
|
||||||
|
|
||||||
public static void main(String[] args) throws SQLException, FileNotFoundException, IOException {
|
public static void main(String[] args) throws SQLException, FileNotFoundException, IOException {
|
||||||
// TODO support cancelling poi search request! Do it in another thread (Check is cancelled()!!!)
|
// TODO support cancelling poi search request! Do it in another thread (Check is cancelled()!!!)
|
||||||
// TODO implement UI to show matching by name subcategories
|
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
IndexPoiCreator poiCreator = new IndexPoiCreator();
|
IndexPoiCreator poiCreator = new IndexPoiCreator();
|
||||||
// String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.odb";
|
// String fileSqlte = "/home/victor/projects/OsmAnd/data/osm-gen/POI/Ru-mow.poi.odb";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<string name="poi_query_by_name_matches_categories">Some poi categories matching to the query were found :</string>
|
||||||
<string name="data_to_search_poi_not_available">Local data to search POI is not present.</string>
|
<string name="data_to_search_poi_not_available">Local data to search POI is not present.</string>
|
||||||
<string name="poi_filter_by_name">Search by name</string>
|
<string name="poi_filter_by_name">Search by name</string>
|
||||||
<string name="old_poi_file_should_be_deleted">The poi data file \'%1$s\' is deprecated and can be deleted.</string>
|
<string name="old_poi_file_should_be_deleted">The poi data file \'%1$s\' is deprecated and can be deleted.</string>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import net.osmand.Algoritms;
|
import net.osmand.Algoritms;
|
||||||
import net.osmand.LogUtil;
|
import net.osmand.LogUtil;
|
||||||
|
@ -49,6 +50,11 @@ public class AmenityIndexRepositoryBinary implements AmenityIndexRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<AmenityType, List<String>> searchAmenityCategoriesByName(String query, Map<AmenityType, List<String>> map) {
|
||||||
|
return index.searchPoiCategoriesByName(query, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<Amenity> searchAmenitiesByName(int x, int y, String query, ResultMatcher<Amenity> resulMatcher) {
|
public List<Amenity> searchAmenitiesByName(int x, int y, String query, ResultMatcher<Amenity> resulMatcher) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
List<Amenity> amenities = Collections.emptyList();
|
List<Amenity> amenities = Collections.emptyList();
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package net.osmand.plus;
|
package net.osmand.plus;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import net.osmand.OsmAndFormatter;
|
import net.osmand.OsmAndFormatter;
|
||||||
import net.osmand.ResultMatcher;
|
import net.osmand.ResultMatcher;
|
||||||
|
@ -168,6 +170,10 @@ public class PoiFilter {
|
||||||
return set.contains(subtype);
|
return set.contains(subtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearFilter(){
|
||||||
|
acceptedTypes = new LinkedHashMap<AmenityType, LinkedHashSet<String>>();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean areAllTypesAccepted(){
|
public boolean areAllTypesAccepted(){
|
||||||
if(AmenityType.values().length == acceptedTypes.size()){
|
if(AmenityType.values().length == acceptedTypes.size()){
|
||||||
for(AmenityType a : acceptedTypes.keySet()){
|
for(AmenityType a : acceptedTypes.keySet()){
|
||||||
|
@ -189,6 +195,19 @@ public class PoiFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMapToAccept(Map<AmenityType, List<String>> newMap) {
|
||||||
|
Iterator<Entry<AmenityType, List<String>>> iterator = newMap.entrySet().iterator();
|
||||||
|
acceptedTypes.clear();
|
||||||
|
while(iterator.hasNext()){
|
||||||
|
Entry<AmenityType, List<String>> e = iterator.next();
|
||||||
|
if(e.getValue() == null){
|
||||||
|
acceptedTypes.put(e.getKey(), null);
|
||||||
|
} else {
|
||||||
|
acceptedTypes.put(e.getKey(), new LinkedHashSet<String>(e.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String buildSqlWhereFilter(){
|
public String buildSqlWhereFilter(){
|
||||||
if(areAllTypesAccepted()){
|
if(areAllTypesAccepted()){
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import net.osmand.ResultMatcher;
|
||||||
import net.osmand.Version;
|
import net.osmand.Version;
|
||||||
import net.osmand.binary.BinaryMapIndexReader;
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.data.Amenity;
|
import net.osmand.data.Amenity;
|
||||||
|
import net.osmand.data.AmenityType;
|
||||||
import net.osmand.data.IndexConstants;
|
import net.osmand.data.IndexConstants;
|
||||||
import net.osmand.data.MapTileDownloader;
|
import net.osmand.data.MapTileDownloader;
|
||||||
import net.osmand.data.TransportStop;
|
import net.osmand.data.TransportStop;
|
||||||
|
@ -645,6 +646,18 @@ public class ResourceManager {
|
||||||
return amenities;
|
return amenities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<AmenityType, List<String>> searchAmenityCategoriesByName(String searchQuery, double lat, double lon) {
|
||||||
|
Map<AmenityType, List<String>> map = new LinkedHashMap<AmenityType, List<String>>();
|
||||||
|
for (AmenityIndexRepository index : amenityRepositories) {
|
||||||
|
if (index instanceof AmenityIndexRepositoryBinary) {
|
||||||
|
if (index.checkContains(lat, lon)) {
|
||||||
|
((AmenityIndexRepositoryBinary) index).searchAmenityCategoriesByName(searchQuery, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
public void searchAmenitiesAsync(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, PoiFilter filter, List<Amenity> toFill){
|
public void searchAmenitiesAsync(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, int zoom, PoiFilter filter, List<Amenity> toFill){
|
||||||
if(filter instanceof NameFinderPoiFilter){
|
if(filter instanceof NameFinderPoiFilter){
|
||||||
List<Amenity> amenities = ((NameFinderPoiFilter) filter).getSearchedAmenities();
|
List<Amenity> amenities = ((NameFinderPoiFilter) filter).getSearchedAmenities();
|
||||||
|
|
|
@ -40,7 +40,6 @@ import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Frolov
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class EditPOIFilterActivity extends ListActivity {
|
public class EditPOIFilterActivity extends ListActivity {
|
||||||
|
|
|
@ -3,19 +3,24 @@
|
||||||
*/
|
*/
|
||||||
package net.osmand.plus.activities.search;
|
package net.osmand.plus.activities.search;
|
||||||
|
|
||||||
|
|
||||||
import gnu.trove.set.hash.TLongHashSet;
|
import gnu.trove.set.hash.TLongHashSet;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import net.osmand.Algoritms;
|
import net.osmand.Algoritms;
|
||||||
import net.osmand.LogUtil;
|
import net.osmand.LogUtil;
|
||||||
import net.osmand.OsmAndFormatter;
|
import net.osmand.OsmAndFormatter;
|
||||||
import net.osmand.ResultMatcher;
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.data.Amenity;
|
import net.osmand.data.Amenity;
|
||||||
|
import net.osmand.data.AmenityType;
|
||||||
import net.osmand.osm.LatLon;
|
import net.osmand.osm.LatLon;
|
||||||
import net.osmand.osm.OpeningHoursParser;
|
import net.osmand.osm.OpeningHoursParser;
|
||||||
import net.osmand.osm.OpeningHoursParser.OpeningHoursRule;
|
import net.osmand.osm.OpeningHoursParser.OpeningHoursRule;
|
||||||
|
@ -24,11 +29,13 @@ import net.osmand.plus.OsmandSettings;
|
||||||
import net.osmand.plus.PoiFilter;
|
import net.osmand.plus.PoiFilter;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.SearchByNameFilter;
|
import net.osmand.plus.SearchByNameFilter;
|
||||||
|
import net.osmand.plus.activities.EditPOIFilterActivity;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.activities.OsmandApplication;
|
import net.osmand.plus.activities.OsmandApplication;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
@ -70,8 +77,7 @@ import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maxim Frolov
|
* Search poi activity
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class SearchPOIActivity extends ListActivity implements SensorEventListener {
|
public class SearchPOIActivity extends ListActivity implements SensorEventListener {
|
||||||
|
|
||||||
|
@ -137,7 +143,9 @@ public class SearchPOIActivity extends ListActivity implements SensorEventListen
|
||||||
runNewSearchQuery(SearchAmenityRequest.buildRequest(location, SearchAmenityRequest.NEW_SEARCH_INIT));
|
runNewSearchQuery(SearchAmenityRequest.buildRequest(location, SearchAmenityRequest.NEW_SEARCH_INIT));
|
||||||
} else if(isSearchByNameFilter() &&
|
} else if(isSearchByNameFilter() &&
|
||||||
!Algoritms.objectEquals(((SearchByNameFilter) filter).getQuery(), query)){
|
!Algoritms.objectEquals(((SearchByNameFilter) filter).getQuery(), query)){
|
||||||
|
showFilter.setVisibility(View.INVISIBLE);
|
||||||
filter.clearPreviousZoom();
|
filter.clearPreviousZoom();
|
||||||
|
showPoiCategoriesByNameFilter(query, location);
|
||||||
((SearchByNameFilter) filter).setQuery(query);
|
((SearchByNameFilter) filter).setQuery(query);
|
||||||
runNewSearchQuery(SearchAmenityRequest.buildRequest(location, SearchAmenityRequest.NEW_SEARCH_INIT));
|
runNewSearchQuery(SearchAmenityRequest.buildRequest(location, SearchAmenityRequest.NEW_SEARCH_INIT));
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,11 +157,21 @@ public class SearchPOIActivity extends ListActivity implements SensorEventListen
|
||||||
showFilter.setOnClickListener(new OnClickListener() {
|
showFilter.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (searchFilterLayout.getVisibility() == View.GONE) {
|
if(isSearchByNameFilter()){
|
||||||
searchFilterLayout.setVisibility(View.VISIBLE);
|
Intent newIntent = new Intent(SearchPOIActivity.this, EditPOIFilterActivity.class);
|
||||||
|
newIntent.putExtra(EditPOIFilterActivity.AMENITY_FILTER, PoiFilter.CUSTOM_FILTER_ID);
|
||||||
|
if(location != null) {
|
||||||
|
newIntent.putExtra(EditPOIFilterActivity.SEARCH_LAT, location.getLatitude());
|
||||||
|
newIntent.putExtra(EditPOIFilterActivity.SEARCH_LON, location.getLongitude());
|
||||||
|
}
|
||||||
|
startActivity(newIntent);
|
||||||
} else {
|
} else {
|
||||||
searchFilter.setText(""); //$NON-NLS-1$
|
if (searchFilterLayout.getVisibility() == View.GONE) {
|
||||||
searchFilterLayout.setVisibility(View.GONE);
|
searchFilterLayout.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
searchFilter.setText(""); //$NON-NLS-1$
|
||||||
|
searchFilterLayout.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -233,14 +251,17 @@ public class SearchPOIActivity extends ListActivity implements SensorEventListen
|
||||||
clearSearchQuery();
|
clearSearchQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isNameFinderFilter() || isSearchByNameFilter() ){
|
if(isNameFinderFilter()){
|
||||||
showFilter.setVisibility(View.GONE);
|
showFilter.setVisibility(View.GONE);
|
||||||
searchFilterLayout.setVisibility(View.VISIBLE);
|
searchFilterLayout.setVisibility(View.VISIBLE);
|
||||||
|
} else if(isSearchByNameFilter() ){
|
||||||
|
showFilter.setVisibility(View.INVISIBLE);
|
||||||
|
searchFilterLayout.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
showFilter.setVisibility(View.VISIBLE);
|
showFilter.setVisibility(View.VISIBLE);
|
||||||
showOnMap.setEnabled(filter != null);
|
showOnMap.setEnabled(filter != null);
|
||||||
}
|
}
|
||||||
showOnMap.setVisibility(isSearchByNameFilter() ? View.INVISIBLE : View.VISIBLE);
|
showOnMap.setVisibility(isSearchByNameFilter() ? View.GONE : View.VISIBLE);
|
||||||
|
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
searchArea.setText(filter.getSearchArea());
|
searchArea.setText(filter.getSearchArea());
|
||||||
|
@ -261,7 +282,47 @@ public class SearchPOIActivity extends ListActivity implements SensorEventListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showPoiCategoriesByNameFilter(String query, Location loc){
|
||||||
|
OsmandApplication app = (OsmandApplication) getApplication();
|
||||||
|
if(loc != null){
|
||||||
|
Map<AmenityType, List<String>> map = app.getResourceManager().searchAmenityCategoriesByName(query, loc.getLatitude(), loc.getLongitude());
|
||||||
|
if(!map.isEmpty()){
|
||||||
|
PoiFilter filter = ((OsmandApplication)getApplication()).getPoiFilters().getFilterById(PoiFilter.CUSTOM_FILTER_ID);
|
||||||
|
if(filter != null){
|
||||||
|
showFilter.setVisibility(View.VISIBLE);
|
||||||
|
filter.setMapToAccept(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
String s = typesToString(map);
|
||||||
|
Toast.makeText(this, getString(R.string.poi_query_by_name_matches_categories) + s, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String typesToString(Map<AmenityType, List<String>> map) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
int count = 0;
|
||||||
|
Iterator<Entry<AmenityType, List<String>>> iterator = map.entrySet().iterator();
|
||||||
|
while(iterator.hasNext() && count < 4){
|
||||||
|
Entry<AmenityType, List<String>> e = iterator.next();
|
||||||
|
b.append("\n").append(OsmAndFormatter.toPublicString(e.getKey(), this)).append(" - ");
|
||||||
|
if(e.getValue() == null){
|
||||||
|
b.append("...");
|
||||||
|
} else {
|
||||||
|
for(int j=0; j<e.getValue().size() && j < 3; j++){
|
||||||
|
if(j > 0){
|
||||||
|
b.append(", ");
|
||||||
|
}
|
||||||
|
b.append(e.getValue().get(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(iterator.hasNext()){
|
||||||
|
b.append("\n...");
|
||||||
|
}
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateSearchPoiTextButton(){
|
private void updateSearchPoiTextButton(){
|
||||||
if(location == null){
|
if(location == null){
|
||||||
searchPOILevel.setText(R.string.search_poi_location);
|
searchPOILevel.setText(R.string.search_poi_location);
|
||||||
|
|
|
@ -110,6 +110,7 @@ public class SearchPoiFilterActivity extends ListActivity {
|
||||||
public void onListItemClick(ListView parent, View v, int position, long id) {
|
public void onListItemClick(ListView parent, View v, int position, long id) {
|
||||||
final PoiFilter filter = ((AmenityAdapter) getListAdapter()).getItem(position);
|
final PoiFilter filter = ((AmenityAdapter) getListAdapter()).getItem(position);
|
||||||
if (filter.getFilterId().equals(PoiFilter.CUSTOM_FILTER_ID)) {
|
if (filter.getFilterId().equals(PoiFilter.CUSTOM_FILTER_ID)) {
|
||||||
|
filter.clearFilter();
|
||||||
showEditActivity(filter);
|
showEditActivity(filter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue