Core search in progress
This commit is contained in:
parent
44eeb3f7cc
commit
1a455885fa
22 changed files with 875 additions and 190 deletions
|
@ -4,6 +4,10 @@ android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 23
|
||||||
buildToolsVersion "23.0.3"
|
buildToolsVersion "23.0.3"
|
||||||
|
|
||||||
|
dexOptions {
|
||||||
|
jumboMode true
|
||||||
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
|
|
|
@ -23,12 +23,10 @@ import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import net.osmand.core.android.AtlasMapRendererView;
|
import net.osmand.core.android.AtlasMapRendererView;
|
||||||
import net.osmand.core.android.NativeCore;
|
|
||||||
import net.osmand.core.jni.AreaI;
|
import net.osmand.core.jni.AreaI;
|
||||||
import net.osmand.core.jni.IMapLayerProvider;
|
import net.osmand.core.jni.IMapLayerProvider;
|
||||||
import net.osmand.core.jni.IMapStylesCollection;
|
import net.osmand.core.jni.IMapStylesCollection;
|
||||||
import net.osmand.core.jni.LatLon;
|
import net.osmand.core.jni.LatLon;
|
||||||
import net.osmand.core.jni.LogSeverityLevel;
|
|
||||||
import net.osmand.core.jni.Logger;
|
import net.osmand.core.jni.Logger;
|
||||||
import net.osmand.core.jni.MapObjectsSymbolsProvider;
|
import net.osmand.core.jni.MapObjectsSymbolsProvider;
|
||||||
import net.osmand.core.jni.MapPresentationEnvironment;
|
import net.osmand.core.jni.MapPresentationEnvironment;
|
||||||
|
@ -45,12 +43,12 @@ import net.osmand.core.jni.Utilities;
|
||||||
import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener;
|
import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener;
|
||||||
import net.osmand.core.samples.android.sample1.adapters.SearchListAdapter;
|
import net.osmand.core.samples.android.sample1.adapters.SearchListAdapter;
|
||||||
import net.osmand.core.samples.android.sample1.adapters.SearchListItem;
|
import net.osmand.core.samples.android.sample1.adapters.SearchListItem;
|
||||||
|
|
||||||
import net.osmand.core.samples.android.sample1.search.SearchAPI;
|
import net.osmand.core.samples.android.sample1.search.SearchAPI;
|
||||||
import net.osmand.core.samples.android.sample1.search.SearchAPI.SearchAPICallback;
|
import net.osmand.core.samples.android.sample1.search.SearchAPI.SearchCallback;
|
||||||
import net.osmand.core.samples.android.sample1.search.SearchItem;
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -86,7 +84,8 @@ public class MainActivity extends Activity {
|
||||||
private SearchAPI searchAPI;
|
private SearchAPI searchAPI;
|
||||||
private ListView searchListView;
|
private ListView searchListView;
|
||||||
private SearchListAdapter adapter;
|
private SearchListAdapter adapter;
|
||||||
private final static int MAX_SEARCH_RESULTS = 50;
|
private final static int MAX_SEARCH_RESULTS_CORE = 500;
|
||||||
|
private final static int MAX_SEARCH_RESULTS_IU = 50;
|
||||||
|
|
||||||
// Germany
|
// Germany
|
||||||
private final static float INIT_LAT = 49.353953f;
|
private final static float INIT_LAT = 49.353953f;
|
||||||
|
@ -402,41 +401,50 @@ public class MainActivity extends Activity {
|
||||||
private void runSearch(AreaI bounds31, String keyword) {
|
private void runSearch(AreaI bounds31, String keyword) {
|
||||||
|
|
||||||
searchAPI.setObfAreaFilter(bounds31);
|
searchAPI.setObfAreaFilter(bounds31);
|
||||||
searchAPI.startSearch(keyword, MAX_SEARCH_RESULTS, new SearchAPICallback() {
|
searchAPI.startSearch(keyword, MAX_SEARCH_RESULTS_CORE,
|
||||||
@Override
|
// Intermediate search callback
|
||||||
public void onSearchFinished(List<SearchItem> searchItems, boolean cancelled) {
|
new SearchCallback() {
|
||||||
if (searchItems != null && !cancelled) {
|
@Override
|
||||||
LatLon latLon = Utilities.convert31ToLatLon(target31);
|
public void onSearchFinished(List<SearchItem> searchItems) {
|
||||||
List<SearchListItem> rows = new ArrayList<>();
|
processSearchResult(searchItems);
|
||||||
for (SearchItem item : searchItems) {
|
|
||||||
SearchListItem row =
|
|
||||||
SearchListItem.buildListItem((SampleApplication)getApplication(), item);
|
|
||||||
rows.add(row);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
adapter.clear();
|
// Core search callback
|
||||||
adapter.addAll(rows);
|
new SearchCallback() {
|
||||||
adapter.updateDistance(latLon.getLatitude(), latLon.getLongitude());
|
@Override
|
||||||
adapter.sort(new Comparator<SearchListItem>() {
|
public void onSearchFinished(List<SearchItem> searchItems) {
|
||||||
@Override
|
processSearchResult(searchItems);
|
||||||
public int compare(SearchListItem lhs, SearchListItem rhs) {
|
|
||||||
int res = Double.compare(lhs.getDistance(), rhs.getDistance());
|
|
||||||
if (res == 0) {
|
|
||||||
return lhs.getName().compareToIgnoreCase(rhs.getName());
|
|
||||||
} else {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
if (adapter.getCount() > 0) {
|
|
||||||
searchListView.setSelection(0);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
showSearchList();
|
private void processSearchResult(List<SearchItem> searchItems) {
|
||||||
|
if (searchItems != null) {
|
||||||
|
LatLon latLon = Utilities.convert31ToLatLon(target31);
|
||||||
|
double latitude = latLon.getLatitude();
|
||||||
|
double longitude = latLon.getLongitude();
|
||||||
|
List<SearchListItem> rows = new ArrayList<>();
|
||||||
|
for (SearchItem item : searchItems) {
|
||||||
|
SearchListItem listItem =
|
||||||
|
SearchListItem.buildListItem((SampleApplication)getApplication(), item);
|
||||||
|
if (listItem != null) {
|
||||||
|
rows.add(listItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
if (rows.size() > MAX_SEARCH_RESULTS_IU) {
|
||||||
|
rows = rows.subList(0, MAX_SEARCH_RESULTS_IU);
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter.clear();
|
||||||
|
adapter.addAll(rows);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
if (adapter.getCount() > 0) {
|
||||||
|
searchListView.setSelection(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
showSearchList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MapViewOnGestureListener extends SimpleOnGestureListener {
|
private class MapViewOnGestureListener extends SimpleOnGestureListener {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package net.osmand.core.samples.android.sample1.adapters;
|
||||||
|
|
||||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||||
import net.osmand.core.samples.android.sample1.search.AddressSearchItem;
|
import net.osmand.core.samples.android.sample1.search.items.AddressSearchItem;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
public class AddressSearchListItem extends SearchListItem {
|
public class AddressSearchListItem extends SearchListItem {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||||
import net.osmand.core.samples.android.sample1.search.AmenitySearchItem;
|
import net.osmand.core.samples.android.sample1.search.items.AmenitySearchItem;
|
||||||
import net.osmand.data.Amenity;
|
import net.osmand.data.Amenity;
|
||||||
import net.osmand.osm.MapPoiTypes;
|
import net.osmand.osm.MapPoiTypes;
|
||||||
import net.osmand.osm.PoiCategory;
|
import net.osmand.osm.PoiCategory;
|
||||||
|
|
|
@ -26,8 +26,7 @@ public class SearchListAdapter extends ArrayAdapter<SearchListItem> {
|
||||||
for (int i = 0; i < getCount(); i++) {
|
for (int i = 0; i < getCount(); i++) {
|
||||||
SearchListItem item = getItem(i);
|
SearchListItem item = getItem(i);
|
||||||
item.setDistance(Utilities.distance(
|
item.setDistance(Utilities.distance(
|
||||||
longitude, latitude,
|
longitude, latitude, item.getLongitude(), item.getLatitude()));
|
||||||
item.getLongitude(), item.getLatitude()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,14 @@ package net.osmand.core.samples.android.sample1.adapters;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||||
import net.osmand.core.samples.android.sample1.search.AddressSearchItem;
|
import net.osmand.core.samples.android.sample1.search.items.AddressSearchItem;
|
||||||
import net.osmand.core.samples.android.sample1.search.AmenitySearchItem;
|
import net.osmand.core.samples.android.sample1.search.items.AmenitySearchItem;
|
||||||
import net.osmand.core.samples.android.sample1.search.SearchItem;
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
|
||||||
public class SearchListItem {
|
public class SearchListItem {
|
||||||
|
|
||||||
protected SampleApplication app;
|
protected SampleApplication app;
|
||||||
private SearchItem searchItem;
|
private SearchItem searchItem;
|
||||||
private double distance;
|
|
||||||
|
|
||||||
public SearchListItem(SampleApplication app, SearchItem searchItem) {
|
public SearchListItem(SampleApplication app, SearchItem searchItem) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
@ -45,11 +44,11 @@ public class SearchListItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getDistance() {
|
public double getDistance() {
|
||||||
return distance;
|
return searchItem.getDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDistance(double distance) {
|
public void setDistance(double distance) {
|
||||||
this.distance = distance;
|
searchItem.setDistance(distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable getIcon() {
|
public Drawable getIcon() {
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
package net.osmand.core.samples.android.sample1.search;
|
package net.osmand.core.samples.android.sample1.search;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import net.osmand.core.jni.Address;
|
|
||||||
import net.osmand.core.jni.AddressesByNameSearch;
|
|
||||||
import net.osmand.core.jni.AmenitiesByNameSearch;
|
|
||||||
import net.osmand.core.jni.Amenity;
|
|
||||||
import net.osmand.core.jni.AreaI;
|
import net.osmand.core.jni.AreaI;
|
||||||
import net.osmand.core.jni.IQueryController;
|
|
||||||
import net.osmand.core.jni.ISearch;
|
|
||||||
import net.osmand.core.jni.ISearch.INewResultEntryCallback;
|
|
||||||
import net.osmand.core.jni.NullableAreaI;
|
|
||||||
import net.osmand.core.jni.ObfsCollection;
|
import net.osmand.core.jni.ObfsCollection;
|
||||||
|
import net.osmand.core.jni.PointI;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.requests.CoreSearchRequest;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.requests.IntermediateSearchRequest;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.requests.SearchRequest;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SearchAPI {
|
public class SearchAPI {
|
||||||
|
@ -21,15 +17,23 @@ public class SearchAPI {
|
||||||
private ObfsCollection obfsCollection;
|
private ObfsCollection obfsCollection;
|
||||||
private AreaI searchableArea;
|
private AreaI searchableArea;
|
||||||
private AreaI obfAreaFilter;
|
private AreaI obfAreaFilter;
|
||||||
private SearchRequestExecutor executor;
|
private PointI searchLocation;
|
||||||
|
private double searchRadius;
|
||||||
|
|
||||||
public interface SearchAPICallback {
|
private SearchRequestExecutor executor;
|
||||||
void onSearchFinished(List<SearchItem> searchItems, boolean cancelled);
|
private SearchString searchString;
|
||||||
|
private SearchScope searchScope;
|
||||||
|
private List<SearchItem> searchItems;
|
||||||
|
|
||||||
|
public interface SearchCallback {
|
||||||
|
void onSearchFinished(List<SearchItem> searchItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchAPI(ObfsCollection obfsCollection) {
|
public SearchAPI(@NonNull ObfsCollection obfsCollection) {
|
||||||
this.obfsCollection = obfsCollection;
|
this.obfsCollection = obfsCollection;
|
||||||
executor = new SearchRequestExecutor();
|
this.executor = new SearchRequestExecutor();
|
||||||
|
this.searchString = new SearchString();
|
||||||
|
this.searchScope = new SearchScope(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AreaI getSearchableArea() {
|
public AreaI getSearchableArea() {
|
||||||
|
@ -48,8 +52,55 @@ public class SearchAPI {
|
||||||
this.obfAreaFilter = obfAreaFilter;
|
this.obfAreaFilter = obfAreaFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startSearch(String keyword, int maxSearchResults, SearchAPICallback apiCallback) {
|
public PointI getSearchLocation() {
|
||||||
executor.run(new SearchRequest(keyword, maxSearchResults, apiCallback), true);
|
return searchLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchLocation(PointI searchLocation) {
|
||||||
|
this.searchLocation = searchLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSearchRadius() {
|
||||||
|
return searchRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchRadius(double searchRadius) {
|
||||||
|
this.searchRadius = searchRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObfsCollection getObfsCollection() {
|
||||||
|
return obfsCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchString getSearchString() {
|
||||||
|
return searchString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchScope getSearchScope() {
|
||||||
|
return searchScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SearchItem> getSearchItems() {
|
||||||
|
return searchItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchItems(List<SearchItem> searchItems) {
|
||||||
|
this.searchItems = searchItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startSearch(String query, int maxSearchResults,
|
||||||
|
SearchCallback intermediateSearchCallback,
|
||||||
|
SearchCallback coreSearchCallback) {
|
||||||
|
|
||||||
|
searchString.setQueryText(query);
|
||||||
|
searchScope.updateScope();
|
||||||
|
IntermediateSearchRequest intermediateSearchRequest = null;
|
||||||
|
if (searchItems != null && !searchItems.isEmpty()) {
|
||||||
|
intermediateSearchRequest =
|
||||||
|
new IntermediateSearchRequest(this, maxSearchResults, intermediateSearchCallback);
|
||||||
|
}
|
||||||
|
executor.run(new CoreSearchRequest(intermediateSearchRequest, this,
|
||||||
|
maxSearchResults, coreSearchCallback), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelSearch() {
|
public void cancelSearch() {
|
||||||
|
@ -97,127 +148,4 @@ public class SearchAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SearchRequest {
|
|
||||||
private String keyword;
|
|
||||||
private int maxSearchResults;
|
|
||||||
private Runnable onFinished;
|
|
||||||
private SearchAPICallback apiCallback;
|
|
||||||
|
|
||||||
private boolean cancelled;
|
|
||||||
private int amenityResultsCounter;
|
|
||||||
private int addressResultsCounter;
|
|
||||||
|
|
||||||
public SearchRequest(String keyword, int maxSearchResults, SearchAPICallback apiCallback) {
|
|
||||||
this.keyword = keyword;
|
|
||||||
this.maxSearchResults = maxSearchResults;
|
|
||||||
this.apiCallback = apiCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
new AsyncTask<String, Void, List<SearchItem>>() {
|
|
||||||
@Override
|
|
||||||
protected List<SearchItem> doInBackground(String... params) {
|
|
||||||
return doSearch(params[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(List<SearchItem> searchItems) {
|
|
||||||
|
|
||||||
if (onFinished != null) {
|
|
||||||
onFinished.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apiCallback != null) {
|
|
||||||
apiCallback.onSearchFinished(searchItems, cancelled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.execute(keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SearchItem> doSearch(String keyword) {
|
|
||||||
System.out.println("=== Start search");
|
|
||||||
amenityResultsCounter = 0;
|
|
||||||
addressResultsCounter = 0;
|
|
||||||
|
|
||||||
final List<SearchItem> searchItems = new ArrayList<>();
|
|
||||||
|
|
||||||
// Setup Amenities by name search
|
|
||||||
AmenitiesByNameSearch amByNameSearch = new AmenitiesByNameSearch(obfsCollection);
|
|
||||||
AmenitiesByNameSearch.Criteria amByNameCriteria = new AmenitiesByNameSearch.Criteria();
|
|
||||||
amByNameCriteria.setName(keyword);
|
|
||||||
if (obfAreaFilter != null) {
|
|
||||||
amByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(obfAreaFilter));
|
|
||||||
}
|
|
||||||
INewResultEntryCallback amByNameResultCallback = new ISearch.INewResultEntryCallback() {
|
|
||||||
@Override
|
|
||||||
public void method(ISearch.Criteria criteria, ISearch.IResultEntry resultEntry) {
|
|
||||||
Amenity amenity = new AmenityResultEntry(resultEntry).getAmenity();
|
|
||||||
AmenitySearchItem amenitySearchItem = new AmenitySearchItem(amenity);
|
|
||||||
searchItems.add(amenitySearchItem);
|
|
||||||
System.out.println("Poi found === " + amenitySearchItem.toString());
|
|
||||||
amenityResultsCounter++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup Addresses by name search
|
|
||||||
AddressesByNameSearch addrByNameSearch = new AddressesByNameSearch(obfsCollection);
|
|
||||||
AddressesByNameSearch.Criteria addrByNameCriteria = new AddressesByNameSearch.Criteria();
|
|
||||||
addrByNameCriteria.setName(keyword);
|
|
||||||
if (obfAreaFilter != null) {
|
|
||||||
addrByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(obfAreaFilter));
|
|
||||||
}
|
|
||||||
INewResultEntryCallback addrByNameResultCallback = new ISearch.INewResultEntryCallback() {
|
|
||||||
@Override
|
|
||||||
public void method(ISearch.Criteria criteria, ISearch.IResultEntry resultEntry) {
|
|
||||||
Address address = new AddressResultEntry(resultEntry).getAddress();
|
|
||||||
AddressSearchItem addrSearchItem = new AddressSearchItem(address);
|
|
||||||
searchItems.add(addrSearchItem);
|
|
||||||
System.out.println("Address found === " + addrSearchItem.toString());
|
|
||||||
addressResultsCounter++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
amByNameSearch.performSearch(amByNameCriteria, amByNameResultCallback.getBinding(), new IQueryController() {
|
|
||||||
@Override
|
|
||||||
public boolean isAborted() {
|
|
||||||
return amenityResultsCounter >= maxSearchResults || cancelled;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!cancelled) {
|
|
||||||
addrByNameSearch.performSearch(addrByNameCriteria, addrByNameResultCallback.getBinding(), new IQueryController() {
|
|
||||||
@Override
|
|
||||||
public boolean isAborted() {
|
|
||||||
return addressResultsCounter >= maxSearchResults || cancelled;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println("=== Finish search");
|
|
||||||
|
|
||||||
return searchItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
cancelled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnFinishedCallback(Runnable onFinished) {
|
|
||||||
this.onFinished = onFinished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AmenityResultEntry extends AmenitiesByNameSearch.ResultEntry {
|
|
||||||
protected AmenityResultEntry(ISearch.IResultEntry resultEntry) {
|
|
||||||
super(ISearch.IResultEntry.getCPtr(resultEntry), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AddressResultEntry extends AddressesByNameSearch.ResultEntry {
|
|
||||||
protected AddressResultEntry(ISearch.IResultEntry resultEntry) {
|
|
||||||
super(ISearch.IResultEntry.getCPtr(resultEntry), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search;
|
||||||
|
|
||||||
|
import net.osmand.core.jni.AddressesByNameSearch;
|
||||||
|
import net.osmand.core.jni.AmenitiesByNameSearch;
|
||||||
|
import net.osmand.core.jni.LatLon;
|
||||||
|
import net.osmand.core.jni.QStringList;
|
||||||
|
import net.osmand.core.jni.QStringStringListHash;
|
||||||
|
import net.osmand.core.jni.Utilities;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.AddressSearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.AmenitySearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.CitySearchToken;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.PoiTypeSearchToken;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.PostcodeSearchToken;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken.TokenType;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SearchScope {
|
||||||
|
|
||||||
|
private SearchAPI searchAPI;
|
||||||
|
private Map<TokenType, SearchToken> resolvedTokens;
|
||||||
|
private double searchLat;
|
||||||
|
private double searchLon;
|
||||||
|
private double searchRadius;
|
||||||
|
|
||||||
|
public SearchScope(SearchAPI searchAPI) {
|
||||||
|
this.searchAPI = searchAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateScope() {
|
||||||
|
resolvedTokens = searchAPI.getSearchString().getResolvedTokens();
|
||||||
|
LatLon latLon = Utilities.convert31ToLatLon(searchAPI.getSearchLocation());
|
||||||
|
searchLat = latLon.getLatitude();
|
||||||
|
searchLon = latLon.getLongitude();
|
||||||
|
searchRadius = searchAPI.getSearchRadius();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupAmenitySearchCriteria(AmenitiesByNameSearch.Criteria criteria) {
|
||||||
|
String categoryName = null;
|
||||||
|
String typeName = null;
|
||||||
|
if (resolvedTokens.containsKey(TokenType.POI_TYPE)) {
|
||||||
|
PoiTypeSearchToken token = (PoiTypeSearchToken)resolvedTokens.get(TokenType.POI_TYPE);
|
||||||
|
categoryName = token.getPoiType().getCategory().getKeyName();
|
||||||
|
typeName = token.getName();
|
||||||
|
} else if (resolvedTokens.containsKey(TokenType.POI_FILTER)) {
|
||||||
|
SearchToken token = resolvedTokens.get(TokenType.POI_FILTER);
|
||||||
|
categoryName = token.getName();
|
||||||
|
} else if (resolvedTokens.containsKey(TokenType.POI_CATEGORY)) {
|
||||||
|
SearchToken token = resolvedTokens.get(TokenType.POI_CATEGORY);
|
||||||
|
categoryName = token.getName();
|
||||||
|
}
|
||||||
|
if (!Algorithms.isEmpty(categoryName) && !Algorithms.isEmpty(typeName)) {
|
||||||
|
QStringStringListHash list = new QStringStringListHash();
|
||||||
|
QStringList stringList = new QStringList();
|
||||||
|
//todo list.set(categoryName, stringList);
|
||||||
|
criteria.setCategoriesFilter(list);
|
||||||
|
} else if (!Algorithms.isEmpty(categoryName)) {
|
||||||
|
QStringStringListHash list = new QStringStringListHash();
|
||||||
|
//todo list.set(categoryName, new QStringList());
|
||||||
|
criteria.setCategoriesFilter(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupAddressSearchCriteria(AddressesByNameSearch.Criteria criteria) {
|
||||||
|
//not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean processAmenitySearchItem(AmenitySearchItem item) {
|
||||||
|
boolean res = true;
|
||||||
|
updateDistance(item);
|
||||||
|
if (searchRadius > 0) {
|
||||||
|
res = item.getDistance() < searchRadius;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean processAddressSearchItem(AddressSearchItem item) {
|
||||||
|
boolean res = true;
|
||||||
|
if (resolvedTokens.containsKey(TokenType.CITY) && item.getParentCityObfId() != null) {
|
||||||
|
CitySearchToken token = (CitySearchToken)resolvedTokens.get(TokenType.CITY);
|
||||||
|
res = token.getObfId().equals(item.getParentCityObfId());
|
||||||
|
} else if (resolvedTokens.containsKey(TokenType.POSTCODE) && item.getParentPostcodeObfId() != null) {
|
||||||
|
PostcodeSearchToken token = (PostcodeSearchToken)resolvedTokens.get(TokenType.CITY);
|
||||||
|
res = token.getObfId().equals(item.getParentPostcodeObfId());
|
||||||
|
}
|
||||||
|
if (res) {
|
||||||
|
updateDistance(item);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processSearchResult(List<SearchItem> searchItems) {
|
||||||
|
/*
|
||||||
|
Collections.sort(searchItems, new Comparator<SearchItem>() {
|
||||||
|
@Override
|
||||||
|
public int compare(SearchItem lhs, SearchItem rhs) {
|
||||||
|
int res = Double.compare(lhs.getDistance(), rhs.getDistance());
|
||||||
|
if (res == 0) {
|
||||||
|
return lhs.getName().compareToIgnoreCase(rhs.getName());
|
||||||
|
} else {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
//todo
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDistance(SearchItem item) {
|
||||||
|
item.setDistance(Utilities.distance(
|
||||||
|
searchLon, searchLat, item.getLongitude(), item.getLatitude()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search;
|
||||||
|
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.NameFilterSearchToken;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken.TokenType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SearchString {
|
||||||
|
|
||||||
|
private String queryText = "";
|
||||||
|
private List<SearchToken> tokens = new ArrayList<>();
|
||||||
|
|
||||||
|
public SearchString() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQueryText() {
|
||||||
|
return queryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setQueryText(String queryText) {
|
||||||
|
int newTextLength = queryText.length();
|
||||||
|
int currTextLength = this.queryText.length();
|
||||||
|
boolean isNewText = currTextLength == 0
|
||||||
|
|| newTextLength == 0
|
||||||
|
|| !this.queryText.regionMatches(0, queryText, 0,
|
||||||
|
newTextLength > currTextLength ? currTextLength : newTextLength);
|
||||||
|
|
||||||
|
int lastKnownTokenIndex = -1;
|
||||||
|
if (isNewText) {
|
||||||
|
tokens.clear();
|
||||||
|
} else {
|
||||||
|
int brokenTokenIndex = -1;
|
||||||
|
for (int i = 0; i < tokens.size(); i++) {
|
||||||
|
SearchToken token = tokens.get(i);
|
||||||
|
int lastTokenIndex = token.getLastIndex();
|
||||||
|
if (lastTokenIndex > newTextLength - 1
|
||||||
|
|| (lastTokenIndex < newTextLength - 1 && !startWithDelimiter(queryText.substring(lastTokenIndex + 1)))) {
|
||||||
|
brokenTokenIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastKnownTokenIndex = token.getLastIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brokenTokenIndex != -1) {
|
||||||
|
if (brokenTokenIndex == 0) {
|
||||||
|
tokens.clear();
|
||||||
|
} else {
|
||||||
|
for (int i = tokens.size() - 1; i >= brokenTokenIndex; i--) {
|
||||||
|
tokens.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newTextLength - 1 > lastKnownTokenIndex) {
|
||||||
|
int firstWordIndex = lastKnownTokenIndex + 1;
|
||||||
|
for (int i = lastKnownTokenIndex + 1; i < newTextLength; i++) {
|
||||||
|
char c = queryText.charAt(i);
|
||||||
|
if (isDelimiterChar(c)) {
|
||||||
|
if (i == firstWordIndex) {
|
||||||
|
firstWordIndex++;
|
||||||
|
} else {
|
||||||
|
SearchToken token = new NameFilterSearchToken(firstWordIndex, queryText.substring(firstWordIndex, i));
|
||||||
|
tokens.add(token);
|
||||||
|
firstWordIndex = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (firstWordIndex <= newTextLength - 1) {
|
||||||
|
SearchToken token = new NameFilterSearchToken(firstWordIndex, queryText.substring(firstWordIndex));
|
||||||
|
tokens.add(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.queryText = queryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean startWithDelimiter(String text) {
|
||||||
|
char firstChar = text.charAt(0);
|
||||||
|
return isDelimiterChar(firstChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDelimiterChar(char c) {
|
||||||
|
return c == ',' || c == ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized SearchToken getNextNameFilterToken() {
|
||||||
|
SearchToken res = null;
|
||||||
|
if (!tokens.isEmpty()) {
|
||||||
|
for (int i = tokens.size() - 1; i >= 0; i--) {
|
||||||
|
SearchToken token = tokens.get(i);
|
||||||
|
if (token.getType() == TokenType.NAME_FILTER) {
|
||||||
|
res = token;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized SearchToken getLastToken() {
|
||||||
|
if (!tokens.isEmpty()) {
|
||||||
|
return tokens.get(tokens.size() - 1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean hasNameFilterTokens() {
|
||||||
|
return getNextNameFilterToken() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean replaceToken(SearchToken oldToken, SearchToken newToken) {
|
||||||
|
int index = tokens.indexOf(oldToken);
|
||||||
|
if (index != -1) {
|
||||||
|
tokens.set(index, newToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Map<TokenType, SearchToken> getResolvedTokens() {
|
||||||
|
Map<TokenType, SearchToken> map = new HashMap<>();
|
||||||
|
for (SearchToken token : tokens) {
|
||||||
|
if (token.getType() != SearchToken.TokenType.NAME_FILTER) {
|
||||||
|
map.put(token.getType(), token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
//test
|
||||||
|
SearchString searchString = new SearchString();
|
||||||
|
searchString.setQueryText("cit");
|
||||||
|
searchString.setQueryText("city");
|
||||||
|
searchString.setQueryText("city ");
|
||||||
|
searchString.setQueryText("city s");
|
||||||
|
searchString.setQueryText("city st");
|
||||||
|
searchString.setQueryText("city street ");
|
||||||
|
searchString.setQueryText("city street 8");
|
||||||
|
searchString.setQueryText("new");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,23 @@
|
||||||
package net.osmand.core.samples.android.sample1.search;
|
package net.osmand.core.samples.android.sample1.search.items;
|
||||||
|
|
||||||
import net.osmand.core.jni.Address;
|
import net.osmand.core.jni.Address;
|
||||||
import net.osmand.core.jni.ObfAddressStreetGroupSubtype;
|
import net.osmand.core.jni.ObfAddressStreetGroupSubtype;
|
||||||
|
import net.osmand.core.jni.ObfAddressStreetGroupType;
|
||||||
import net.osmand.core.jni.Street;
|
import net.osmand.core.jni.Street;
|
||||||
import net.osmand.core.jni.StreetGroup;
|
import net.osmand.core.jni.StreetGroup;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
public class AddressSearchItem extends SearchItem {
|
public class AddressSearchItem extends SearchItem {
|
||||||
|
|
||||||
private String namePrefix;
|
private String namePrefix;
|
||||||
private String nameSuffix;
|
private String nameSuffix;
|
||||||
private String typeStr;
|
private String typeStr;
|
||||||
|
|
||||||
|
private BigInteger parentCityObfId;
|
||||||
|
private BigInteger parentPostcodeObfId;
|
||||||
|
|
||||||
public AddressSearchItem(Address address) {
|
public AddressSearchItem(Address address) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -22,8 +28,14 @@ public class AddressSearchItem extends SearchItem {
|
||||||
setNativeName(street.getNativeName());
|
setNativeName(street.getNativeName());
|
||||||
addLocalizedNames(street.getLocalizedNames());
|
addLocalizedNames(street.getLocalizedNames());
|
||||||
if (street.getStreetGroup() != null) {
|
if (street.getStreetGroup() != null) {
|
||||||
|
StreetGroup streetGroup = street.getStreetGroup();
|
||||||
nameSuffix = "st.";
|
nameSuffix = "st.";
|
||||||
typeStr = street.getStreetGroup().getNativeName() + " — " + getTypeStr(street.getStreetGroup());
|
typeStr = streetGroup.getNativeName() + " — " + getTypeStr(streetGroup);
|
||||||
|
if (streetGroup.getType() == ObfAddressStreetGroupType.Postcode) {
|
||||||
|
parentPostcodeObfId = streetGroup.getId().getId();
|
||||||
|
} else {
|
||||||
|
parentCityObfId = streetGroup.getId().getId();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
typeStr = "Street";
|
typeStr = "Street";
|
||||||
}
|
}
|
||||||
|
@ -77,6 +89,14 @@ public class AddressSearchItem extends SearchItem {
|
||||||
return typeStr;
|
return typeStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigInteger getParentCityObfId() {
|
||||||
|
return parentCityObfId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getParentPostcodeObfId() {
|
||||||
|
return parentPostcodeObfId;
|
||||||
|
}
|
||||||
|
|
||||||
private class StreetInternal extends Street {
|
private class StreetInternal extends Street {
|
||||||
public StreetInternal(Address address) {
|
public StreetInternal(Address address) {
|
||||||
super(Address.getCPtr(address), false);
|
super(Address.getCPtr(address), false);
|
|
@ -1,4 +1,4 @@
|
||||||
package net.osmand.core.samples.android.sample1.search;
|
package net.osmand.core.samples.android.sample1.search.items;
|
||||||
|
|
||||||
import net.osmand.core.jni.Amenity;
|
import net.osmand.core.jni.Amenity;
|
||||||
import net.osmand.core.jni.DecodedCategoryList;
|
import net.osmand.core.jni.DecodedCategoryList;
|
|
@ -1,4 +1,4 @@
|
||||||
package net.osmand.core.samples.android.sample1.search;
|
package net.osmand.core.samples.android.sample1.search.items;
|
||||||
|
|
||||||
import net.osmand.core.jni.LatLon;
|
import net.osmand.core.jni.LatLon;
|
||||||
import net.osmand.core.jni.PointI;
|
import net.osmand.core.jni.PointI;
|
||||||
|
@ -16,6 +16,9 @@ public abstract class SearchItem {
|
||||||
protected String nativeName;
|
protected String nativeName;
|
||||||
protected Map<String, String> localizedNames = new HashMap<>();
|
protected Map<String, String> localizedNames = new HashMap<>();
|
||||||
|
|
||||||
|
private double distance;
|
||||||
|
private float priority;
|
||||||
|
|
||||||
protected SearchItem() {
|
protected SearchItem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +74,22 @@ public abstract class SearchItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getDistance() {
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistance(double distance) {
|
||||||
|
this.distance = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(float priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getName() + " (" + getType() + ") {lat:" + getLatitude() + " lon: " + getLongitude() + "}";
|
return getName() + " (" + getType() + ") {lat:" + getLatitude() + " lon: " + getLongitude() + "}";
|
|
@ -0,0 +1,175 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.requests;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.core.jni.Address;
|
||||||
|
import net.osmand.core.jni.AddressesByNameSearch;
|
||||||
|
import net.osmand.core.jni.AmenitiesByNameSearch;
|
||||||
|
import net.osmand.core.jni.Amenity;
|
||||||
|
import net.osmand.core.jni.IQueryController;
|
||||||
|
import net.osmand.core.jni.ISearch;
|
||||||
|
import net.osmand.core.jni.NullableAreaI;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchAPI;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchAPI.SearchCallback;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.AddressSearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.AmenitySearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CoreSearchRequest extends SearchRequest {
|
||||||
|
|
||||||
|
private IntermediateSearchRequest intermediateSearchRequest;
|
||||||
|
private boolean intermediateSearchDone;
|
||||||
|
|
||||||
|
private int amenityResultsCounter;
|
||||||
|
private int addressResultsCounter;
|
||||||
|
|
||||||
|
public CoreSearchRequest(@Nullable IntermediateSearchRequest intermediateSearchRequest,
|
||||||
|
@NonNull SearchAPI searchAPI, int maxSearchResults, @Nullable SearchCallback searchCallback) {
|
||||||
|
super(searchAPI, maxSearchResults, searchCallback);
|
||||||
|
this.intermediateSearchRequest = intermediateSearchRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
if (intermediateSearchRequest != null) {
|
||||||
|
intermediateSearchRequest.setOnFinishedCallback(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
intermediateSearchDone = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
intermediateSearchRequest.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSearchRequestPostExecute(List<SearchItem> searchItems) {
|
||||||
|
if (intermediateSearchRequest != null && !intermediateSearchDone) {
|
||||||
|
intermediateSearchRequest.cancel();
|
||||||
|
}
|
||||||
|
searchAPI.setSearchItems(searchItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
if (intermediateSearchRequest != null) {
|
||||||
|
intermediateSearchRequest.cancel();
|
||||||
|
}
|
||||||
|
super.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<SearchItem> doSearch() {
|
||||||
|
|
||||||
|
List<SearchItem> res = new ArrayList<>();
|
||||||
|
|
||||||
|
SearchToken token = searchString.getNextNameFilterToken();
|
||||||
|
while (token != null && !cancelled) {
|
||||||
|
if (token.getType() == SearchToken.TokenType.NAME_FILTER) {
|
||||||
|
List<SearchItem> searchItems = doCoreSearch(token);
|
||||||
|
res.clear();
|
||||||
|
res.addAll(searchItems);
|
||||||
|
}
|
||||||
|
token = searchString.getNextNameFilterToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SearchItem> doCoreSearch(@NonNull SearchToken token) {
|
||||||
|
System.out.println("=== Start search");
|
||||||
|
amenityResultsCounter = 0;
|
||||||
|
addressResultsCounter = 0;
|
||||||
|
|
||||||
|
String keyword = token.getQueryText();
|
||||||
|
final List<SearchItem> searchItems = new ArrayList<>();
|
||||||
|
|
||||||
|
// Setup Amenities by name search
|
||||||
|
AmenitiesByNameSearch amByNameSearch = new AmenitiesByNameSearch(searchAPI.getObfsCollection());
|
||||||
|
AmenitiesByNameSearch.Criteria amenityByNameCriteria = new AmenitiesByNameSearch.Criteria();
|
||||||
|
amenityByNameCriteria.setName(keyword);
|
||||||
|
if (searchAPI.getObfAreaFilter() != null) {
|
||||||
|
amenityByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(searchAPI.getObfAreaFilter()));
|
||||||
|
}
|
||||||
|
searchScope.setupAmenitySearchCriteria(amenityByNameCriteria);
|
||||||
|
|
||||||
|
ISearch.INewResultEntryCallback amenityByNameResultCallback = new ISearch.INewResultEntryCallback() {
|
||||||
|
@Override
|
||||||
|
public void method(ISearch.Criteria criteria, ISearch.IResultEntry resultEntry) {
|
||||||
|
Amenity amenity = new AmenityResultEntry(resultEntry).getAmenity();
|
||||||
|
AmenitySearchItem amenitySearchItem = new AmenitySearchItem(amenity);
|
||||||
|
if (searchScope.processAmenitySearchItem(amenitySearchItem)) {
|
||||||
|
searchItems.add(amenitySearchItem);
|
||||||
|
}
|
||||||
|
System.out.println("Poi found === " + amenitySearchItem.toString());
|
||||||
|
amenityResultsCounter++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup Addresses by name search
|
||||||
|
AddressesByNameSearch addrByNameSearch = new AddressesByNameSearch(searchAPI.getObfsCollection());
|
||||||
|
AddressesByNameSearch.Criteria addrByNameCriteria = new AddressesByNameSearch.Criteria();
|
||||||
|
addrByNameCriteria.setName(keyword);
|
||||||
|
if (searchAPI.getObfAreaFilter() != null) {
|
||||||
|
addrByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(searchAPI.getObfAreaFilter()));
|
||||||
|
}
|
||||||
|
searchScope.setupAddressSearchCriteria(addrByNameCriteria);
|
||||||
|
|
||||||
|
ISearch.INewResultEntryCallback addrByNameResultCallback = new ISearch.INewResultEntryCallback() {
|
||||||
|
@Override
|
||||||
|
public void method(ISearch.Criteria criteria, ISearch.IResultEntry resultEntry) {
|
||||||
|
Address address = new AddressResultEntry(resultEntry).getAddress();
|
||||||
|
AddressSearchItem addrSearchItem = new AddressSearchItem(address);
|
||||||
|
if (searchScope.processAddressSearchItem(addrSearchItem)) {
|
||||||
|
searchItems.add(addrSearchItem);
|
||||||
|
}
|
||||||
|
System.out.println("Address found === " + addrSearchItem.toString());
|
||||||
|
addressResultsCounter++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
amByNameSearch.performSearch(amenityByNameCriteria, amenityByNameResultCallback.getBinding(), new IQueryController() {
|
||||||
|
@Override
|
||||||
|
public boolean isAborted() {
|
||||||
|
return amenityResultsCounter >= maxSearchResults || cancelled;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!cancelled) {
|
||||||
|
addrByNameSearch.performSearch(addrByNameCriteria, addrByNameResultCallback.getBinding(), new IQueryController() {
|
||||||
|
@Override
|
||||||
|
public boolean isAborted() {
|
||||||
|
return addressResultsCounter >= maxSearchResults || cancelled;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cancelled) {
|
||||||
|
searchScope.processSearchResult(searchItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("=== Finish search");
|
||||||
|
|
||||||
|
return searchItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AmenityResultEntry extends AmenitiesByNameSearch.ResultEntry {
|
||||||
|
protected AmenityResultEntry(ISearch.IResultEntry resultEntry) {
|
||||||
|
super(ISearch.IResultEntry.getCPtr(resultEntry), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AddressResultEntry extends AddressesByNameSearch.ResultEntry {
|
||||||
|
protected AddressResultEntry(ISearch.IResultEntry resultEntry) {
|
||||||
|
super(ISearch.IResultEntry.getCPtr(resultEntry), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.requests;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchAPI;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchAPI.SearchCallback;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.requests.SearchRequest;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IntermediateSearchRequest extends SearchRequest {
|
||||||
|
|
||||||
|
private List<SearchItem> searchItems;
|
||||||
|
protected String keyword = "";
|
||||||
|
|
||||||
|
public IntermediateSearchRequest(@NonNull SearchAPI searchAPI, int maxSearchResults, @Nullable SearchCallback searchCallback) {
|
||||||
|
super(searchAPI, maxSearchResults, searchCallback);
|
||||||
|
this.searchItems = new ArrayList<>(searchAPI.getSearchItems());
|
||||||
|
|
||||||
|
SearchToken token = searchString.getLastToken();
|
||||||
|
if (token != null && token.getType() == SearchToken.TokenType.NAME_FILTER) {
|
||||||
|
keyword = token.getQueryText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<SearchItem> doSearch() {
|
||||||
|
List<SearchItem> res = new ArrayList<>();
|
||||||
|
for (SearchItem item : searchItems) {
|
||||||
|
if (cancelled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (keyword.isEmpty() || item.getName().contains(keyword)) {
|
||||||
|
res.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.requests;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchAPI;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchAPI.SearchCallback;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchScope;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.SearchString;
|
||||||
|
import net.osmand.core.samples.android.sample1.search.items.SearchItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class SearchRequest {
|
||||||
|
protected SearchAPI searchAPI;
|
||||||
|
protected SearchString searchString;
|
||||||
|
protected SearchScope searchScope;
|
||||||
|
|
||||||
|
protected int maxSearchResults;
|
||||||
|
protected Runnable onFinished;
|
||||||
|
protected SearchCallback searchCallback;
|
||||||
|
|
||||||
|
protected boolean cancelled;
|
||||||
|
|
||||||
|
public SearchRequest(@NonNull SearchAPI searchAPI, int maxSearchResults, @Nullable SearchCallback searchCallback) {
|
||||||
|
this.searchAPI = searchAPI;
|
||||||
|
this.searchString = searchAPI.getSearchString();
|
||||||
|
this.searchScope= searchAPI.getSearchScope();
|
||||||
|
this.maxSearchResults = maxSearchResults;
|
||||||
|
this.searchCallback = searchCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
new AsyncTask<Void, Void, List<SearchItem>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<SearchItem> doInBackground(Void... params) {
|
||||||
|
return doSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(List<SearchItem> searchItems) {
|
||||||
|
|
||||||
|
onSearchRequestPostExecute(searchItems);
|
||||||
|
|
||||||
|
if (onFinished != null) {
|
||||||
|
onFinished.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchCallback != null && !cancelled) {
|
||||||
|
searchCallback.onSearchFinished(searchItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onSearchRequestPostExecute(List<SearchItem> searchItems) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract List<SearchItem> doSearch();
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnFinishedCallback(@Nullable Runnable onFinished) {
|
||||||
|
this.onFinished = onFinished;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class CitySearchToken extends SearchToken {
|
||||||
|
|
||||||
|
private BigInteger obfId;
|
||||||
|
|
||||||
|
public CitySearchToken(BigInteger obfId, int startIndex, String queryText, String name) {
|
||||||
|
super(TokenType.CITY, startIndex, queryText, name);
|
||||||
|
this.obfId = obfId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getObfId() {
|
||||||
|
return obfId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
public class NameFilterSearchToken extends SearchToken {
|
||||||
|
|
||||||
|
public NameFilterSearchToken(int startIndex, String queryText) {
|
||||||
|
super(TokenType.NAME_FILTER, startIndex, queryText, queryText);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.osm.PoiCategory;
|
||||||
|
|
||||||
|
public class PoiCategorySearchToken extends SearchToken {
|
||||||
|
private PoiCategory poiCategory;
|
||||||
|
|
||||||
|
public PoiCategorySearchToken(@NonNull PoiCategory poiCategory, int startIndex, String queryText) {
|
||||||
|
super(TokenType.POI_CATEGORY, startIndex, queryText, poiCategory.getKeyName());
|
||||||
|
this.poiCategory = poiCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoiCategory getPoiCategory() {
|
||||||
|
return poiCategory;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.osm.PoiCategory;
|
||||||
|
import net.osmand.osm.PoiFilter;
|
||||||
|
|
||||||
|
public class PoiFilterSearchToken extends SearchToken {
|
||||||
|
private PoiFilter poiFilter;
|
||||||
|
|
||||||
|
public PoiFilterSearchToken(@NonNull PoiFilter poiFilter, int startIndex, String queryText) {
|
||||||
|
super(TokenType.POI_FILTER, startIndex, queryText, poiFilter.getKeyName());
|
||||||
|
this.poiFilter = poiFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoiFilter getPoiFilter() {
|
||||||
|
return poiFilter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.osm.PoiFilter;
|
||||||
|
import net.osmand.osm.PoiType;
|
||||||
|
|
||||||
|
public class PoiTypeSearchToken extends SearchToken {
|
||||||
|
private PoiType poiType;
|
||||||
|
|
||||||
|
public PoiTypeSearchToken(@NonNull PoiType poiType, int startIndex, String queryText) {
|
||||||
|
super(TokenType.POI_TYPE, startIndex, queryText, poiType.getKeyName());
|
||||||
|
this.poiType = poiType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoiType getPoiType() {
|
||||||
|
return poiType;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class PostcodeSearchToken extends SearchToken {
|
||||||
|
private BigInteger obfId;
|
||||||
|
|
||||||
|
public PostcodeSearchToken(BigInteger obfId, int startIndex, String queryText, String name) {
|
||||||
|
super(TokenType.POSTCODE, startIndex, queryText, name);
|
||||||
|
this.obfId = obfId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getObfId() {
|
||||||
|
return obfId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||||
|
|
||||||
|
public abstract class SearchToken {
|
||||||
|
|
||||||
|
public enum TokenType {
|
||||||
|
CITY,
|
||||||
|
POSTCODE,
|
||||||
|
STREET,
|
||||||
|
BUILDING,
|
||||||
|
POI_CATEGORY,
|
||||||
|
POI_FILTER,
|
||||||
|
POI_TYPE,
|
||||||
|
LOCATION,
|
||||||
|
NAME_FILTER
|
||||||
|
}
|
||||||
|
|
||||||
|
private TokenType type;
|
||||||
|
private int startIndex;
|
||||||
|
protected String queryText;
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
public SearchToken(TokenType type, int startIndex, String queryText, String name) {
|
||||||
|
this.type = type;
|
||||||
|
this.startIndex = startIndex;
|
||||||
|
this.queryText = queryText;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStartIndex() {
|
||||||
|
return startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartIndex(int startIndex) {
|
||||||
|
this.startIndex = startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQueryText() {
|
||||||
|
return queryText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastIndex() {
|
||||||
|
return startIndex + queryText.length() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getQueryTextLenght() {
|
||||||
|
return queryText.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue