Address search in progress
This commit is contained in:
parent
cd68355c97
commit
85553fd2c3
39 changed files with 1009 additions and 743 deletions
|
@ -15,7 +15,7 @@
|
|||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_gravity="top"
|
||||
android:scaleType="centerInside"
|
||||
android:visibility="visible"/>
|
||||
|
||||
|
|
|
@ -43,13 +43,12 @@ import net.osmand.core.jni.Utilities;
|
|||
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.SearchListItem;
|
||||
import net.osmand.core.samples.android.sample1.adapters.SearchListPositionItem;
|
||||
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.SearchAPI.SearchApiCallback;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
@ -84,7 +83,7 @@ public class MainActivity extends Activity {
|
|||
private SearchAPI searchAPI;
|
||||
private ListView searchListView;
|
||||
private SearchListAdapter adapter;
|
||||
private final static int MAX_SEARCH_RESULTS_CORE = 500;
|
||||
private final static int MAX_SEARCH_RESULTS_CORE = 300;
|
||||
private final static int MAX_SEARCH_RESULTS_IU = 50;
|
||||
|
||||
// Germany
|
||||
|
@ -204,7 +203,7 @@ public class MainActivity extends Activity {
|
|||
|
||||
//Setup search
|
||||
|
||||
searchAPI = new SearchAPI(obfsCollection);
|
||||
searchAPI = new SearchAPI(obfsCollection, MapUtils.LANGUAGE);
|
||||
|
||||
final EditText searchEditText = (EditText) findViewById(R.id.searchEditText);
|
||||
searchEditText.addTextChangedListener(new TextWatcher() {
|
||||
|
@ -218,9 +217,7 @@ public class MainActivity extends Activity {
|
|||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (s.length() > 2) {
|
||||
runSearch(getScreenBounds31(), s.toString());
|
||||
}
|
||||
runSearch(getScreenCenter31(), getScreenBounds31(), s.toString());
|
||||
}
|
||||
});
|
||||
searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
|
@ -255,9 +252,13 @@ public class MainActivity extends Activity {
|
|||
hideSearchList();
|
||||
mapView.requestFocus();
|
||||
SearchListItem item = adapter.getItem(position);
|
||||
PointI target = Utilities.convertLatLonTo31(new LatLon(item.getLatitude(), item.getLongitude()));
|
||||
setTarget(target);
|
||||
setZoom(17f);
|
||||
if (item instanceof SearchListPositionItem) {
|
||||
SearchListPositionItem positionItem = (SearchListPositionItem) item;
|
||||
PointI target = Utilities.convertLatLonTo31(
|
||||
new LatLon(positionItem.getLatitude(), positionItem.getLongitude()));
|
||||
setTarget(target);
|
||||
setZoom(17f);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -289,6 +290,12 @@ public class MainActivity extends Activity {
|
|||
return (SampleApplication) getApplication();
|
||||
}
|
||||
|
||||
private PointI getScreenCenter31() {
|
||||
PointI point = new PointI();
|
||||
mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point);
|
||||
return point;
|
||||
}
|
||||
|
||||
private AreaI getScreenBounds31() {
|
||||
PointI topLeftPoint = new PointI();
|
||||
PointI bottomRightPoint = new PointI();
|
||||
|
@ -398,33 +405,31 @@ public class MainActivity extends Activity {
|
|||
|| gestureDetector.onTouchEvent(event);
|
||||
}
|
||||
|
||||
private void runSearch(AreaI bounds31, String keyword) {
|
||||
private void runSearch(PointI position31, AreaI bounds31, String keyword) {
|
||||
|
||||
searchAPI.setSearchLocation31(position31);
|
||||
searchAPI.setObfAreaFilter(bounds31);
|
||||
searchAPI.startSearch(keyword, MAX_SEARCH_RESULTS_CORE,
|
||||
// Intermediate search callback
|
||||
new SearchCallback() {
|
||||
new SearchApiCallback() {
|
||||
@Override
|
||||
public void onSearchFinished(List<SearchItem> searchItems) {
|
||||
processSearchResult(searchItems);
|
||||
public void onSearchFinished(List<SearchObject> searchObjects) {
|
||||
processSearchResult(searchObjects);
|
||||
}
|
||||
},
|
||||
// Core search callback
|
||||
new SearchCallback() {
|
||||
new SearchApiCallback() {
|
||||
@Override
|
||||
public void onSearchFinished(List<SearchItem> searchItems) {
|
||||
processSearchResult(searchItems);
|
||||
public void onSearchFinished(List<SearchObject> searchObjects) {
|
||||
processSearchResult(searchObjects);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processSearchResult(List<SearchItem> searchItems) {
|
||||
if (searchItems != null) {
|
||||
LatLon latLon = Utilities.convert31ToLatLon(target31);
|
||||
double latitude = latLon.getLatitude();
|
||||
double longitude = latLon.getLongitude();
|
||||
private void processSearchResult(List<SearchObject> searchObjects) {
|
||||
if (searchObjects != null) {
|
||||
List<SearchListItem> rows = new ArrayList<>();
|
||||
for (SearchItem item : searchItems) {
|
||||
for (SearchObject item : searchObjects) {
|
||||
SearchListItem listItem =
|
||||
SearchListItem.buildListItem((SampleApplication)getApplication(), item);
|
||||
if (listItem != null) {
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.items.AddressSearchItem;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
public class AddressSearchListItem extends SearchListItem {
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public AddressSearchListItem(SampleApplication app, AddressSearchItem searchItem) {
|
||||
super(app, searchItem);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String localizedName = searchItem.getLocalizedNames().get(MapUtils.LANGUAGE);
|
||||
if (Algorithms.isEmpty(localizedName)) {
|
||||
localizedName = searchItem.getNativeName();
|
||||
}
|
||||
if (!Algorithms.isEmpty(searchItem.getNamePrefix())) {
|
||||
sb.append(searchItem.getNamePrefix());
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(localizedName);
|
||||
if (!Algorithms.isEmpty(searchItem.getNameSuffix())) {
|
||||
sb.append(" ");
|
||||
sb.append(searchItem.getNameSuffix());
|
||||
}
|
||||
|
||||
nameStr = sb.toString();
|
||||
typeStr = searchItem.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return typeStr;
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.items.AmenitySearchItem;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.osm.MapPoiTypes;
|
||||
import net.osmand.osm.PoiCategory;
|
||||
import net.osmand.osm.PoiType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class AmenitySearchListItem extends SearchListItem {
|
||||
|
||||
private Amenity amenity;
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public AmenitySearchListItem(SampleApplication app, AmenitySearchItem searchItem) {
|
||||
super(app, searchItem);
|
||||
amenity = parseAmenity(searchItem);
|
||||
nameStr = amenity.getName(MapUtils.LANGUAGE);
|
||||
typeStr = getTypeStr();
|
||||
}
|
||||
|
||||
private Amenity parseAmenity(AmenitySearchItem searchItem) {
|
||||
|
||||
MapPoiTypes poiTypes = app.getPoiTypes();
|
||||
|
||||
Amenity a = new Amenity();
|
||||
PoiCategory category = poiTypes.getPoiCategoryByName(searchItem.getCategory());
|
||||
a.setType(category);
|
||||
a.setSubType(searchItem.getSubcategory());
|
||||
a.setName(searchItem.getNativeName());
|
||||
for (Entry<String, String> entry : searchItem.getLocalizedNames().entrySet()) {
|
||||
a.setName(entry.getKey(), entry.getValue());
|
||||
}
|
||||
a.setAdditionalInfo(searchItem.getValues());
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
public Amenity getAmenity() {
|
||||
return amenity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
private String getTypeStr() {
|
||||
/*
|
||||
PoiCategory pc = amenity.getType();
|
||||
PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType());
|
||||
String typeStr = amenity.getSubType();
|
||||
if (pt != null) {
|
||||
typeStr = pt.getTranslation();
|
||||
} else if (typeStr != null) {
|
||||
typeStr = Algorithms.capitalizeFirstLetterAndLowercase(typeStr.replace('_', ' '));
|
||||
}
|
||||
return typeStr;
|
||||
*/
|
||||
return Algorithms.capitalizeFirstLetterAndLowercase(amenity.getSubType().replace('_', ' '));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getIcon() {
|
||||
Drawable drawable = null;
|
||||
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
|
||||
if (st != null) {
|
||||
drawable = app.getIconsCache().getIcon(st.getOsmTag() + "_" + st.getOsmValue());
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.CitySearchObject;
|
||||
|
||||
public class CitySearchListItem extends SearchListPositionItem{
|
||||
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public CitySearchListItem(SampleApplication app, CitySearchObject searchItem) {
|
||||
super(app, searchItem);
|
||||
|
||||
nameStr = searchItem.getName(MapUtils.LANGUAGE);
|
||||
typeStr = "City";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return typeStr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import net.osmand.core.jni.Amenity.DecodedCategory;
|
||||
import net.osmand.core.jni.Amenity.DecodedValue;
|
||||
import net.osmand.core.jni.DecodedCategoryList;
|
||||
import net.osmand.core.jni.DecodedValueList;
|
||||
import net.osmand.core.jni.QStringList;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.PoiSearchObject;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.osm.MapPoiTypes;
|
||||
import net.osmand.osm.PoiCategory;
|
||||
import net.osmand.osm.PoiType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PoiSearchListItem extends SearchListPositionItem {
|
||||
|
||||
private Amenity amenity;
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public PoiSearchListItem(SampleApplication app, PoiSearchObject searchItem) {
|
||||
super(app, searchItem);
|
||||
amenity = parseAmenity(searchItem);
|
||||
nameStr = amenity.getName(MapUtils.LANGUAGE);
|
||||
typeStr = getTypeStr();
|
||||
}
|
||||
|
||||
private Amenity parseAmenity(PoiSearchObject searchItem) {
|
||||
|
||||
String categoryName = "";
|
||||
String subcategoryName = "";
|
||||
Map<String, String> values = new HashMap<>();
|
||||
|
||||
net.osmand.core.jni.Amenity coreAmenity = searchItem.getAmenity();
|
||||
DecodedCategoryList catList = coreAmenity.getDecodedCategories();
|
||||
if (catList.size() > 0) {
|
||||
DecodedCategory decodedCategory = catList.get(0);
|
||||
categoryName = decodedCategory.getCategory();
|
||||
subcategoryName = decodedCategory.getSubcategory();
|
||||
}
|
||||
|
||||
DecodedValueList decodedValueList = coreAmenity.getDecodedValues();
|
||||
if (decodedValueList.size() > 0) {
|
||||
for (int i = 0; i < decodedValueList.size(); i++) {
|
||||
DecodedValue decodedValue = decodedValueList.get(i);
|
||||
String tag = decodedValue.getDeclaration().getTagName();
|
||||
String value = decodedValue.getValue();
|
||||
values.put(tag, value);
|
||||
}
|
||||
}
|
||||
|
||||
MapPoiTypes poiTypes = app.getPoiTypes();
|
||||
|
||||
Amenity a = new Amenity();
|
||||
PoiCategory category = poiTypes.getPoiCategoryByName(categoryName);
|
||||
a.setType(category);
|
||||
a.setSubType(subcategoryName);
|
||||
a.setName(searchItem.getNativeName());
|
||||
|
||||
QStringStringHash localizedNamesMap = coreAmenity.getLocalizedNames();
|
||||
QStringList locNamesKeys = localizedNamesMap.keys();
|
||||
for (int i = 0; i < locNamesKeys.size(); i++) {
|
||||
String key = locNamesKeys.get(i);
|
||||
String val = localizedNamesMap.get(key);
|
||||
a.setName(key, val);
|
||||
}
|
||||
|
||||
a.setAdditionalInfo(values);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
public Amenity getAmenity() {
|
||||
return amenity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
private String getTypeStr() {
|
||||
/*
|
||||
PoiCategory pc = amenity.getTypeName();
|
||||
PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType());
|
||||
String typeStr = amenity.getSubType();
|
||||
if (pt != null) {
|
||||
typeStr = pt.getTranslation();
|
||||
} else if (typeStr != null) {
|
||||
typeStr = Algorithms.capitalizeFirstLetterAndLowercase(typeStr.replace('_', ' '));
|
||||
}
|
||||
return typeStr;
|
||||
*/
|
||||
return Algorithms.capitalizeFirstLetterAndLowercase(amenity.getSubType().replace('_', ' '));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getIcon() {
|
||||
Drawable drawable = null;
|
||||
PoiType st = amenity.getType().getPoiTypeByKeyName(amenity.getSubType());
|
||||
if (st != null) {
|
||||
drawable = app.getIconsCache().getIcon(st.getOsmTag() + "_" + st.getOsmValue());
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.CitySearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.PostcodeSearchObject;
|
||||
|
||||
public class PostcodeSearchListItem extends SearchListPositionItem {
|
||||
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public PostcodeSearchListItem(SampleApplication app, PostcodeSearchObject searchItem) {
|
||||
super(app, searchItem);
|
||||
|
||||
nameStr = searchItem.getNativeName();
|
||||
typeStr = "Postcode";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return typeStr;
|
||||
}
|
||||
}
|
|
@ -25,8 +25,11 @@ public class SearchListAdapter extends ArrayAdapter<SearchListItem> {
|
|||
public void updateDistance(double latitude, double longitude) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
SearchListItem item = getItem(i);
|
||||
item.setDistance(Utilities.distance(
|
||||
longitude, latitude, item.getLongitude(), item.getLatitude()));
|
||||
if (item instanceof SearchListPositionItem) {
|
||||
SearchListPositionItem positionItem = (SearchListPositionItem) item;
|
||||
positionItem.setDistance(Utilities.distance(
|
||||
longitude, latitude, positionItem.getLongitude(), positionItem.getLatitude()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,11 +54,17 @@ public class SearchListAdapter extends ArrayAdapter<SearchListItem> {
|
|||
|
||||
imageView.setImageDrawable(listItem.getIcon());
|
||||
title.setText(listItem.getName());
|
||||
subtitle.setText(listItem.getType());
|
||||
if (listItem.getDistance() == 0) {
|
||||
distance.setText("");
|
||||
subtitle.setText(listItem.getTypeName());
|
||||
if (listItem instanceof SearchListPositionItem) {
|
||||
SearchListPositionItem positionItem = (SearchListPositionItem) listItem;
|
||||
if (positionItem.getDistance() == 0) {
|
||||
distance.setText("");
|
||||
} else {
|
||||
distance.setText(Utils.getFormattedDistance(positionItem.getDistance()));
|
||||
}
|
||||
distance.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
distance.setText(Utils.getFormattedDistance(listItem.getDistance()));
|
||||
distance.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
|
|
@ -3,52 +3,49 @@ package net.osmand.core.samples.android.sample1.adapters;
|
|||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
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.objects.CitySearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.PoiSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.PostcodeSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.StreetSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.VillageSearchObject;
|
||||
|
||||
public class SearchListItem {
|
||||
|
||||
protected SampleApplication app;
|
||||
private SearchItem searchItem;
|
||||
private SearchObject searchObject;
|
||||
|
||||
public SearchListItem(SampleApplication app, SearchItem searchItem) {
|
||||
public SearchListItem(SampleApplication app, SearchObject searchObject) {
|
||||
this.app = app;
|
||||
this.searchItem = searchItem;
|
||||
this.searchObject = searchObject;
|
||||
}
|
||||
|
||||
public static SearchListItem buildListItem(SampleApplication app, SearchItem item) {
|
||||
|
||||
if (item instanceof AmenitySearchItem) {
|
||||
return new AmenitySearchListItem(app, (AmenitySearchItem) item);
|
||||
} else if (item instanceof AddressSearchItem) {
|
||||
return new AddressSearchListItem(app, (AddressSearchItem) item);
|
||||
public static SearchListItem buildListItem(SampleApplication app, SearchObject item) {
|
||||
switch (item.getType()) {
|
||||
case POI:
|
||||
return new PoiSearchListItem(app, (PoiSearchObject) item);
|
||||
case STREET:
|
||||
return new StreetSearchListItem(app, (StreetSearchObject) item);
|
||||
case CITY:
|
||||
return new CitySearchListItem(app, (CitySearchObject) item);
|
||||
case VILLAGE:
|
||||
return new VillageSearchListItem(app, (VillageSearchObject) item);
|
||||
case POSTCODE:
|
||||
return new PostcodeSearchListItem(app, (PostcodeSearchObject) item);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return searchItem.getLatitude();
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return searchItem.getLongitude();
|
||||
protected SearchObject getSearchObject() {
|
||||
return searchObject;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return searchItem.getName();
|
||||
return searchObject.getNativeName();
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return searchItem.getType();
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return searchItem.getDistance();
|
||||
}
|
||||
|
||||
public void setDistance(double distance) {
|
||||
searchItem.setDistance(distance);
|
||||
public String getTypeName() {
|
||||
return searchObject.getType().name();
|
||||
}
|
||||
|
||||
public Drawable getIcon() {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import net.osmand.core.jni.LatLon;
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.Utilities;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchPositionObject;
|
||||
|
||||
public class SearchListPositionItem extends SearchListItem {
|
||||
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
|
||||
|
||||
public SearchListPositionItem(SampleApplication app, SearchPositionObject searchObject) {
|
||||
super(app, searchObject);
|
||||
PointI position31 = searchObject.getPosition31();
|
||||
LatLon latLon = Utilities.convert31ToLatLon(position31);
|
||||
latitude = latLon.getLatitude();
|
||||
longitude = latLon.getLongitude();
|
||||
}
|
||||
|
||||
public SearchPositionObject getSearchPositionObject() {
|
||||
return (SearchPositionObject) getSearchObject();
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return getSearchPositionObject().getDistance();
|
||||
}
|
||||
|
||||
public void setDistance(double distance) {
|
||||
getSearchPositionObject().setDistance(distance);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import net.osmand.core.jni.ObfAddressStreetGroupSubtype;
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.StreetSearchObject;
|
||||
|
||||
public class StreetSearchListItem extends SearchListItem {
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public StreetSearchListItem(SampleApplication app, StreetSearchObject searchItem) {
|
||||
super(app, searchItem);
|
||||
|
||||
nameStr = searchItem.getName(MapUtils.LANGUAGE);
|
||||
|
||||
StreetGroup streetGroup = searchItem.getStreet().getStreetGroup();
|
||||
if (streetGroup != null) {
|
||||
typeStr = streetGroup.getNativeName() + " — " + getTypeStr(streetGroup);
|
||||
} else {
|
||||
typeStr = "Street";
|
||||
}
|
||||
}
|
||||
|
||||
private String getTypeStr(StreetGroup streetGroup) {
|
||||
String typeStr;
|
||||
if (streetGroup.getSubtype() != ObfAddressStreetGroupSubtype.Unknown) {
|
||||
typeStr = streetGroup.getSubtype().name();
|
||||
} else {
|
||||
typeStr = streetGroup.getType().name();
|
||||
}
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return typeStr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.osmand.core.samples.android.sample1.adapters;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.MapUtils;
|
||||
import net.osmand.core.samples.android.sample1.SampleApplication;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.CitySearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.VillageSearchObject;
|
||||
|
||||
public class VillageSearchListItem extends SearchListPositionItem{
|
||||
|
||||
private String nameStr;
|
||||
private String typeStr;
|
||||
|
||||
public VillageSearchListItem(SampleApplication app, VillageSearchObject searchItem) {
|
||||
super(app, searchItem);
|
||||
|
||||
nameStr = searchItem.getName(MapUtils.LANGUAGE);
|
||||
typeStr = "Village";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return typeStr;
|
||||
}
|
||||
}
|
|
@ -5,11 +5,13 @@ import android.support.annotation.NonNull;
|
|||
import net.osmand.core.jni.AreaI;
|
||||
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.objects.SearchObject;
|
||||
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 net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchAPI {
|
||||
|
@ -17,23 +19,44 @@ public class SearchAPI {
|
|||
private ObfsCollection obfsCollection;
|
||||
private AreaI searchableArea;
|
||||
private AreaI obfAreaFilter;
|
||||
private PointI searchLocation;
|
||||
private PointI searchLocation31;
|
||||
private double searchRadius;
|
||||
private String lang;
|
||||
|
||||
private SearchRequestExecutor executor;
|
||||
private SearchString searchString;
|
||||
private SearchScope searchScope;
|
||||
private List<SearchItem> searchItems;
|
||||
private List<SearchObject> searchObjects;
|
||||
|
||||
public interface SearchCallback {
|
||||
void onSearchFinished(List<SearchItem> searchItems);
|
||||
private SearchCallbackInternal internalCallback = new SearchCallbackInternal() {
|
||||
@Override
|
||||
public void onSearchObjectsFound(List<SearchObject> searchObjects) {
|
||||
setSearchObjects(searchObjects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTokenFound(SearchToken oldToken, SearchToken newToken) {
|
||||
searchString.replaceToken(oldToken, newToken);
|
||||
}
|
||||
};
|
||||
|
||||
public interface SearchApiCallback {
|
||||
void onSearchFinished(List<SearchObject> searchObjects);
|
||||
}
|
||||
|
||||
public SearchAPI(@NonNull ObfsCollection obfsCollection) {
|
||||
public interface SearchCallbackInternal {
|
||||
void onSearchObjectsFound(List<SearchObject> searchObjects);
|
||||
void onNewTokenFound(SearchToken oldToken, SearchToken newToken);
|
||||
}
|
||||
|
||||
public SearchAPI(@NonNull ObfsCollection obfsCollection, String lang) {
|
||||
this.obfsCollection = obfsCollection;
|
||||
this.executor = new SearchRequestExecutor();
|
||||
this.searchString = new SearchString();
|
||||
this.searchScope = new SearchScope(this);
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public AreaI getSearchableArea() {
|
||||
|
@ -52,12 +75,12 @@ public class SearchAPI {
|
|||
this.obfAreaFilter = obfAreaFilter;
|
||||
}
|
||||
|
||||
public PointI getSearchLocation() {
|
||||
return searchLocation;
|
||||
public PointI getSearchLocation31() {
|
||||
return searchLocation31;
|
||||
}
|
||||
|
||||
public void setSearchLocation(PointI searchLocation) {
|
||||
this.searchLocation = searchLocation;
|
||||
public void setSearchLocation31(PointI position31) {
|
||||
this.searchLocation31 = position31;
|
||||
}
|
||||
|
||||
public double getSearchRadius() {
|
||||
|
@ -72,35 +95,32 @@ public class SearchAPI {
|
|||
return obfsCollection;
|
||||
}
|
||||
|
||||
public SearchString getSearchString() {
|
||||
return searchString;
|
||||
public SearchString getSearchStringCopy() {
|
||||
return searchString.copy();
|
||||
}
|
||||
|
||||
public SearchScope getSearchScope() {
|
||||
return searchScope;
|
||||
public List<SearchObject> getSearchObjects() {
|
||||
return searchObjects;
|
||||
}
|
||||
|
||||
public List<SearchItem> getSearchItems() {
|
||||
return searchItems;
|
||||
}
|
||||
|
||||
public void setSearchItems(List<SearchItem> searchItems) {
|
||||
this.searchItems = searchItems;
|
||||
public void setSearchObjects(List<SearchObject> searchObjects) {
|
||||
this.searchObjects = searchObjects;
|
||||
}
|
||||
|
||||
public void startSearch(String query, int maxSearchResults,
|
||||
SearchCallback intermediateSearchCallback,
|
||||
SearchCallback coreSearchCallback) {
|
||||
SearchApiCallback intermediateSearchCallback,
|
||||
SearchApiCallback coreSearchCallback) {
|
||||
|
||||
searchString.setQueryText(query);
|
||||
searchScope.updateScope();
|
||||
SearchScope searchScope = new SearchScope(this);
|
||||
IntermediateSearchRequest intermediateSearchRequest = null;
|
||||
if (searchItems != null && !searchItems.isEmpty()) {
|
||||
if (searchObjects != null && !searchObjects.isEmpty()) {
|
||||
intermediateSearchRequest =
|
||||
new IntermediateSearchRequest(this, maxSearchResults, intermediateSearchCallback);
|
||||
new IntermediateSearchRequest(searchScope, new ArrayList<>(searchObjects),
|
||||
maxSearchResults, intermediateSearchCallback);
|
||||
}
|
||||
executor.run(new CoreSearchRequest(intermediateSearchRequest, this,
|
||||
maxSearchResults, coreSearchCallback), true);
|
||||
executor.run(new CoreSearchRequest(intermediateSearchRequest, searchScope,
|
||||
maxSearchResults, coreSearchCallback, internalCallback), true);
|
||||
}
|
||||
|
||||
public void cancelSearch() {
|
||||
|
|
|
@ -2,117 +2,190 @@ 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.AreaI;
|
||||
import net.osmand.core.jni.ObfAddressStreetGroupSubtype;
|
||||
import net.osmand.core.jni.ObfAddressStreetGroupType;
|
||||
import net.osmand.core.jni.ObfsCollection;
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.Street;
|
||||
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.objects.PoiSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject.SearchObjectType;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchPositionObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.StreetGroupSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.StreetSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.tokens.ObjectSearchToken;
|
||||
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.Collections;
|
||||
import java.util.Comparator;
|
||||
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 ObfsCollection obfsCollection;
|
||||
private SearchString searchString;
|
||||
private String lang;
|
||||
private Map<SearchObjectType, SearchToken> objectTokens;
|
||||
private PointI searchLocation31;
|
||||
private AreaI searchableArea;
|
||||
private AreaI obfAreaFilter;
|
||||
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();
|
||||
obfsCollection = searchAPI.getObfsCollection();
|
||||
lang = searchAPI.getLang();
|
||||
searchString = searchAPI.getSearchStringCopy();
|
||||
objectTokens = searchString.getObjectTokens();
|
||||
searchLocation31 = searchAPI.getSearchLocation31();
|
||||
searchableArea = searchAPI.getSearchableArea();
|
||||
obfAreaFilter = searchAPI.getObfAreaFilter();
|
||||
searchRadius = searchAPI.getSearchRadius();
|
||||
}
|
||||
|
||||
public ObfsCollection getObfsCollection() {
|
||||
return obfsCollection;
|
||||
}
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public SearchString getSearchString() {
|
||||
return searchString;
|
||||
}
|
||||
|
||||
public Map<SearchObjectType, SearchToken> getObjectTokens() {
|
||||
return objectTokens;
|
||||
}
|
||||
|
||||
public PointI getSearchLocation31() {
|
||||
return searchLocation31;
|
||||
}
|
||||
|
||||
public AreaI getSearchableArea() {
|
||||
return searchableArea;
|
||||
}
|
||||
|
||||
public AreaI getObfAreaFilter() {
|
||||
return obfAreaFilter;
|
||||
}
|
||||
|
||||
public double getSearchRadius() {
|
||||
return searchRadius;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
//todo criteria.setCategoriesFilter() if needed;
|
||||
}
|
||||
|
||||
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 processPoiSearchObject(PoiSearchObject poiSearchObject) {
|
||||
updateDistance(poiSearchObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
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 boolean processAddressSearchObject(SearchPositionObject addressSearchObject) {
|
||||
updateDistance(addressSearchObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
public SearchToken processSearchResult(SearchToken token, List<SearchObject> searchObjects) {
|
||||
|
||||
SearchToken newToken = null;
|
||||
|
||||
boolean cityVillagePostcodeSelected = objectTokens.containsKey(SearchObjectType.CITY)
|
||||
|| objectTokens.containsKey(SearchObjectType.VILLAGE)
|
||||
|| objectTokens.containsKey(SearchObjectType.POSTCODE);
|
||||
|
||||
for (SearchObject searchObject : searchObjects) {
|
||||
float priority = 0f;
|
||||
boolean sortByName = false;
|
||||
switch (searchObject.getType()) {
|
||||
case POI:
|
||||
priority = getPriorityByDistance(10, ((PoiSearchObject) searchObject).getDistance());
|
||||
break;
|
||||
case CITY:
|
||||
case VILLAGE:
|
||||
case POSTCODE:
|
||||
float cityType = getCityType((StreetGroupSearchObject) searchObject);
|
||||
priority = (getPriorityByDistance(cityVillagePostcodeSelected
|
||||
? 20f : 7f + cityType, ((StreetGroupSearchObject) searchObject).getDistance()));
|
||||
break;
|
||||
|
||||
case STREET:
|
||||
StreetSearchObject streetSearchObject = (StreetSearchObject) searchObject;
|
||||
Street street = streetSearchObject.getStreet();
|
||||
if (!cityVillagePostcodeSelected) {
|
||||
priority = getPriorityByDistance(9f, streetSearchObject.getDistance());
|
||||
} else {
|
||||
boolean streetFromSelectedCity = false;
|
||||
for (SearchToken st : objectTokens.values()) {
|
||||
if (st.getSearchObject() instanceof StreetGroupSearchObject) {
|
||||
StreetGroupSearchObject streetGroupSearchObject = (StreetGroupSearchObject) st.getSearchObject();
|
||||
if (streetGroupSearchObject.getStreetGroup().getId().getId()
|
||||
.equals(street.getStreetGroup().getId().getId())) {
|
||||
streetFromSelectedCity = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (streetFromSelectedCity) {
|
||||
priority = 3f;
|
||||
sortByName = true;
|
||||
} else {
|
||||
priority = getPriorityByDistance(9f, streetSearchObject.getDistance());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
*/
|
||||
searchObject.setPriority(priority);
|
||||
searchObject.setSortByName(sortByName);
|
||||
}
|
||||
|
||||
//todo
|
||||
if (searchObjects.size() > 0) {
|
||||
Collections.sort(searchObjects, new Comparator<SearchObject>() {
|
||||
@Override
|
||||
public int compare(SearchObject lhs, SearchObject rhs) {
|
||||
int res = Double.compare(lhs.getPriority(), rhs.getPriority());
|
||||
if (res == 0 && lhs.isSortByName() && rhs.isSortByName()) {
|
||||
return lhs.getName(lang).compareToIgnoreCase(rhs.getName(lang));
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (token.getType() == SearchToken.TokenType.NAME_FILTER
|
||||
&& !Algorithms.isEmpty(token.getQueryText())) {
|
||||
newToken = new ObjectSearchToken(token, searchObjects.get(0));
|
||||
}
|
||||
}
|
||||
return newToken;
|
||||
}
|
||||
|
||||
private void updateDistance(SearchItem item) {
|
||||
item.setDistance(Utilities.distance(
|
||||
searchLon, searchLat, item.getLongitude(), item.getLatitude()));
|
||||
private float getCityType(StreetGroupSearchObject searchObject) {
|
||||
if (searchObject.getStreetGroup().getType() == ObfAddressStreetGroupType.CityOrTown) {
|
||||
if (searchObject.getStreetGroup().getSubtype() == ObfAddressStreetGroupSubtype.City) {
|
||||
return 1f;
|
||||
} else if (searchObject.getStreetGroup().getSubtype() == ObfAddressStreetGroupSubtype.Town) {
|
||||
return 1.5f;
|
||||
}
|
||||
}
|
||||
return 2.5f;
|
||||
}
|
||||
|
||||
private float getPriorityByDistance(float priority, double distance) {
|
||||
return priority + (float)(1 / (1 + distance));
|
||||
}
|
||||
|
||||
private void updateDistance(SearchPositionObject item) {
|
||||
item.setDistance(Utilities.distance31(searchLocation31, item.getPosition31()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package net.osmand.core.samples.android.sample1.search;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject.SearchObjectType;
|
||||
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 net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -17,11 +19,18 @@ public class SearchString {
|
|||
public SearchString() {
|
||||
}
|
||||
|
||||
public SearchString copy() {
|
||||
SearchString res = new SearchString();
|
||||
res.queryText = queryText;
|
||||
res.tokens = new ArrayList<>(tokens);
|
||||
return res;
|
||||
}
|
||||
|
||||
public String getQueryText() {
|
||||
return queryText;
|
||||
}
|
||||
|
||||
public synchronized void setQueryText(String queryText) {
|
||||
public void setQueryText(String queryText) {
|
||||
int newTextLength = queryText.length();
|
||||
int currTextLength = this.queryText.length();
|
||||
boolean isNewText = currTextLength == 0
|
||||
|
@ -73,12 +82,19 @@ public class SearchString {
|
|||
if (firstWordIndex <= newTextLength - 1) {
|
||||
SearchToken token = new NameFilterSearchToken(firstWordIndex, queryText.substring(firstWordIndex));
|
||||
tokens.add(token);
|
||||
} else if (endWithDelimeter(queryText)) {
|
||||
SearchToken token = new NameFilterSearchToken(firstWordIndex, "");
|
||||
tokens.add(token);
|
||||
}
|
||||
}
|
||||
|
||||
this.queryText = queryText;
|
||||
}
|
||||
|
||||
private boolean endWithDelimeter(String text) {
|
||||
return !Algorithms.isEmpty(text) && isDelimiterChar(text.charAt(text.length() - 1));
|
||||
}
|
||||
|
||||
private boolean startWithDelimiter(String text) {
|
||||
char firstChar = text.charAt(0);
|
||||
return isDelimiterChar(firstChar);
|
||||
|
@ -88,7 +104,7 @@ public class SearchString {
|
|||
return c == ',' || c == ' ';
|
||||
}
|
||||
|
||||
public synchronized SearchToken getNextNameFilterToken() {
|
||||
public SearchToken getNextNameFilterToken() {
|
||||
SearchToken res = null;
|
||||
if (!tokens.isEmpty()) {
|
||||
for (int i = tokens.size() - 1; i >= 0; i--) {
|
||||
|
@ -103,18 +119,18 @@ public class SearchString {
|
|||
return res;
|
||||
}
|
||||
|
||||
public synchronized SearchToken getLastToken() {
|
||||
public SearchToken getLastToken() {
|
||||
if (!tokens.isEmpty()) {
|
||||
return tokens.get(tokens.size() - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized boolean hasNameFilterTokens() {
|
||||
public boolean hasNameFilterTokens() {
|
||||
return getNextNameFilterToken() != null;
|
||||
}
|
||||
|
||||
public synchronized boolean replaceToken(SearchToken oldToken, SearchToken newToken) {
|
||||
public boolean replaceToken(SearchToken oldToken, SearchToken newToken) {
|
||||
int index = tokens.indexOf(oldToken);
|
||||
if (index != -1) {
|
||||
tokens.set(index, newToken);
|
||||
|
@ -123,11 +139,11 @@ public class SearchString {
|
|||
return false;
|
||||
}
|
||||
|
||||
public synchronized Map<TokenType, SearchToken> getResolvedTokens() {
|
||||
Map<TokenType, SearchToken> map = new HashMap<>();
|
||||
public Map<SearchObjectType, SearchToken> getObjectTokens() {
|
||||
Map<SearchObjectType, SearchToken> map = new HashMap<>();
|
||||
for (SearchToken token : tokens) {
|
||||
if (token.getType() != SearchToken.TokenType.NAME_FILTER) {
|
||||
map.put(token.getType(), token);
|
||||
if (token.getType() == TokenType.SEARCH_OBJECT) {
|
||||
map.put(token.getSearchObject().getType(), token);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
package net.osmand.core.samples.android.sample1.search.items;
|
||||
|
||||
import net.osmand.core.jni.Address;
|
||||
import net.osmand.core.jni.ObfAddressStreetGroupSubtype;
|
||||
import net.osmand.core.jni.ObfAddressStreetGroupType;
|
||||
import net.osmand.core.jni.Street;
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class AddressSearchItem extends SearchItem {
|
||||
|
||||
private String namePrefix;
|
||||
private String nameSuffix;
|
||||
private String typeStr;
|
||||
|
||||
private BigInteger parentCityObfId;
|
||||
private BigInteger parentPostcodeObfId;
|
||||
|
||||
public AddressSearchItem(Address address) {
|
||||
super();
|
||||
|
||||
switch (address.getAddressType()) {
|
||||
case Street:
|
||||
StreetInternal street = new StreetInternal(address);
|
||||
setLocation(street.getPosition31());
|
||||
setNativeName(street.getNativeName());
|
||||
addLocalizedNames(street.getLocalizedNames());
|
||||
if (street.getStreetGroup() != null) {
|
||||
StreetGroup streetGroup = street.getStreetGroup();
|
||||
nameSuffix = "st.";
|
||||
typeStr = streetGroup.getNativeName() + " — " + getTypeStr(streetGroup);
|
||||
if (streetGroup.getType() == ObfAddressStreetGroupType.Postcode) {
|
||||
parentPostcodeObfId = streetGroup.getId().getId();
|
||||
} else {
|
||||
parentCityObfId = streetGroup.getId().getId();
|
||||
}
|
||||
} else {
|
||||
typeStr = "Street";
|
||||
}
|
||||
break;
|
||||
|
||||
case StreetGroup:
|
||||
StreetGroupInternal streetGroup = new StreetGroupInternal(address);
|
||||
setLocation(streetGroup.getPosition31());
|
||||
setNativeName(streetGroup.getNativeName());
|
||||
addLocalizedNames(streetGroup.getLocalizedNames());
|
||||
typeStr = getTypeStr(streetGroup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public String getNamePrefix() {
|
||||
return namePrefix;
|
||||
}
|
||||
|
||||
public String getNameSuffix() {
|
||||
return nameSuffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!Algorithms.isEmpty(namePrefix)) {
|
||||
sb.append(namePrefix);
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(super.getName());
|
||||
if (!Algorithms.isEmpty(nameSuffix)) {
|
||||
sb.append(" ");
|
||||
sb.append(nameSuffix);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
private String getTypeStr(StreetGroup streetGroup) {
|
||||
String typeStr;
|
||||
if (streetGroup.getSubtype() != ObfAddressStreetGroupSubtype.Unknown) {
|
||||
typeStr = streetGroup.getSubtype().name();
|
||||
} else {
|
||||
typeStr = streetGroup.getType().name();
|
||||
}
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
public BigInteger getParentCityObfId() {
|
||||
return parentCityObfId;
|
||||
}
|
||||
|
||||
public BigInteger getParentPostcodeObfId() {
|
||||
return parentPostcodeObfId;
|
||||
}
|
||||
|
||||
private class StreetInternal extends Street {
|
||||
public StreetInternal(Address address) {
|
||||
super(Address.getCPtr(address), false);
|
||||
}
|
||||
}
|
||||
|
||||
private class StreetGroupInternal extends StreetGroup {
|
||||
public StreetGroupInternal(Address address) {
|
||||
super(Address.getCPtr(address), false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package net.osmand.core.samples.android.sample1.search.items;
|
||||
|
||||
import net.osmand.core.jni.Amenity;
|
||||
import net.osmand.core.jni.DecodedCategoryList;
|
||||
import net.osmand.core.jni.DecodedValueList;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AmenitySearchItem extends SearchItem {
|
||||
|
||||
private String category;
|
||||
private String subcategory;
|
||||
private Map<String, String> values = new HashMap<>();
|
||||
|
||||
public AmenitySearchItem(Amenity amenity) {
|
||||
super(amenity.getPosition31());
|
||||
|
||||
setNativeName(amenity.getNativeName());
|
||||
addLocalizedNames(amenity.getLocalizedNames());
|
||||
|
||||
DecodedCategoryList catList = amenity.getDecodedCategories();
|
||||
if (catList.size() > 0) {
|
||||
Amenity.DecodedCategory decodedCategory = catList.get(0);
|
||||
category = decodedCategory.getCategory();
|
||||
subcategory = decodedCategory.getSubcategory();
|
||||
}
|
||||
|
||||
DecodedValueList decodedValueList = amenity.getDecodedValues();
|
||||
if (decodedValueList.size() > 0) {
|
||||
for (int i = 0; i < decodedValueList.size(); i++) {
|
||||
Amenity.DecodedValue decodedValue = decodedValueList.get(i);
|
||||
String tag = decodedValue.getDeclaration().getTagName();
|
||||
String value = decodedValue.getValue();
|
||||
values.put(tag, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public String getSubcategory() {
|
||||
return subcategory;
|
||||
}
|
||||
|
||||
public Map<String, String> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return Algorithms.capitalizeFirstLetterAndLowercase(subcategory);
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
package net.osmand.core.samples.android.sample1.search.items;
|
||||
|
||||
import net.osmand.core.jni.LatLon;
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringList;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
import net.osmand.core.jni.Utilities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class SearchItem {
|
||||
|
||||
protected double latitude;
|
||||
protected double longitude;
|
||||
protected String nativeName;
|
||||
protected Map<String, String> localizedNames = new HashMap<>();
|
||||
|
||||
private double distance;
|
||||
private float priority;
|
||||
|
||||
protected SearchItem() {
|
||||
}
|
||||
|
||||
protected SearchItem(double latitude, double longitude) {
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
protected SearchItem(PointI location31) {
|
||||
LatLon latLon = Utilities.convert31ToLatLon(location31);
|
||||
latitude = latLon.getLatitude();
|
||||
longitude = latLon.getLongitude();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return nativeName;
|
||||
}
|
||||
|
||||
public abstract String getType();
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public String getNativeName() {
|
||||
return nativeName;
|
||||
}
|
||||
|
||||
public Map<String, String> getLocalizedNames() {
|
||||
return localizedNames;
|
||||
}
|
||||
|
||||
protected void setLocation(PointI location31) {
|
||||
LatLon latLon = Utilities.convert31ToLatLon(location31);
|
||||
latitude = latLon.getLatitude();
|
||||
longitude = latLon.getLongitude();
|
||||
}
|
||||
|
||||
protected void setNativeName(String nativeName) {
|
||||
this.nativeName = nativeName;
|
||||
}
|
||||
|
||||
protected void addLocalizedNames(QStringStringHash localizedNames) {
|
||||
QStringList locNamesKeys = localizedNames.keys();
|
||||
for (int i = 0; i < locNamesKeys.size(); i++) {
|
||||
String key = locNamesKeys.get(i);
|
||||
String val = localizedNames.get(key);
|
||||
this.localizedNames.put(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
public String toString() {
|
||||
return getName() + " (" + getType() + ") {lat:" + getLatitude() + " lon: " + getLongitude() + "}";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
|
||||
public class CitySearchObject extends StreetGroupSearchObject {
|
||||
|
||||
public CitySearchObject(StreetGroup streetGroup) {
|
||||
super(SearchObjectType.CITY, streetGroup);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
|
||||
public class CoordinatesSearchObject extends SearchPositionObject {
|
||||
|
||||
public CoordinatesSearchObject(PointI position31) {
|
||||
super(SearchObjectType.COORDINATES, position31);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointI getPosition31() {
|
||||
return (PointI) getInternalObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNativeName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QStringStringHash getLocalizedNames() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.Amenity;
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
|
||||
public class PoiSearchObject extends SearchPositionObject {
|
||||
|
||||
public PoiSearchObject(Amenity amenity) {
|
||||
super(SearchObjectType.POI, amenity);
|
||||
}
|
||||
|
||||
public Amenity getAmenity() {
|
||||
return (Amenity) getInternalObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointI getPosition31() {
|
||||
return getAmenity().getPosition31();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNativeName() {
|
||||
return getAmenity().getNativeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QStringStringHash getLocalizedNames() {
|
||||
return getAmenity().getLocalizedNames();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
|
||||
public class PostcodeSearchObject extends StreetGroupSearchObject {
|
||||
|
||||
public PostcodeSearchObject(StreetGroup streetGroup) {
|
||||
super(SearchObjectType.POSTCODE, streetGroup);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
|
||||
public abstract class SearchObject {
|
||||
|
||||
public enum SearchObjectType {
|
||||
CITY,
|
||||
VILLAGE,
|
||||
POSTCODE,
|
||||
STREET,
|
||||
BUILDING,
|
||||
POI_TYPE,
|
||||
POI_FILTER,
|
||||
POI,
|
||||
COORDINATES
|
||||
}
|
||||
|
||||
private SearchObjectType type;
|
||||
private Object internalObject;
|
||||
|
||||
private float priority;
|
||||
private boolean sortByName;
|
||||
|
||||
protected SearchObject(SearchObjectType type, Object internalObject) {
|
||||
this.type = type;
|
||||
this.internalObject = internalObject;
|
||||
}
|
||||
|
||||
public SearchObjectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
protected Object getInternalObject() {
|
||||
return internalObject;
|
||||
}
|
||||
|
||||
public abstract String getNativeName();
|
||||
|
||||
public String getName(String lang) {
|
||||
QStringStringHash locNames = getLocalizedNames();
|
||||
if (locNames != null && lang != null) {
|
||||
String locName = null;
|
||||
if (locNames.has_key(lang)) {
|
||||
locName = locNames.get(lang);
|
||||
}
|
||||
return locName == null ? getNativeName() : locName;
|
||||
} else {
|
||||
return getNativeName();
|
||||
}
|
||||
}
|
||||
|
||||
public String getNameEn() {
|
||||
QStringStringHash locNames = getLocalizedNames();
|
||||
if (locNames != null && locNames.has_key("en")) {
|
||||
return locNames.get("en");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public float getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(float priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public boolean isSortByName() {
|
||||
return sortByName;
|
||||
}
|
||||
|
||||
public void setSortByName(boolean sortByName) {
|
||||
this.sortByName = sortByName;
|
||||
}
|
||||
|
||||
protected abstract QStringStringHash getLocalizedNames();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SearchObject: " + getNativeName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.Address;
|
||||
import net.osmand.core.jni.Street;
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
|
||||
public class SearchObjectsHelper {
|
||||
|
||||
public static SearchPositionObject getAddressObject(Address address) {
|
||||
|
||||
switch (address.getAddressType()) {
|
||||
case Street:
|
||||
StreetInternal street = new StreetInternal(address);
|
||||
return new StreetSearchObject(street);
|
||||
|
||||
case StreetGroup:
|
||||
StreetGroupInternal streetGroup = new StreetGroupInternal(address);
|
||||
switch (streetGroup.getType()) {
|
||||
case CityOrTown:
|
||||
return new CitySearchObject(streetGroup);
|
||||
case Village:
|
||||
return new VillageSearchObject(streetGroup);
|
||||
case Postcode:
|
||||
return new PostcodeSearchObject(streetGroup);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class StreetInternal extends Street {
|
||||
public StreetInternal(Address address) {
|
||||
super(Address.getCPtr(address), false);
|
||||
}
|
||||
}
|
||||
|
||||
private static class StreetGroupInternal extends StreetGroup {
|
||||
public StreetGroupInternal(Address address) {
|
||||
super(Address.getCPtr(address), false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.PointI;
|
||||
|
||||
public abstract class SearchPositionObject extends SearchObject {
|
||||
|
||||
private double distance;
|
||||
|
||||
public SearchPositionObject(SearchObjectType type, Object internalObject) {
|
||||
super(type, internalObject);
|
||||
}
|
||||
|
||||
public abstract PointI getPosition31();
|
||||
|
||||
public double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(double distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SearchPositionObject: " + getNativeName()
|
||||
+ " {x31:" + getPosition31().getX() + " y31: " + getPosition31().getY() + "}";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
|
||||
public abstract class StreetGroupSearchObject extends SearchPositionObject {
|
||||
|
||||
public StreetGroupSearchObject(SearchObjectType type, StreetGroup streetGroup) {
|
||||
super(type, streetGroup);
|
||||
}
|
||||
|
||||
public StreetGroup getStreetGroup() {
|
||||
return (StreetGroup) getInternalObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointI getPosition31() {
|
||||
return getStreetGroup().getPosition31();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNativeName() {
|
||||
return getStreetGroup().getNativeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QStringStringHash getLocalizedNames() {
|
||||
return getStreetGroup().getLocalizedNames();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
import net.osmand.core.jni.Street;
|
||||
|
||||
public class StreetSearchObject extends SearchPositionObject {
|
||||
|
||||
public StreetSearchObject(Street street) {
|
||||
super(SearchObjectType.STREET, street);
|
||||
}
|
||||
|
||||
public Street getStreet() {
|
||||
return (Street) getInternalObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointI getPosition31() {
|
||||
return getStreet().getPosition31();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNativeName() {
|
||||
return getStreet().getNativeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QStringStringHash getLocalizedNames() {
|
||||
return getStreet().getLocalizedNames();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.osmand.core.samples.android.sample1.search.objects;
|
||||
|
||||
import net.osmand.core.jni.PointI;
|
||||
import net.osmand.core.jni.QStringStringHash;
|
||||
import net.osmand.core.jni.StreetGroup;
|
||||
|
||||
public class VillageSearchObject extends StreetGroupSearchObject {
|
||||
|
||||
public VillageSearchObject(StreetGroup streetGroup) {
|
||||
super(SearchObjectType.VILLAGE, streetGroup);
|
||||
}
|
||||
}
|
|
@ -10,12 +10,16 @@ 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.SearchAPI.SearchApiCallback;
|
||||
import net.osmand.core.samples.android.sample1.search.SearchAPI.SearchCallbackInternal;
|
||||
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.objects.PoiSearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObjectsHelper;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchPositionObject;
|
||||
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -24,14 +28,18 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
|
||||
private IntermediateSearchRequest intermediateSearchRequest;
|
||||
private boolean intermediateSearchDone;
|
||||
private SearchCallbackInternal internalCallback;
|
||||
|
||||
private int amenityResultsCounter;
|
||||
private int addressResultsCounter;
|
||||
|
||||
public CoreSearchRequest(@Nullable IntermediateSearchRequest intermediateSearchRequest,
|
||||
@NonNull SearchAPI searchAPI, int maxSearchResults, @Nullable SearchCallback searchCallback) {
|
||||
super(searchAPI, maxSearchResults, searchCallback);
|
||||
@NonNull SearchScope searchScope, int maxSearchResults,
|
||||
@Nullable SearchApiCallback searchCallback,
|
||||
@Nullable SearchCallbackInternal internalCallback) {
|
||||
super(searchScope, maxSearchResults, searchCallback);
|
||||
this.intermediateSearchRequest = intermediateSearchRequest;
|
||||
this.internalCallback = internalCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,11 +59,13 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onSearchRequestPostExecute(List<SearchItem> searchItems) {
|
||||
protected void onSearchRequestPostExecute(List<SearchObject> searchObjects) {
|
||||
if (intermediateSearchRequest != null && !intermediateSearchDone) {
|
||||
intermediateSearchRequest.cancel();
|
||||
}
|
||||
searchAPI.setSearchItems(searchItems);
|
||||
if (internalCallback != null) {
|
||||
internalCallback.onSearchObjectsFound(searchObjects);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,37 +77,42 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<SearchItem> doSearch() {
|
||||
protected List<SearchObject> doSearch() {
|
||||
|
||||
List<SearchItem> res = new ArrayList<>();
|
||||
List<SearchObject> res = new ArrayList<>();
|
||||
|
||||
SearchString searchString = searchScope.getSearchString();
|
||||
SearchToken lastToken = searchString.getLastToken();
|
||||
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);
|
||||
if (token.getType() == SearchToken.TokenType.NAME_FILTER
|
||||
&& !Algorithms.isEmpty(token.getQueryText())) {
|
||||
res = doCoreSearch(token);
|
||||
}
|
||||
if (token != lastToken) {
|
||||
token = searchString.getNextNameFilterToken();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
token = searchString.getNextNameFilterToken();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private List<SearchItem> doCoreSearch(@NonNull SearchToken token) {
|
||||
private List<SearchObject> doCoreSearch(@NonNull SearchToken token) {
|
||||
System.out.println("=== Start search");
|
||||
amenityResultsCounter = 0;
|
||||
addressResultsCounter = 0;
|
||||
|
||||
String keyword = token.getQueryText();
|
||||
final List<SearchItem> searchItems = new ArrayList<>();
|
||||
final List<SearchObject> searchObjects = new ArrayList<>();
|
||||
|
||||
// Setup Amenities by name search
|
||||
AmenitiesByNameSearch amByNameSearch = new AmenitiesByNameSearch(searchAPI.getObfsCollection());
|
||||
AmenitiesByNameSearch amByNameSearch = new AmenitiesByNameSearch(searchScope.getObfsCollection());
|
||||
AmenitiesByNameSearch.Criteria amenityByNameCriteria = new AmenitiesByNameSearch.Criteria();
|
||||
amenityByNameCriteria.setName(keyword);
|
||||
if (searchAPI.getObfAreaFilter() != null) {
|
||||
amenityByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(searchAPI.getObfAreaFilter()));
|
||||
if (searchScope.getObfAreaFilter() != null) {
|
||||
amenityByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(searchScope.getObfAreaFilter()));
|
||||
}
|
||||
searchScope.setupAmenitySearchCriteria(amenityByNameCriteria);
|
||||
|
||||
|
@ -105,9 +120,9 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
@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);
|
||||
PoiSearchObject amenitySearchItem = new PoiSearchObject(amenity);
|
||||
if (searchScope.processPoiSearchObject(amenitySearchItem)) {
|
||||
searchObjects.add(amenitySearchItem);
|
||||
}
|
||||
System.out.println("Poi found === " + amenitySearchItem.toString());
|
||||
amenityResultsCounter++;
|
||||
|
@ -115,11 +130,11 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
};
|
||||
|
||||
// Setup Addresses by name search
|
||||
AddressesByNameSearch addrByNameSearch = new AddressesByNameSearch(searchAPI.getObfsCollection());
|
||||
AddressesByNameSearch.Criteria addrByNameCriteria = new AddressesByNameSearch.Criteria();
|
||||
AddressesByNameSearch addrByNameSearch = new AddressesByNameSearch(searchScope.getObfsCollection());
|
||||
final AddressesByNameSearch.Criteria addrByNameCriteria = new AddressesByNameSearch.Criteria();
|
||||
addrByNameCriteria.setName(keyword);
|
||||
if (searchAPI.getObfAreaFilter() != null) {
|
||||
addrByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(searchAPI.getObfAreaFilter()));
|
||||
if (searchScope.getObfAreaFilter() != null) {
|
||||
addrByNameCriteria.setObfInfoAreaFilter(new NullableAreaI(searchScope.getObfAreaFilter()));
|
||||
}
|
||||
searchScope.setupAddressSearchCriteria(addrByNameCriteria);
|
||||
|
||||
|
@ -127,12 +142,14 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
@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);
|
||||
SearchPositionObject addressSearchObject = SearchObjectsHelper.getAddressObject(address);
|
||||
if (addressSearchObject != null) {
|
||||
if (searchScope.processAddressSearchObject(addressSearchObject)) {
|
||||
searchObjects.add(addressSearchObject);
|
||||
}
|
||||
System.out.println("Address found === " + addressSearchObject.toString());
|
||||
addressResultsCounter++;
|
||||
}
|
||||
System.out.println("Address found === " + addrSearchItem.toString());
|
||||
addressResultsCounter++;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -153,12 +170,15 @@ public class CoreSearchRequest extends SearchRequest {
|
|||
}
|
||||
|
||||
if (!cancelled) {
|
||||
searchScope.processSearchResult(searchItems);
|
||||
SearchToken newToken = searchScope.processSearchResult(token, searchObjects);
|
||||
if (newToken != null && internalCallback != null) {
|
||||
internalCallback.onNewTokenFound(token, newToken);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("=== Finish search");
|
||||
|
||||
return searchItems;
|
||||
return searchObjects;
|
||||
}
|
||||
|
||||
private class AmenityResultEntry extends AmenitiesByNameSearch.ResultEntry {
|
||||
|
|
|
@ -3,10 +3,9 @@ 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.SearchAPI.SearchApiCallback;
|
||||
import net.osmand.core.samples.android.sample1.search.SearchScope;
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
import net.osmand.core.samples.android.sample1.search.tokens.SearchToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -14,27 +13,29 @@ import java.util.List;
|
|||
|
||||
public class IntermediateSearchRequest extends SearchRequest {
|
||||
|
||||
private List<SearchItem> searchItems;
|
||||
private List<SearchObject> searchObjects;
|
||||
protected String keyword = "";
|
||||
|
||||
public IntermediateSearchRequest(@NonNull SearchAPI searchAPI, int maxSearchResults, @Nullable SearchCallback searchCallback) {
|
||||
super(searchAPI, maxSearchResults, searchCallback);
|
||||
this.searchItems = new ArrayList<>(searchAPI.getSearchItems());
|
||||
public IntermediateSearchRequest(@NonNull SearchScope searchScope, List<SearchObject> searchObjects,
|
||||
int maxSearchResults, @Nullable SearchApiCallback searchCallback) {
|
||||
super(searchScope, maxSearchResults, searchCallback);
|
||||
this.searchObjects = searchObjects;
|
||||
|
||||
SearchToken token = searchString.getLastToken();
|
||||
SearchToken token = searchScope.getSearchString().getLastToken();
|
||||
if (token != null && token.getType() == SearchToken.TokenType.NAME_FILTER) {
|
||||
keyword = token.getQueryText();
|
||||
keyword = token.getQueryText().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SearchItem> doSearch() {
|
||||
List<SearchItem> res = new ArrayList<>();
|
||||
for (SearchItem item : searchItems) {
|
||||
protected List<SearchObject> doSearch() {
|
||||
List<SearchObject> res = new ArrayList<>();
|
||||
for (SearchObject item : searchObjects) {
|
||||
if (cancelled) {
|
||||
break;
|
||||
}
|
||||
if (keyword.isEmpty() || item.getName().contains(keyword)) {
|
||||
if (keyword.isEmpty() || item.getName(searchScope.getLang()).toLowerCase().contains(keyword)
|
||||
|| item.getNativeName().toLowerCase().contains(keyword)) {
|
||||
res.add(item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,62 +4,57 @@ 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.SearchAPI.SearchApiCallback;
|
||||
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 net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
|
||||
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 SearchApiCallback 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();
|
||||
public SearchRequest(@NonNull SearchScope searchScope, int maxSearchResults,
|
||||
@Nullable SearchApiCallback searchCallback) {
|
||||
this.searchScope = searchScope;
|
||||
this.maxSearchResults = maxSearchResults;
|
||||
this.searchCallback = searchCallback;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
new AsyncTask<Void, Void, List<SearchItem>>() {
|
||||
new AsyncTask<Void, Void, List<SearchObject>>() {
|
||||
|
||||
@Override
|
||||
protected List<SearchItem> doInBackground(Void... params) {
|
||||
protected List<SearchObject> doInBackground(Void... params) {
|
||||
return doSearch();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<SearchItem> searchItems) {
|
||||
protected void onPostExecute(List<SearchObject> searchObjects) {
|
||||
|
||||
onSearchRequestPostExecute(searchItems);
|
||||
onSearchRequestPostExecute(searchObjects);
|
||||
|
||||
if (onFinished != null) {
|
||||
onFinished.run();
|
||||
}
|
||||
|
||||
if (searchCallback != null && !cancelled) {
|
||||
searchCallback.onSearchFinished(searchItems);
|
||||
searchCallback.onSearchFinished(searchObjects);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
protected void onSearchRequestPostExecute(List<SearchItem> searchItems) {
|
||||
protected void onSearchRequestPostExecute(List<SearchObject> searchObjects) {
|
||||
}
|
||||
|
||||
protected abstract List<SearchItem> doSearch();
|
||||
protected abstract List<SearchObject> doSearch();
|
||||
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,6 @@ 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);
|
||||
super(TokenType.NAME_FILTER, startIndex, queryText, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
|
||||
public class ObjectSearchToken extends SearchToken {
|
||||
|
||||
public ObjectSearchToken(SearchToken searchToken, SearchObject searchObject) {
|
||||
super(TokenType.SEARCH_OBJECT, searchToken.getStartIndex(), searchToken.getQueryText(), searchObject);
|
||||
}
|
||||
|
||||
public ObjectSearchToken(int startIndex, String queryText, SearchObject searchObject) {
|
||||
super(TokenType.SEARCH_OBJECT, startIndex, queryText, searchObject);
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,29 +1,24 @@
|
|||
package net.osmand.core.samples.android.sample1.search.tokens;
|
||||
|
||||
import net.osmand.core.samples.android.sample1.search.objects.SearchObject;
|
||||
|
||||
public abstract class SearchToken {
|
||||
|
||||
public enum TokenType {
|
||||
CITY,
|
||||
POSTCODE,
|
||||
STREET,
|
||||
BUILDING,
|
||||
POI_CATEGORY,
|
||||
POI_FILTER,
|
||||
POI_TYPE,
|
||||
LOCATION,
|
||||
SEARCH_OBJECT,
|
||||
NAME_FILTER
|
||||
}
|
||||
|
||||
private TokenType type;
|
||||
private SearchObject searchObject;
|
||||
private int startIndex;
|
||||
protected String queryText;
|
||||
protected String name;
|
||||
|
||||
public SearchToken(TokenType type, int startIndex, String queryText, String name) {
|
||||
public SearchToken(TokenType type, int startIndex, String queryText, SearchObject searchObject) {
|
||||
this.type = type;
|
||||
this.startIndex = startIndex;
|
||||
this.queryText = queryText;
|
||||
this.name = name;
|
||||
this.searchObject = searchObject;
|
||||
}
|
||||
|
||||
public TokenType getType() {
|
||||
|
@ -50,7 +45,7 @@ public abstract class SearchToken {
|
|||
return queryText.length();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
public SearchObject getSearchObject() {
|
||||
return searchObject;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue