Initial commit address search refactoring
This commit is contained in:
parent
fd9f87ba1d
commit
f40657ebec
12 changed files with 514 additions and 503 deletions
|
@ -17,12 +17,20 @@ public class CollatorStringMatcher implements StringMatcher {
|
|||
private final String part;
|
||||
|
||||
public static enum StringMatcherMode {
|
||||
// tests only first word as base starts with part
|
||||
CHECK_ONLY_STARTS_WITH,
|
||||
// tests all words (split by space) and one of word should start with a given part
|
||||
CHECK_STARTS_FROM_SPACE,
|
||||
// tests all words except first (split by space) and one of word should start with a given part
|
||||
CHECK_STARTS_FROM_SPACE_NOT_BEGINNING,
|
||||
// tests all words (split by space) and one of word should be equal to part
|
||||
CHECK_EQUALS_FROM_SPACE,
|
||||
// TO DO: make a separate method
|
||||
// trims part to make shorter then full text and tests only first word as base starts with part
|
||||
TRIM_AND_CHECK_ONLY_STARTS_WITH,
|
||||
// simple collator contains in any part of the base
|
||||
CHECK_CONTAINS,
|
||||
CHECK_ONLY_STARTS_WITH_TRIM,
|
||||
// simple collator equals
|
||||
CHECK_EQUALS,
|
||||
}
|
||||
|
||||
|
@ -42,22 +50,25 @@ public class CollatorStringMatcher implements StringMatcher {
|
|||
}
|
||||
|
||||
|
||||
public static boolean cmatches(Collator collator, String base, String part, StringMatcherMode mode){
|
||||
public static boolean cmatches(Collator collator, String fullName, String part, StringMatcherMode mode){
|
||||
switch (mode) {
|
||||
case CHECK_CONTAINS:
|
||||
return ccontains(collator, base, part);
|
||||
return ccontains(collator, fullName, part);
|
||||
case CHECK_EQUALS_FROM_SPACE:
|
||||
return cstartsWith(collator, base, part, true, true, true, false);
|
||||
return cstartsWith(collator, fullName, part, true, true, true);
|
||||
case CHECK_STARTS_FROM_SPACE:
|
||||
return cstartsWith(collator, base, part, true, true, false, false);
|
||||
return cstartsWith(collator, fullName, part, true, true, false);
|
||||
case CHECK_STARTS_FROM_SPACE_NOT_BEGINNING:
|
||||
return cstartsWith(collator, base, part, false, true, false, false);
|
||||
return cstartsWith(collator, fullName, part, false, true, false);
|
||||
case CHECK_ONLY_STARTS_WITH:
|
||||
return cstartsWith(collator, base, part, true, false, false, false);
|
||||
case CHECK_ONLY_STARTS_WITH_TRIM:
|
||||
return cstartsWith(collator, base, part, true, false, false, true);
|
||||
return cstartsWith(collator, fullName, part, true, false, false);
|
||||
case TRIM_AND_CHECK_ONLY_STARTS_WITH:
|
||||
if (part.length() > fullName.length()) {
|
||||
part = part.substring(0, fullName.length());
|
||||
}
|
||||
return cstartsWith(collator, fullName, part, true, false, false);
|
||||
case CHECK_EQUALS:
|
||||
return cstartsWith(collator, base, part, false, false, true, false);
|
||||
return cstartsWith(collator, fullName, part, false, false, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -116,21 +127,14 @@ public class CollatorStringMatcher implements StringMatcher {
|
|||
* Special check try to find as well in the middle of name
|
||||
*
|
||||
* @param collator
|
||||
* @param searchInParam
|
||||
* @param fullText
|
||||
* @param theStart
|
||||
* @param trim - trim theStart to searchInParam length if searchInParam non empty
|
||||
* @return true if searchIn starts with token
|
||||
*/
|
||||
public static boolean cstartsWith(Collator collator, String searchInParam, String theStart,
|
||||
boolean checkBeginning, boolean checkSpaces, boolean equals, boolean trim) {
|
||||
String searchIn = searchInParam.toLowerCase(Locale.getDefault());
|
||||
if (trim && searchIn.length() > 0) {
|
||||
searchIn += " ";
|
||||
}
|
||||
public static boolean cstartsWith(Collator collator, String fullText, String theStart,
|
||||
boolean checkBeginning, boolean checkSpaces, boolean equals) {
|
||||
String searchIn = fullText.toLowerCase(Locale.getDefault());
|
||||
int searchInLength = searchIn.length();
|
||||
if (trim && searchInLength > 0 && theStart.length() > searchInLength) {
|
||||
theStart = theStart.substring(0, searchInLength);
|
||||
}
|
||||
int startLength = theStart.length();
|
||||
if (startLength == 0) {
|
||||
return true;
|
||||
|
|
|
@ -13,10 +13,6 @@ public class CommonWords {
|
|||
frequentlyUsedWordsDictionary.put(string, frequentlyUsedWordsDictionary.size());
|
||||
}
|
||||
public static int getCommon(String name) {
|
||||
// if(true) {
|
||||
// // not ready for old versions yet
|
||||
// return -1;
|
||||
// }
|
||||
Integer i = commonWordsDictionary.get(name);
|
||||
return i == null ? -1 : i.intValue();
|
||||
}
|
||||
|
@ -28,7 +24,15 @@ public class CommonWords {
|
|||
|
||||
public static int getCommonSearch(String name) {
|
||||
Integer i = commonWordsDictionary.get(name);
|
||||
return i == null ? getFrequentlyUsed(name) : i.intValue() + frequentlyUsedWordsDictionary.size();
|
||||
// higher means better for search
|
||||
if (i == null) {
|
||||
int fq = getFrequentlyUsed(name);
|
||||
if (fq != -1) {
|
||||
return commonWordsDictionary.size() + fq;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return i.intValue();
|
||||
}
|
||||
|
||||
public static int getCommonGeocoding(String name) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package net.osmand.search;
|
||||
|
||||
import net.osmand.Collator;
|
||||
import net.osmand.OsmAndCollator;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
|
@ -72,7 +71,7 @@ public class SearchUICore {
|
|||
taskQueue = new LinkedBlockingQueue<Runnable>();
|
||||
searchSettings = new SearchSettings(new ArrayList<BinaryMapIndexReader>());
|
||||
searchSettings = searchSettings.setLang(locale, transliterate);
|
||||
phrase = new SearchPhrase(searchSettings, OsmAndCollator.primaryCollator());
|
||||
phrase = SearchPhrase.emptyPhrase();
|
||||
currentSearchResult = new SearchResultCollection(phrase);
|
||||
singleThreadedExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, taskQueue);
|
||||
}
|
||||
|
@ -351,10 +350,10 @@ public class SearchUICore {
|
|||
}
|
||||
}
|
||||
|
||||
public void setFilterOrders(List<String> filterOrders) {
|
||||
public void setActivePoiFiltersByOrder(List<String> filterOrders) {
|
||||
for (SearchCoreAPI capi : apis) {
|
||||
if (capi instanceof SearchAmenityTypesAPI) {
|
||||
((SearchAmenityTypesAPI) capi).setFilterOrders(filterOrders);
|
||||
((SearchAmenityTypesAPI) capi).setActivePoiFiltersByOrder(filterOrders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,7 +403,7 @@ public class SearchUICore {
|
|||
}
|
||||
|
||||
private boolean filterOneResult(SearchResult object, SearchPhrase phrase) {
|
||||
NameStringMatcher nameStringMatcher = phrase.getNameStringMatcher();
|
||||
NameStringMatcher nameStringMatcher = phrase.getFirstUnknownNameStringMatcher();
|
||||
return nameStringMatcher.matches(object.localeName) || nameStringMatcher.matches(object.otherNames);
|
||||
}
|
||||
|
||||
|
@ -714,16 +713,17 @@ public class SearchUICore {
|
|||
|
||||
@Override
|
||||
public boolean publish(SearchResult object) {
|
||||
if (phrase != null && object.otherNames != null && !phrase.getNameStringMatcher().matches(object.localeName)) {
|
||||
// TODO first , other?
|
||||
if (phrase != null && object.otherNames != null && !phrase.getFirstUnknownNameStringMatcher().matches(object.localeName)) {
|
||||
for (String s : object.otherNames) {
|
||||
if (phrase.getNameStringMatcher().matches(s)) {
|
||||
if (phrase.getFirstUnknownNameStringMatcher().matches(s)) {
|
||||
object.alternateName = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Algorithms.isEmpty(object.alternateName) && object.object instanceof Amenity) {
|
||||
for (String value : ((Amenity) object.object).getAdditionalInfo().values()) {
|
||||
if (phrase.getNameStringMatcher().matches(value)) {
|
||||
if (phrase.getFirstUnknownNameStringMatcher().matches(value)) {
|
||||
object.alternateName = value;
|
||||
break;
|
||||
}
|
||||
|
@ -815,7 +815,7 @@ public class SearchUICore {
|
|||
|
||||
SearchExportSettings exportSettings = phrase.getSettings().getExportSettings();
|
||||
json.put("settings", phrase.getSettings().toJSON());
|
||||
json.put("phrase", phrase.getRawUnknownSearchPhrase());
|
||||
json.put("phrase", phrase.getFullSearchPhrase());
|
||||
if (searchResult.searchResults != null && searchResult.searchResults.size() > 0) {
|
||||
JSONArray resultsArr = new JSONArray();
|
||||
for (SearchResult r : searchResult.searchResults) {
|
||||
|
@ -963,14 +963,12 @@ public class SearchUICore {
|
|||
}
|
||||
|
||||
public static class SearchResultComparator implements Comparator<SearchResult> {
|
||||
private SearchPhrase sp;
|
||||
private Collator collator;
|
||||
private LatLon loc;
|
||||
private boolean sortByName;
|
||||
|
||||
|
||||
public SearchResultComparator(SearchPhrase sp) {
|
||||
this.sp = sp;
|
||||
this.collator = sp.getCollator();
|
||||
loc = sp.getLastTokenLocation();
|
||||
sortByName = sp.isSortByName();
|
||||
|
|
|
@ -140,20 +140,18 @@ public class SearchCoreFactory {
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected void subSearchApiOrPublish(SearchPhrase phrase,
|
||||
SearchResultMatcher resultMatcher, SearchResult res, SearchBaseAPI api)
|
||||
protected void subSearchApiOrPublish(SearchPhrase phrase, SearchResultMatcher resultMatcher, SearchResult res, SearchBaseAPI api)
|
||||
throws IOException {
|
||||
phrase.countUnknownWordsMatch(res);
|
||||
// int cnt = resultMatcher.getCount();
|
||||
phrase.countUnknownWordsMatchMainResult(res);
|
||||
// TODO select word & delete found words
|
||||
List<String> ws = phrase.getUnknownSearchWords(res.otherWordsMatch);
|
||||
if (!res.firstUnknownWordMatches) {
|
||||
ws.add(phrase.getUnknownSearchWord());
|
||||
ws.add(phrase.getFirstUnknownSearchWord());
|
||||
}
|
||||
// publish result to set parentSearchResult before search
|
||||
resultMatcher.publish(res);
|
||||
if (!ws.isEmpty() && api != null && api.isSearchAvailable(phrase)) {
|
||||
SearchPhrase nphrase = phrase.selectWord(res, ws,
|
||||
phrase.isLastUnknownSearchWordComplete());
|
||||
SearchPhrase nphrase = phrase.selectWord(res, ws, phrase.isLastUnknownSearchWordComplete());
|
||||
resultMatcher.setParentSearchResult(res);
|
||||
api.search(nphrase, resultMatcher);
|
||||
resultMatcher.setParentSearchResult(res.parentSearchResult);
|
||||
|
@ -166,8 +164,6 @@ public class SearchCoreFactory {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class SearchRegionByNameAPI extends SearchBaseAPI {
|
||||
|
||||
public SearchRegionByNameAPI() {
|
||||
|
@ -186,9 +182,9 @@ public class SearchCoreFactory {
|
|||
sr.objectType = ObjectType.REGION;
|
||||
sr.location = bmir.getRegionCenter();
|
||||
sr.preferredZoom = 6;
|
||||
if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
|
||||
if (phrase.getFirstUnknownSearchWord().length() <= 1 && phrase.isNoSelectedType()) {
|
||||
resultMatcher.publish(sr);
|
||||
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
|
||||
} else if (phrase.getFirstUnknownNameStringMatcher().matches(sr.localeName)) {
|
||||
resultMatcher.publish(sr);
|
||||
}
|
||||
}
|
||||
|
@ -210,19 +206,6 @@ public class SearchCoreFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private static String stripBraces(String localeName) {
|
||||
int i = localeName.indexOf('(');
|
||||
String retName = localeName;
|
||||
if (i > -1) {
|
||||
retName = localeName.substring(0, i);
|
||||
int j = localeName.indexOf(')', i);
|
||||
if (j > -1) {
|
||||
retName = retName.trim() + ' ' + localeName.substring(j);
|
||||
}
|
||||
}
|
||||
return retName;
|
||||
}
|
||||
|
||||
public static class SearchAddressByNameAPI extends SearchBaseAPI {
|
||||
|
||||
private static final int DEFAULT_ADDRESS_BBOX_RADIUS = 100 * 1000;
|
||||
|
@ -310,10 +293,7 @@ public class SearchCoreFactory {
|
|||
if (phrase.isNoSelectedType() && bbox != null
|
||||
&& (phrase.isUnknownSearchWordPresent() || phrase.isEmptyQueryAllowed())
|
||||
&& phrase.isSearchTypeAllowed(ObjectType.CITY)) {
|
||||
String word = phrase.getUnknownWordToSearch();
|
||||
NameStringMatcher nm = phrase.getNameStringMatcher(word, phrase.isUnknownSearchWordComplete());
|
||||
NameStringMatcher wordEqualsMatcher = phrase.getNameStringMatcher(word, true);
|
||||
boolean firstUnknownWordMatches = word.equals(phrase.getUnknownSearchWord());
|
||||
NameStringMatcher nm = phrase.getMainUnknownNameStringMatcher();
|
||||
resArray.clear();
|
||||
resArray = townCitiesQR.queryInBox(bbox, resArray);
|
||||
int limit = 0;
|
||||
|
@ -335,8 +315,6 @@ public class SearchCoreFactory {
|
|||
if (phrase.isEmptyQueryAllowed() && phrase.isEmpty()) {
|
||||
resultMatcher.publish(res);
|
||||
} else if (nm.matches(res.localeName) || nm.matches(res.otherNames)) {
|
||||
res.firstUnknownWordMatches = firstUnknownWordMatches;
|
||||
res.unknownPhraseMatches = wordEqualsMatcher.matches(res.localeName);
|
||||
subSearchApiOrPublish(phrase, resultMatcher, res, cityApi);
|
||||
}
|
||||
if (limit++ > LIMIT * phrase.getRadiusLevel()) {
|
||||
|
@ -348,7 +326,8 @@ public class SearchCoreFactory {
|
|||
|
||||
private void searchByName(final SearchPhrase phrase, final SearchResultMatcher resultMatcher)
|
||||
throws IOException {
|
||||
if (phrase.getRadiusLevel() > 1 || phrase.getUnknownSearchWordLength() > 3 || phrase.getUnknownSearchWords().size() > 0 || phrase.isSearchTypeAllowed(ObjectType.POSTCODE, true)) {
|
||||
if (phrase.getRadiusLevel() > 1 || phrase.getUnknownWordToSearch().length() > 3 ||
|
||||
phrase.hasMoreThanOneUnknownSearchWord()|| phrase.isSearchTypeAllowed(ObjectType.POSTCODE, true)) {
|
||||
final boolean locSpecified = phrase.getLastTokenLocation() != null;
|
||||
LatLon loc = phrase.getLastTokenLocation();
|
||||
final List<SearchResult> immediateResults = new ArrayList<>();
|
||||
|
@ -391,7 +370,7 @@ public class SearchCoreFactory {
|
|||
if (object.getName().startsWith("<")) {
|
||||
return false;
|
||||
}
|
||||
if (!phrase.getNameStringMatcher().matches(stripBraces(sr.localeName))) {
|
||||
if (!phrase.getFirstUnknownNameStringMatcher().matches(stripBraces(sr.localeName))) {
|
||||
sr.priorityDistance = 5;
|
||||
}
|
||||
sr.objectType = ObjectType.STREET;
|
||||
|
@ -460,16 +439,13 @@ public class SearchCoreFactory {
|
|||
};
|
||||
Iterator<BinaryMapIndexReader> offlineIterator = phrase.getRadiusOfflineIndexes(DEFAULT_ADDRESS_BBOX_RADIUS * 5,
|
||||
SearchPhraseDataType.ADDRESS);
|
||||
|
||||
String wordToSearch = phrase.getUnknownWordToSearch();
|
||||
NameStringMatcher wordEqualsMatcher = phrase.getNameStringMatcher(wordToSearch, true);
|
||||
boolean firstUnknownWordMatches = wordToSearch.equals(phrase.getUnknownSearchWord());
|
||||
while (offlineIterator.hasNext() && wordToSearch.length() > 0) {
|
||||
BinaryMapIndexReader r = offlineIterator.next();
|
||||
currentFile[0] = r;
|
||||
immediateResults.clear();
|
||||
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, wordToSearch.toLowerCase(),
|
||||
phrase.isUnknownSearchWordComplete() ? StringMatcherMode.CHECK_EQUALS_FROM_SPACE
|
||||
phrase.isMainUnknownSearchWordComplete() ? StringMatcherMode.CHECK_EQUALS_FROM_SPACE
|
||||
: StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
if (locSpecified) {
|
||||
req.setBBoxRadius(loc.getLatitude(), loc.getLongitude(),
|
||||
|
@ -477,8 +453,6 @@ public class SearchCoreFactory {
|
|||
}
|
||||
r.searchAddressDataByName(req);
|
||||
for (SearchResult res : immediateResults) {
|
||||
res.firstUnknownWordMatches = firstUnknownWordMatches;
|
||||
res.unknownPhraseMatches = wordEqualsMatcher.matches(res.localeName);
|
||||
if (res.objectType == ObjectType.STREET) {
|
||||
City ct = ((Street) res.object).getCity();
|
||||
phrase.countUnknownWordsMatch(res,
|
||||
|
@ -510,35 +484,34 @@ public class SearchCoreFactory {
|
|||
if (!phrase.isUnknownSearchWordPresent()) {
|
||||
return false;
|
||||
}
|
||||
boolean hasUnselectedType = phrase.isNoSelectedType() && phrase.isUnknownSearchWordPresent()
|
||||
&& phrase.isUnknownSearchWordComplete() && phrase.hasUnknownSearchWordPoiTypes();
|
||||
// TODO
|
||||
// consider 'bar' - 'Hospital 512'
|
||||
if (!phrase.isNoSelectedType()) {
|
||||
// don't search by name when type is selected or poi type is part of name
|
||||
return false;
|
||||
}
|
||||
// boolean hasUnselectedType = phrase.isNoSelectedType() && phrase.isUnknownSearchWordPresent()
|
||||
// && phrase.isMainUnknownSearchWordComplete() && phrase.hasUnknownSearchWordPoiTypes();
|
||||
// Check feedback before it was searching exact match of whole phrase.getUnknownSearchPhrase()
|
||||
|
||||
final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1];
|
||||
Iterator<BinaryMapIndexReader> offlineIterator = phrase.getRadiusOfflineIndexes(BBOX_RADIUS,
|
||||
SearchPhraseDataType.POI);
|
||||
String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
|
||||
String searchWord = hasUnselectedType ? unknownSearchPhrase : phrase.getUnknownWordToSearch();
|
||||
final NameStringMatcher nm = phrase.getNameStringMatcher(searchWord, phrase.isUnknownSearchWordComplete());
|
||||
final NameStringMatcher phraseMatcher;
|
||||
if (!Algorithms.isEmpty(unknownSearchPhrase)) {
|
||||
phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
|
||||
} else {
|
||||
phraseMatcher = null;
|
||||
}
|
||||
String searchWord = phrase.getUnknownWordToSearch();
|
||||
final NameStringMatcher nm = phrase.getMainUnknownNameStringMatcher();
|
||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE);
|
||||
final Set<String> ids = new HashSet<String>();
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
(int)bbox.centerX(), (int)bbox.centerY(),
|
||||
searchWord,
|
||||
(int)bbox.left, (int)bbox.right,
|
||||
(int)bbox.top, (int)bbox.bottom,
|
||||
new ResultMatcher<Amenity>() {
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest((int) bbox.centerX(),
|
||||
(int) bbox.centerY(), searchWord, (int) bbox.left, (int) bbox.right, (int) bbox.top,
|
||||
(int) bbox.bottom, new ResultMatcher<Amenity>() {
|
||||
int limit = 0;
|
||||
|
||||
@Override
|
||||
public boolean publish(Amenity object) {
|
||||
if (phrase.getSettings().isExportObjects()) {
|
||||
resultMatcher.exportObject(object);
|
||||
}
|
||||
if (limit ++ > LIMIT) {
|
||||
if (limit++ > LIMIT) {
|
||||
return false;
|
||||
}
|
||||
String poiID = object.getType().getKeyName() + "_" + object.getId();
|
||||
|
@ -547,19 +520,17 @@ public class SearchCoreFactory {
|
|||
}
|
||||
SearchResult sr = new SearchResult(phrase);
|
||||
sr.otherNames = object.getAllNames(true);
|
||||
sr.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||
if (phrase.isUnknownSearchWordComplete()) {
|
||||
if(!nm.matches(sr.localeName) && !nm.matches(sr.otherNames) &&
|
||||
!nm.matches(object.getAdditionalInfo().values())) {
|
||||
return false;
|
||||
}
|
||||
sr.localeName = object.getName(phrase.getSettings().getLang(),
|
||||
phrase.getSettings().isTransliterate());
|
||||
if (!nm.matches(sr.localeName) && !nm.matches(sr.otherNames)
|
||||
&& !nm.matches(object.getAdditionalInfo().values())) {
|
||||
return false;
|
||||
}
|
||||
sr.object = object;
|
||||
sr.preferredZoom = 17;
|
||||
sr.file = currentFile[0];
|
||||
sr.location = object.getLocation();
|
||||
if (object.getSubType().equals("city") ||
|
||||
object.getSubType().equals("country")) {
|
||||
if (object.getSubType().equals("city") || object.getSubType().equals("country")) {
|
||||
sr.priorityDistance = SEARCH_AMENITY_BY_NAME_CITY_PRIORITY_DISTANCE;
|
||||
sr.preferredZoom = object.getSubType().equals("country") ? 7 : 13;
|
||||
} else if (object.getSubType().equals("town")) {
|
||||
|
@ -568,10 +539,7 @@ public class SearchCoreFactory {
|
|||
sr.priorityDistance = 1;
|
||||
}
|
||||
sr.priority = SEARCH_AMENITY_BY_NAME_PRIORITY;
|
||||
if (phraseMatcher != null) {
|
||||
sr.unknownPhraseMatches = phraseMatcher.matches(sr.localeName);
|
||||
}
|
||||
phrase.countUnknownWordsMatch(sr);
|
||||
phrase.countUnknownWordsMatchMainResult(sr);
|
||||
sr.objectType = ObjectType.POI;
|
||||
resultMatcher.publish(sr);
|
||||
ids.add(poiID);
|
||||
|
@ -580,7 +548,7 @@ public class SearchCoreFactory {
|
|||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return resultMatcher.isCancelled() && (limit < LIMIT) ;
|
||||
return resultMatcher.isCancelled() && (limit < LIMIT);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -633,9 +601,8 @@ public class SearchCoreFactory {
|
|||
private List<AbstractPoiType> topVisibleFilters;
|
||||
private List<PoiCategory> categories;
|
||||
private List<CustomSearchPoiFilter> customPoiFilters = new ArrayList<>();
|
||||
private TIntArrayList customPoiFiltersPriorites = new TIntArrayList();
|
||||
private Map<String, Integer> activePoiFilters = new HashMap<>();
|
||||
private MapPoiTypes types;
|
||||
private List<String> filterOrders = new ArrayList<>();
|
||||
|
||||
public SearchAmenityTypesAPI(MapPoiTypes types) {
|
||||
super(ObjectType.POI_TYPE);
|
||||
|
@ -644,126 +611,123 @@ public class SearchCoreFactory {
|
|||
|
||||
public void clearCustomFilters() {
|
||||
this.customPoiFilters.clear();
|
||||
this.customPoiFiltersPriorites.clear();
|
||||
}
|
||||
|
||||
public void addCustomFilter(CustomSearchPoiFilter poiFilter, int priority) {
|
||||
this.customPoiFilters.add(poiFilter);
|
||||
this.customPoiFiltersPriorites.add(priority);
|
||||
}
|
||||
|
||||
public void setFilterOrders(List<String> filterOrders) {
|
||||
this.filterOrders = filterOrders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException {
|
||||
if (translatedNames.isEmpty()) {
|
||||
translatedNames = types.getAllTranslatedNames(false);
|
||||
topVisibleFilters = types.getTopVisibleFilters();
|
||||
categories = types.getCategories(false);
|
||||
if (priority > 0) {
|
||||
this.activePoiFilters.put(poiFilter.getFilterId(), priority);
|
||||
}
|
||||
}
|
||||
|
||||
public void setActivePoiFiltersByOrder(List<String> filterOrder) {
|
||||
for (int i = 0; i < filterOrder.size(); i++) {
|
||||
this.activePoiFilters.put(filterOrder.get(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
public List<AbstractPoiType> getPoiTypeResults(NameStringMatcher nm, boolean includeAdditionals) {
|
||||
List<AbstractPoiType> results = new ArrayList<AbstractPoiType>();
|
||||
List<AbstractPoiType> searchWordTypes = new ArrayList<AbstractPoiType>();
|
||||
NameStringMatcher nm;
|
||||
String unknownSearchPhrase = phrase.getUnknownSearchPhrase();
|
||||
boolean showTopFiltersOnly = !phrase.isUnknownSearchWordPresent();
|
||||
if (phrase.getUnknownSearchWord().length() < unknownSearchPhrase.length()) {
|
||||
nm = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_ONLY_STARTS_WITH_TRIM);
|
||||
} else {
|
||||
nm = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
}
|
||||
for (AbstractPoiType pf : topVisibleFilters) {
|
||||
if (showTopFiltersOnly
|
||||
|| nm.matches(pf.getTranslation())
|
||||
|| nm.matches(pf.getEnTranslation())
|
||||
if (nm.matches(pf.getTranslation()) || nm.matches(pf.getEnTranslation())
|
||||
|| nm.matches(pf.getSynonyms())) {
|
||||
results.add(pf);
|
||||
searchWordTypes.add(pf);
|
||||
}
|
||||
}
|
||||
if (!showTopFiltersOnly) {
|
||||
for (PoiCategory c : categories) {
|
||||
if (!results.contains(c)
|
||||
&& (nm.matches(c.getTranslation())
|
||||
|| nm.matches(c.getEnTranslation())
|
||||
|| nm.matches(c.getSynonyms()))) {
|
||||
results.add(c);
|
||||
searchWordTypes.add(c);
|
||||
}
|
||||
for (PoiCategory c : categories) {
|
||||
if (!results.contains(c) && (nm.matches(c.getTranslation()) || nm.matches(c.getEnTranslation())
|
||||
|| nm.matches(c.getSynonyms()))) {
|
||||
results.add(c);
|
||||
}
|
||||
Iterator<Entry<String, PoiType>> it = translatedNames.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<String, PoiType> e = it.next();
|
||||
PoiType pt = e.getValue();
|
||||
if (pt.getCategory() != types.getOtherMapCategory()) {
|
||||
if (!results.contains(pt)
|
||||
&& (nm.matches(pt.getEnTranslation())
|
||||
|| nm.matches(pt.getTranslation())
|
||||
|| nm.matches(pt.getSynonyms()))) {
|
||||
results.add(pt);
|
||||
searchWordTypes.add(pt);
|
||||
}
|
||||
List<PoiType> additionals = pt.getPoiAdditionals();
|
||||
if (additionals != null) {
|
||||
for (PoiType a : additionals) {
|
||||
if (!results.contains(a)) {
|
||||
String enTranslation = a.getEnTranslation().toLowerCase();
|
||||
if (!"yes".equals(enTranslation) && !"no".equals(enTranslation)
|
||||
&& (nm.matches(enTranslation) || nm.matches(a.getTranslation()) || nm.matches(a.getSynonyms()))) {
|
||||
results.add(a);
|
||||
}
|
||||
}
|
||||
Iterator<Entry<String, PoiType>> it = translatedNames.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<String, PoiType> e = it.next();
|
||||
PoiType pt = e.getValue();
|
||||
if (pt.getCategory() != types.getOtherMapCategory()) {
|
||||
if (!results.contains(pt) && (nm.matches(pt.getEnTranslation()) || nm.matches(pt.getTranslation())
|
||||
|| nm.matches(pt.getSynonyms()))) {
|
||||
results.add(pt);
|
||||
}
|
||||
List<PoiType> additionals = pt.getPoiAdditionals();
|
||||
if (additionals != null && includeAdditionals) {
|
||||
for (PoiType a : additionals) {
|
||||
if (!results.contains(a)) {
|
||||
String enTranslation = a.getEnTranslation().toLowerCase();
|
||||
if (!"yes".equals(enTranslation) && !"no".equals(enTranslation)
|
||||
&& (nm.matches(enTranslation) || nm.matches(a.getTranslation())
|
||||
|| nm.matches(a.getSynonyms()))) {
|
||||
results.add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
phrase.setUnknownSearchWordPoiTypes(searchWordTypes);
|
||||
return results;
|
||||
}
|
||||
|
||||
if (resultMatcher != null) {
|
||||
String word = phrase.getUnknownSearchWord();
|
||||
NameStringMatcher startMatch = new NameStringMatcher(word, StringMatcherMode.CHECK_ONLY_STARTS_WITH);
|
||||
for (AbstractPoiType pt : results) {
|
||||
private void initPoiTypes() {
|
||||
if (translatedNames.isEmpty()) {
|
||||
translatedNames = types.getAllTranslatedNames(false);
|
||||
topVisibleFilters = types.getTopVisibleFilters();
|
||||
categories = types.getCategories(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException {
|
||||
boolean showTopFiltersOnly = !phrase.isUnknownSearchWordPresent();
|
||||
NameStringMatcher nm = phrase.getFullUnknownNameMatcher();
|
||||
initPoiTypes();
|
||||
List<AbstractPoiType> poiTypes = topVisibleFilters;
|
||||
if (!showTopFiltersOnly) {
|
||||
poiTypes = getPoiTypeResults(nm, true);
|
||||
}
|
||||
for (AbstractPoiType pt : poiTypes) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = pt.getTranslation();
|
||||
res.object = pt;
|
||||
addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(pt), res);
|
||||
}
|
||||
for (int i = 0; i < customPoiFilters.size(); i++) {
|
||||
CustomSearchPoiFilter csf = customPoiFilters.get(i);
|
||||
if (showTopFiltersOnly || nm.matches(csf.getName())) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = pt.getTranslation();
|
||||
res.object = pt;
|
||||
res.priorityDistance = 0;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
res.firstUnknownWordMatches = startMatch.matches(res.localeName);
|
||||
if (showTopFiltersOnly) {
|
||||
String stdFilterId = getStandardFilterId(pt);
|
||||
if (filterOrders.contains(stdFilterId)) {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + filterOrders.indexOf(stdFilterId);
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
} else {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < customPoiFilters.size(); i++) {
|
||||
CustomSearchPoiFilter csf = customPoiFilters.get(i);
|
||||
if (!phrase.isUnknownSearchWordPresent() || nm.matches(csf.getName())) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = csf.getName();
|
||||
res.object = csf;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
if (showTopFiltersOnly) {
|
||||
if (filterOrders.contains(csf.getFilterId())) {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + filterOrders.indexOf(csf.getFilterId());
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
} else {
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY + customPoiFiltersPriorites.get(i);
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
}
|
||||
res.localeName = csf.getName();
|
||||
res.object = csf;
|
||||
addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, csf.getFilterId(), res);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addPoiTypeResult(SearchPhrase phrase, SearchResultMatcher resultMatcher, boolean showTopFiltersOnly,
|
||||
String stdFilterId , SearchResult res) {
|
||||
res.priorityDistance = 0;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
if (showTopFiltersOnly) {
|
||||
if (activePoiFilters.containsKey(stdFilterId)) {
|
||||
res.priority = getPoiTypePriority(stdFilterId);
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
} else {
|
||||
phrase.countUnknownWordsMatchMainResult(res);
|
||||
res.priority = SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
resultMatcher.publish(res);
|
||||
}
|
||||
}
|
||||
|
||||
private int getPoiTypePriority(String stdFilterId) {
|
||||
Integer i = activePoiFilters.get(stdFilterId);
|
||||
if ( i == null) {
|
||||
return SEARCH_AMENITY_TYPE_PRIORITY;
|
||||
}
|
||||
return SEARCH_AMENITY_TYPE_PRIORITY + i.intValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getStandardFilterId(AbstractPoiType poi) {
|
||||
return STD_POI_FILTER_PREFIX + poi.getKeyName();
|
||||
}
|
||||
|
@ -842,68 +806,67 @@ public class SearchCoreFactory {
|
|||
|
||||
@Override
|
||||
public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException {
|
||||
SearchPoiTypeFilter poiTypeFilter = null;
|
||||
String nameFilter = null;
|
||||
if (phrase.isLastWord(ObjectType.POI_TYPE)) {
|
||||
Object obj = phrase.getLastSelectedWord().getResult().object;
|
||||
SearchPoiTypeFilter ptf;
|
||||
if (obj instanceof AbstractPoiType) {
|
||||
ptf = getPoiTypeFilter((AbstractPoiType) obj);
|
||||
poiTypeFilter = getPoiTypeFilter((AbstractPoiType) obj);
|
||||
} else if (obj instanceof SearchPoiTypeFilter) {
|
||||
ptf = (SearchPoiTypeFilter) obj;
|
||||
poiTypeFilter = (SearchPoiTypeFilter) obj;
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
searchPoi(phrase, resultMatcher, obj, null, ptf);
|
||||
} else if (searchAmenityTypesAPI != null) {
|
||||
if (phrase.getUnknownSearchWordPoiTypes() == null) {
|
||||
searchAmenityTypesAPI.search(phrase, null);
|
||||
}
|
||||
NameStringMatcher nm = phrase.getFullUnknownNameMatcher();
|
||||
searchAmenityTypesAPI.initPoiTypes();
|
||||
List<AbstractPoiType> presentPoiTypes = searchAmenityTypesAPI.getPoiTypeResults(nm, false);
|
||||
// TODO get first ?
|
||||
AbstractPoiType poiType = phrase.getUnknownSearchWordPoiType();
|
||||
if (poiType != null) {
|
||||
SearchPoiTypeFilter ptf = getPoiTypeFilter(poiType);
|
||||
String customName = phrase.getPoiNameFilter(poiType);
|
||||
if (customName != null) {
|
||||
poiTypeFilter = getPoiTypeFilter(poiType);
|
||||
nameFilter = phrase.getPoiNameFilter(poiType);
|
||||
if (nameFilter != null) {
|
||||
phrase.setUnknownSearchWordPoiType(poiType);
|
||||
searchPoi(phrase, resultMatcher, null, customName.length() == 0 ? null : customName, ptf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (poiTypeFilter != null) {
|
||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS);
|
||||
List<BinaryMapIndexReader> offlineIndexes = phrase.getOfflineIndexes();
|
||||
Set<String> searchedPois = new TreeSet<>();
|
||||
for (BinaryMapIndexReader r : offlineIndexes) {
|
||||
ResultMatcher<Amenity> rm = getResultMatcher(phrase, resultMatcher, nameFilter, r, searchedPois);
|
||||
if (poiTypeFilter instanceof CustomSearchPoiFilter) {
|
||||
rm = ((CustomSearchPoiFilter) poiTypeFilter).wrapResultMatcher(rm);
|
||||
}
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest((int) bbox.left,
|
||||
(int) bbox.right, (int) bbox.top, (int) bbox.bottom, -1, poiTypeFilter, rm);
|
||||
r.searchPoi(req);
|
||||
resultMatcher.apiSearchRegionFinished(this, r, phrase);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void searchPoi(SearchPhrase phrase, SearchResultMatcher resultMatcher, Object obj, String customName, SearchPoiTypeFilter ptf) throws IOException {
|
||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS);
|
||||
List<BinaryMapIndexReader> oo = phrase.getOfflineIndexes();
|
||||
Set<String> searchedPois = new TreeSet<>();
|
||||
for (BinaryMapIndexReader o : oo) {
|
||||
ResultMatcher<Amenity> rm = getResultMatcher(phrase, resultMatcher, customName, o, searchedPois);
|
||||
if (obj instanceof CustomSearchPoiFilter) {
|
||||
rm = ((CustomSearchPoiFilter) obj).wrapResultMatcher(rm);
|
||||
}
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
(int) bbox.left, (int) bbox.right,
|
||||
(int) bbox.top, (int) bbox.bottom, -1, ptf,
|
||||
rm);
|
||||
o.searchPoi(req);
|
||||
resultMatcher.apiSearchRegionFinished(this, o, phrase);
|
||||
}
|
||||
}
|
||||
|
||||
private ResultMatcher<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchResultMatcher resultMatcher,
|
||||
final String customName, final BinaryMapIndexReader selected,
|
||||
final String nameFilter, final BinaryMapIndexReader selected,
|
||||
final Set<String> searchedPois) {
|
||||
String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
|
||||
final NameStringMatcher phraseMatcher;
|
||||
if (!Algorithms.isEmpty(unknownSearchPhrase)) {
|
||||
phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
|
||||
} else {
|
||||
phraseMatcher = null;
|
||||
}
|
||||
// TODO
|
||||
// String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
|
||||
// final NameStringMatcher phraseMatcher;
|
||||
// if (!Algorithms.isEmpty(unknownSearchPhrase)) {
|
||||
// phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
|
||||
// } else {
|
||||
// phraseMatcher = null;
|
||||
// }
|
||||
final NameStringMatcher ns;
|
||||
final boolean hasCustomName = !Algorithms.isEmpty(customName);
|
||||
final boolean hasCustomName = !Algorithms.isEmpty(nameFilter);
|
||||
if (hasCustomName) {
|
||||
ns = phrase.getNameStringMatcher(customName, phrase.isLastUnknownSearchWordComplete());
|
||||
ns = phrase.getNameStringMatcher(nameFilter, phrase.isLastUnknownSearchWordComplete());
|
||||
} else {
|
||||
ns = phrase.getNameStringMatcher();
|
||||
ns = phrase.getFirstUnknownNameStringMatcher();
|
||||
}
|
||||
return new ResultMatcher<Amenity>() {
|
||||
|
||||
|
@ -930,13 +893,17 @@ public class SearchCoreFactory {
|
|||
res.localeName = object.getSubType();
|
||||
}
|
||||
}
|
||||
if (phrase.isUnknownSearchWordPresent()
|
||||
&& !(ns.matches(res.localeName) || ns.matches(res.otherNames))) {
|
||||
String ref = object.getTagContent(Amenity.REF, null);
|
||||
if(ref == null || !ns.matches(ref)) {
|
||||
return false;
|
||||
if (phrase.isUnknownSearchWordPresent()) {
|
||||
if (ns.matches(res.localeName) || ns.matches(res.otherNames)) {
|
||||
phrase.countUnknownWordsMatchMainResult(res);
|
||||
} else {
|
||||
res.localeName += " " + ref;
|
||||
String ref = object.getTagContent(Amenity.REF, null);
|
||||
if (ref == null || !ns.matches(ref)) {
|
||||
return false;
|
||||
} else {
|
||||
phrase.countUnknownWordsMatch(res, ref, null);
|
||||
res.localeName += " " + ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -946,6 +913,7 @@ public class SearchCoreFactory {
|
|||
res.location = object.getLocation();
|
||||
res.priority = SEARCH_AMENITY_BY_TYPE_PRIORITY;
|
||||
res.priorityDistance = 1;
|
||||
|
||||
if (phraseMatcher != null) {
|
||||
boolean unknownPhraseMatches = phraseMatcher.matches(res.localeName);
|
||||
AbstractPoiType unknownSearchWordPoiType = phrase.getUnknownSearchWordPoiType();
|
||||
|
@ -969,7 +937,6 @@ public class SearchCoreFactory {
|
|||
}
|
||||
|
||||
private SearchPoiTypeFilter getPoiTypeFilter(AbstractPoiType pt) {
|
||||
|
||||
acceptedTypes.clear();
|
||||
poiAdditionals.clear();
|
||||
updateTypesToAccept(pt);
|
||||
|
@ -1045,16 +1012,8 @@ public class SearchCoreFactory {
|
|||
sw.getResult().file.preloadStreets(c, null);
|
||||
}
|
||||
int limit = 0;
|
||||
String wordToSearch = phrase.getUnknownWordToSearch();
|
||||
boolean firstUnknownWordMatches = wordToSearch.equals(phrase.getUnknownSearchWord());
|
||||
NameStringMatcher nm = phrase.getNameStringMatcher(wordToSearch, phrase.isUnknownSearchWordComplete());
|
||||
String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
|
||||
NameStringMatcher phraseMatcher = null;
|
||||
if (!Algorithms.isEmpty(unknownSearchPhrase)) {
|
||||
phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
|
||||
}
|
||||
NameStringMatcher nm = phrase.getMainUnknownNameStringMatcher();
|
||||
for (Street object : c.getStreets()) {
|
||||
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
|
||||
res.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||
|
@ -1067,12 +1026,6 @@ public class SearchCoreFactory {
|
|||
&& !(nm.matches(res.localeName) || nm.matches(res.otherNames))) {
|
||||
continue;
|
||||
}
|
||||
res.firstUnknownWordMatches = firstUnknownWordMatches ||
|
||||
phrase.getNameStringMatcher().matches(res.localeName) ||
|
||||
phrase.getNameStringMatcher().matches(res.otherNames);
|
||||
if (phraseMatcher != null) {
|
||||
res.unknownPhraseMatches = phraseMatcher.matches(res.localeName);
|
||||
}
|
||||
res.localeRelatedObjectName = c.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||
res.object = object;
|
||||
res.preferredZoom = 17;
|
||||
|
@ -1102,11 +1055,6 @@ public class SearchCoreFactory {
|
|||
|
||||
}
|
||||
|
||||
public static boolean isLastWordCityGroup(SearchPhrase p ) {
|
||||
return p.isLastWord(ObjectType.CITY) || p.isLastWord(ObjectType.POSTCODE) ||
|
||||
p.isLastWord(ObjectType.VILLAGE);
|
||||
}
|
||||
|
||||
public static class SearchBuildingAndIntersectionsByStreetAPI extends SearchBaseAPI {
|
||||
Street cacheBuilding;
|
||||
|
||||
|
@ -1179,7 +1127,7 @@ public class SearchCoreFactory {
|
|||
});
|
||||
}
|
||||
String lw = phrase.getUnknownWordToSearchBuilding();
|
||||
NameStringMatcher buildingMatch = phrase.getNameStringMatcher(lw, phrase.isLastUnknownSearchWordComplete());
|
||||
NameStringMatcher buildingMatch = phrase.getUnknownWordToSearchBuildingNameMatcher();
|
||||
NameStringMatcher startMatch = new NameStringMatcher(lw, StringMatcherMode.CHECK_ONLY_STARTS_WITH);
|
||||
for (Building b : s.getBuildings()) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
|
@ -1194,6 +1142,7 @@ public class SearchCoreFactory {
|
|||
res.file = file;
|
||||
res.priority = priority;
|
||||
res.priorityDistance = 0;
|
||||
// TOOO phrase.countUnknownWordsMatchMainResult(res);
|
||||
res.firstUnknownWordMatches = startMatch.matches(res.localeName);
|
||||
res.relatedObject = s;
|
||||
res.localeRelatedObjectName = s.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||
|
@ -1208,7 +1157,7 @@ public class SearchCoreFactory {
|
|||
resultMatcher.publish(res);
|
||||
}
|
||||
String streetIntersection = phrase.getUnknownWordToSearch();
|
||||
NameStringMatcher streetMatch = phrase.getNameStringMatcher(streetIntersection, phrase.isLastUnknownSearchWordComplete());
|
||||
NameStringMatcher streetMatch = phrase.getMainUnknownNameStringMatcher();
|
||||
if (Algorithms.isEmpty(streetIntersection) ||
|
||||
(!Character.isDigit(streetIntersection.charAt(0)) &&
|
||||
CommonWords.getCommonSearch(streetIntersection) == -1) ) {
|
||||
|
@ -1218,6 +1167,7 @@ public class SearchCoreFactory {
|
|||
|| !phrase.isSearchTypeAllowed(ObjectType.STREET_INTERSECTION)) {
|
||||
continue;
|
||||
}
|
||||
// TOOO phrase.countUnknownWordsMatchMainResult(res);
|
||||
res.otherNames = street.getAllNames(true);
|
||||
res.localeName = street.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||
res.object = street;
|
||||
|
@ -1404,4 +1354,22 @@ public class SearchCoreFactory {
|
|||
return cachedParsedCode == null ? SEARCH_LOCATION_PRIORITY : SEARCH_MAX_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
||||
private static String stripBraces(String localeName) {
|
||||
int i = localeName.indexOf('(');
|
||||
String retName = localeName;
|
||||
if (i > -1) {
|
||||
retName = localeName.substring(0, i);
|
||||
int j = localeName.indexOf(')', i);
|
||||
if (j > -1) {
|
||||
retName = retName.trim() + ' ' + localeName.substring(j);
|
||||
}
|
||||
}
|
||||
return retName;
|
||||
}
|
||||
|
||||
public static boolean isLastWordCityGroup(SearchPhrase p ) {
|
||||
return p.isLastWord(ObjectType.CITY) || p.isLastWord(ObjectType.POSTCODE) ||
|
||||
p.isLastWord(ObjectType.VILLAGE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.osmand.search.core;
|
||||
|
||||
import net.osmand.Collator;
|
||||
import net.osmand.CollatorStringMatcher;
|
||||
import net.osmand.CollatorStringMatcher;import net.osmand.OsmAndCollator;
|
||||
import net.osmand.CollatorStringMatcher.StringMatcherMode;
|
||||
import net.osmand.StringMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
|
@ -10,6 +10,7 @@ import net.osmand.binary.CommonWords;
|
|||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.osm.AbstractPoiType;
|
||||
import net.osmand.search.core.SearchPhrase.NameStringMatcher;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.LocationParser;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
@ -27,31 +28,39 @@ import java.util.Set;
|
|||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
//immutable object
|
||||
// Immutable object !
|
||||
public class SearchPhrase {
|
||||
|
||||
private List<SearchWord> words = new ArrayList<>();
|
||||
private List<String> unknownWords = new ArrayList<>();
|
||||
private List<NameStringMatcher> unknownWordsMatcher = new ArrayList<>();
|
||||
private String unknownSearchWordTrim;
|
||||
private String rawUnknownSearchPhrase = "";
|
||||
private String unknownSearchPhrase = "";
|
||||
private AbstractPoiType unknownSearchWordPoiType;
|
||||
private List<AbstractPoiType> unknownSearchWordPoiTypes = null;
|
||||
|
||||
private NameStringMatcher sm;
|
||||
private SearchSettings settings;
|
||||
private List<BinaryMapIndexReader> indexes;
|
||||
|
||||
private QuadRect cache1kmRect;
|
||||
private boolean lastUnknownSearchWordComplete;
|
||||
private static final String DELIMITER = " ";
|
||||
private static final String ALLDELIMITERS = "\\s|,";
|
||||
private static final Pattern reg = Pattern.compile(ALLDELIMITERS);
|
||||
private Collator clt;
|
||||
private static Comparator<String> commonWordsComparator;
|
||||
|
||||
private static Set<String> conjunctions = new TreeSet<>();
|
||||
|
||||
private final Collator clt;
|
||||
private final SearchSettings settings;
|
||||
private List<BinaryMapIndexReader> indexes;
|
||||
|
||||
// Object consists of 2 part [known + unknown]
|
||||
private String fullTextSearchPhrase = "";
|
||||
private String unknownSearchPhrase = "";
|
||||
|
||||
// Words of 2 parts
|
||||
private List<SearchWord> words = new ArrayList<>();
|
||||
private String firstUnknownSearchWord = "";
|
||||
private List<String> otherUnknownWords = new ArrayList<>();
|
||||
private boolean lastUnknownSearchWordComplete;
|
||||
|
||||
// Main unknown word used for search
|
||||
private String mainUnknownWordToSearch = null;
|
||||
private boolean mainUnknownSearchWordComplete;
|
||||
|
||||
// Name Searchers
|
||||
private NameStringMatcher firstUnknownNameStringMatcher;
|
||||
private NameStringMatcher mainUnknownNameStringMatcher;
|
||||
private List<NameStringMatcher> unknownWordsMatcher = new ArrayList<>();
|
||||
|
||||
private QuadRect cache1kmRect;
|
||||
|
||||
static {
|
||||
// the
|
||||
conjunctions.add("the");
|
||||
|
@ -140,7 +149,7 @@ public class SearchPhrase {
|
|||
}
|
||||
|
||||
|
||||
public SearchPhrase(SearchSettings settings, Collator clt) {
|
||||
private SearchPhrase(SearchSettings settings, Collator clt) {
|
||||
this.settings = settings;
|
||||
this.clt = clt;
|
||||
}
|
||||
|
@ -149,83 +158,160 @@ public class SearchPhrase {
|
|||
return clt;
|
||||
}
|
||||
|
||||
|
||||
public SearchPhrase generateNewPhrase(String text, SearchSettings settings) {
|
||||
SearchPhrase sp = new SearchPhrase(settings, this.clt);
|
||||
String restText = text;
|
||||
String textToSearch = text;
|
||||
List<SearchWord> leftWords = this.words;
|
||||
String thisTxt = getText(true);
|
||||
List<SearchWord> foundWords = new ArrayList<>();
|
||||
if (text.startsWith(thisTxt)) {
|
||||
// string is longer
|
||||
restText = text.substring(getText(false).length());
|
||||
sp.words = new ArrayList<>(this.words);
|
||||
textToSearch = text.substring(getText(false).length());
|
||||
foundWords.addAll(this.words);
|
||||
leftWords = leftWords.subList(leftWords.size(), leftWords.size());
|
||||
}
|
||||
for(SearchWord w : leftWords) {
|
||||
if(restText.startsWith(w.getWord() + DELIMITER)) {
|
||||
sp.words.add(w);
|
||||
restText = restText.substring(w.getWord().length() + DELIMITER.length());
|
||||
for (SearchWord w : leftWords) {
|
||||
if (textToSearch.startsWith(w.getWord() + DELIMITER)) {
|
||||
foundWords.add(w);
|
||||
textToSearch = textToSearch.substring(w.getWord().length() + DELIMITER.length());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sp.rawUnknownSearchPhrase = text;
|
||||
sp.unknownSearchPhrase = restText;
|
||||
sp.unknownWords.clear();
|
||||
sp.unknownWordsMatcher.clear();
|
||||
SearchPhrase sp = createNewSearchPhrase(settings, text, foundWords, textToSearch);
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
||||
public static SearchPhrase emptyPhrase() {
|
||||
return emptyPhrase(null);
|
||||
}
|
||||
|
||||
public static SearchPhrase emptyPhrase(SearchSettings settings) {
|
||||
return emptyPhrase(settings, OsmAndCollator.primaryCollator());
|
||||
}
|
||||
|
||||
public static SearchPhrase emptyPhrase(SearchSettings settings, Collator clt) {
|
||||
return new SearchPhrase(settings, clt);
|
||||
}
|
||||
|
||||
// init search phrase
|
||||
private SearchPhrase createNewSearchPhrase(SearchSettings settings, String fullText, List<SearchWord> foundWords,
|
||||
String textToSearch) {
|
||||
SearchPhrase sp = new SearchPhrase(settings, this.clt);
|
||||
sp.words = foundWords;
|
||||
sp.fullTextSearchPhrase = fullText;
|
||||
sp.unknownSearchPhrase = textToSearch;
|
||||
|
||||
if (!reg.matcher(restText).find()) {
|
||||
sp.unknownSearchWordTrim = sp.unknownSearchPhrase.trim();
|
||||
if (!reg.matcher(textToSearch).find()) {
|
||||
sp.firstUnknownSearchWord = sp.unknownSearchPhrase.trim();
|
||||
} else {
|
||||
sp.unknownSearchWordTrim = "";
|
||||
String[] ws = restText.split(ALLDELIMITERS);
|
||||
sp.firstUnknownSearchWord = "";
|
||||
String[] ws = textToSearch.split(ALLDELIMITERS);
|
||||
boolean first = true;
|
||||
for (int i = 0; i < ws.length ; i++) {
|
||||
String wd = ws[i].trim();
|
||||
if (wd.length() > 0 && !conjunctions.contains(wd.toLowerCase())) {
|
||||
if (first) {
|
||||
sp.unknownSearchWordTrim = wd;
|
||||
sp.firstUnknownSearchWord = wd;
|
||||
first = false;
|
||||
} else {
|
||||
sp.unknownWords.add(wd);
|
||||
sp.otherUnknownWords.add(wd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sp.lastUnknownSearchWordComplete = false;
|
||||
if (text.length() > 0 ) {
|
||||
char ch = text.charAt(text.length() - 1);
|
||||
sp.lastUnknownSearchWordComplete = ch == ' ' || ch == ',' || ch == '\r' || ch == '\n'
|
||||
|| ch == ';';
|
||||
}
|
||||
|
||||
sp.lastUnknownSearchWordComplete = isTextComplete(fullText) ;
|
||||
return sp;
|
||||
}
|
||||
|
||||
public SearchPhrase selectWord(SearchResult res, List<String> unknownWords, boolean lastComplete) {
|
||||
SearchPhrase sp = new SearchPhrase(this.settings, this.clt);
|
||||
addResult(res, sp);
|
||||
SearchResult prnt = res.parentSearchResult;
|
||||
while (prnt != null) {
|
||||
addResult(prnt, sp);
|
||||
prnt = prnt.parentSearchResult;
|
||||
}
|
||||
sp.words.addAll(0, this.words);
|
||||
if (unknownWords != null) {
|
||||
sp.lastUnknownSearchWordComplete = lastComplete;
|
||||
StringBuilder genUnknownSearchPhrase = new StringBuilder();
|
||||
for (int i = 0; i < unknownWords.size(); i++) {
|
||||
if (i == 0) {
|
||||
sp.firstUnknownSearchWord = unknownWords.get(0);
|
||||
} else {
|
||||
sp.otherUnknownWords.add(unknownWords.get(i));
|
||||
}
|
||||
genUnknownSearchPhrase.append(unknownWords.get(i)).append(" ");
|
||||
}
|
||||
sp.fullTextSearchPhrase = fullTextSearchPhrase;
|
||||
sp.unknownSearchPhrase = genUnknownSearchPhrase.toString().trim();
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
||||
private void calcMainUnknownWordToSearch() {
|
||||
if (mainUnknownWordToSearch != null) {
|
||||
return;
|
||||
}
|
||||
List<String> unknownSearchWords = otherUnknownWords;
|
||||
mainUnknownWordToSearch = firstUnknownSearchWord;
|
||||
mainUnknownSearchWordComplete = lastUnknownSearchWordComplete;
|
||||
if (unknownSearchWords.size() > 0) {
|
||||
mainUnknownSearchWordComplete = true;
|
||||
List<String> searchWords = new ArrayList<>(unknownSearchWords);
|
||||
searchWords.add(0, getFirstUnknownSearchWord());
|
||||
Collections.sort(searchWords, commonWordsComparator);
|
||||
for (String s : searchWords) {
|
||||
if (s.length() > 0 && !Character.isDigit(s.charAt(0)) && !LocationParser.isValidOLC(s)) {
|
||||
mainUnknownWordToSearch = s.trim();
|
||||
int unknownInd = unknownSearchWords.indexOf(s);
|
||||
if (!lastUnknownSearchWordComplete && unknownSearchWords.size() - 1 == unknownInd) {
|
||||
mainUnknownSearchWordComplete = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<SearchWord> getWords() {
|
||||
return words;
|
||||
}
|
||||
|
||||
|
||||
public boolean isUnknownSearchWordComplete() {
|
||||
return lastUnknownSearchWordComplete || unknownWords.size() > 0 || unknownSearchWordPoiType != null;
|
||||
public boolean isMainUnknownSearchWordComplete() {
|
||||
// return lastUnknownSearchWordComplete || otherUnknownWords.size() > 0 || unknownSearchWordPoiType != null;
|
||||
// TODO unknownSearchWordPoiType != null;!!!
|
||||
return mainUnknownSearchWordComplete;
|
||||
}
|
||||
|
||||
|
||||
public boolean isLastUnknownSearchWordComplete() {
|
||||
return lastUnknownSearchWordComplete;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getUnknownSearchWords() {
|
||||
return unknownWords;
|
||||
}
|
||||
|
||||
public NameStringMatcher getFullUnknownNameMatcher() {
|
||||
// TODO investigate diesel 95
|
||||
if (isLastUnknownSearchWordComplete() || hasMoreThanOneUnknownSearchWord()) {
|
||||
return new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.TRIM_AND_CHECK_ONLY_STARTS_WITH);
|
||||
} else {
|
||||
return new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMoreThanOneUnknownSearchWord() {
|
||||
return otherUnknownWords.size() > 0;
|
||||
}
|
||||
|
||||
public List<String> getUnknownSearchWords(Collection<String> exclude) {
|
||||
if(exclude == null || unknownWords.size() == 0 || exclude.size() == 0) {
|
||||
return unknownWords;
|
||||
if(exclude == null || otherUnknownWords.size() == 0 || exclude.size() == 0) {
|
||||
return otherUnknownWords;
|
||||
}
|
||||
List<String> l = new ArrayList<>();
|
||||
for(String uw : unknownWords) {
|
||||
for(String uw : otherUnknownWords) {
|
||||
if(exclude == null || !exclude.contains(uw)) {
|
||||
l.add(uw);
|
||||
}
|
||||
|
@ -234,12 +320,12 @@ public class SearchPhrase {
|
|||
}
|
||||
|
||||
|
||||
public String getUnknownSearchWord() {
|
||||
return unknownSearchWordTrim;
|
||||
public String getFirstUnknownSearchWord() {
|
||||
return firstUnknownSearchWord;
|
||||
}
|
||||
|
||||
public String getRawUnknownSearchPhrase() {
|
||||
return rawUnknownSearchPhrase;
|
||||
public String getFullSearchPhrase() {
|
||||
return fullTextSearchPhrase;
|
||||
}
|
||||
|
||||
public String getUnknownSearchPhrase() {
|
||||
|
@ -247,66 +333,9 @@ public class SearchPhrase {
|
|||
}
|
||||
|
||||
public boolean isUnknownSearchWordPresent() {
|
||||
return unknownSearchWordTrim.length() > 0;
|
||||
return firstUnknownSearchWord.length() > 0;
|
||||
}
|
||||
|
||||
public int getUnknownSearchWordLength() {
|
||||
return unknownSearchWordTrim.length() ;
|
||||
}
|
||||
|
||||
public AbstractPoiType getUnknownSearchWordPoiType() {
|
||||
return unknownSearchWordPoiType;
|
||||
}
|
||||
|
||||
public void setUnknownSearchWordPoiType(AbstractPoiType unknownSearchWordPoiType) {
|
||||
this.unknownSearchWordPoiType = unknownSearchWordPoiType;
|
||||
}
|
||||
|
||||
public boolean hasUnknownSearchWordPoiType() {
|
||||
return unknownSearchWordPoiType != null;
|
||||
}
|
||||
|
||||
public String getPoiNameFilter() {
|
||||
return getPoiNameFilter(unknownSearchWordPoiType);
|
||||
}
|
||||
|
||||
public boolean hasUnknownSearchWordPoiTypes() {
|
||||
return unknownSearchWordPoiTypes != null && unknownSearchWordPoiTypes.size() > 0;
|
||||
}
|
||||
|
||||
public List<AbstractPoiType> getUnknownSearchWordPoiTypes() {
|
||||
return unknownSearchWordPoiTypes;
|
||||
}
|
||||
|
||||
public void setUnknownSearchWordPoiTypes(List<AbstractPoiType> unknownSearchWordPoiTypes) {
|
||||
this.unknownSearchWordPoiTypes = unknownSearchWordPoiTypes;
|
||||
for (AbstractPoiType pt : unknownSearchWordPoiTypes) {
|
||||
if (getPoiNameFilter(pt) != null) {
|
||||
setUnknownSearchWordPoiType(pt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getPoiNameFilter(AbstractPoiType pt) {
|
||||
String nameFilter = null;
|
||||
if (pt != null) {
|
||||
NameStringMatcher nm = getNameStringMatcher(getUnknownSearchWord(), true);
|
||||
String unknownSearchPhrase = getUnknownSearchPhrase();
|
||||
String enTranslation = pt.getEnTranslation();
|
||||
String translation = pt.getTranslation();
|
||||
String synonyms = pt.getSynonyms();
|
||||
if (unknownSearchPhrase.length() >= enTranslation.length() && nm.matches(enTranslation)) {
|
||||
nameFilter = unknownSearchPhrase.substring(enTranslation.length()).trim();
|
||||
} else if (unknownSearchPhrase.length() >= translation.length() && nm.matches(translation)) {
|
||||
nameFilter = unknownSearchPhrase.substring(translation.length()).trim();
|
||||
} else if (unknownSearchPhrase.length() >= synonyms.length() && nm.matches(synonyms)) {
|
||||
nameFilter = unknownSearchPhrase.substring(synonyms.length()).trim();
|
||||
}
|
||||
}
|
||||
return nameFilter;
|
||||
}
|
||||
|
||||
public QuadRect getRadiusBBoxToSearch(int radius) {
|
||||
int radiusInMeters = getRadiusSearch(radius);
|
||||
QuadRect cache1kmRect = get1km31Rect();
|
||||
|
@ -459,31 +488,6 @@ public class SearchPhrase {
|
|||
return selectWord(res, null, false);
|
||||
}
|
||||
|
||||
public SearchPhrase selectWord(SearchResult res, List<String> unknownWords, boolean lastComplete) {
|
||||
SearchPhrase sp = new SearchPhrase(this.settings, this.clt);
|
||||
addResult(res, sp);
|
||||
SearchResult prnt = res.parentSearchResult;
|
||||
while (prnt != null) {
|
||||
addResult(prnt, sp);
|
||||
prnt = prnt.parentSearchResult;
|
||||
}
|
||||
sp.words.addAll(0, this.words);
|
||||
if (unknownWords != null) {
|
||||
sp.lastUnknownSearchWordComplete = lastComplete;
|
||||
StringBuilder genUnknownSearchPhrase = new StringBuilder();
|
||||
for (int i = 0; i < unknownWords.size(); i++) {
|
||||
if (i == 0) {
|
||||
sp.unknownSearchWordTrim = unknownWords.get(0);
|
||||
} else {
|
||||
sp.unknownWords.add(unknownWords.get(i));
|
||||
}
|
||||
genUnknownSearchPhrase.append(unknownWords.get(i)).append(" ");
|
||||
}
|
||||
|
||||
sp.rawUnknownSearchPhrase = sp.unknownSearchPhrase = genUnknownSearchPhrase.toString().trim();
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
private void addResult(SearchResult res, SearchPhrase sp) {
|
||||
SearchWord sw = new SearchWord(res.wordsSpan != null ? res.wordsSpan : res.localeName.trim(), res);
|
||||
|
@ -513,16 +517,32 @@ public class SearchPhrase {
|
|||
return null;
|
||||
}
|
||||
|
||||
public NameStringMatcher getNameStringMatcher() {
|
||||
if(sm != null) {
|
||||
return sm;
|
||||
public NameStringMatcher getMainUnknownNameStringMatcher() {
|
||||
calcMainUnknownWordToSearch();
|
||||
if (mainUnknownNameStringMatcher == null) {
|
||||
mainUnknownNameStringMatcher = getNameStringMatcher(mainUnknownWordToSearch, mainUnknownSearchWordComplete);
|
||||
}
|
||||
sm = getNameStringMatcher(unknownSearchWordTrim, lastUnknownSearchWordComplete);
|
||||
return sm;
|
||||
return mainUnknownNameStringMatcher;
|
||||
}
|
||||
|
||||
public NameStringMatcher getFirstUnknownNameStringMatcher() {
|
||||
if (firstUnknownNameStringMatcher == null) {
|
||||
firstUnknownNameStringMatcher = getNameStringMatcher(firstUnknownSearchWord, lastUnknownSearchWordComplete);
|
||||
}
|
||||
return firstUnknownNameStringMatcher;
|
||||
}
|
||||
|
||||
public NameStringMatcher getUnknownNameStringMatcher(int i) {
|
||||
while (unknownWordsMatcher.size() <= i) {
|
||||
int ind = unknownWordsMatcher.size() - 1;
|
||||
boolean completeMatch = ind < otherUnknownWords.size() - 1 || isLastUnknownSearchWordComplete();
|
||||
unknownWordsMatcher.add(getNameStringMatcher(otherUnknownWords.get(ind), completeMatch));
|
||||
}
|
||||
return unknownWordsMatcher.get(i);
|
||||
}
|
||||
|
||||
|
||||
public NameStringMatcher getNameStringMatcher(String word, boolean complete) {
|
||||
private NameStringMatcher getNameStringMatcher(String word, boolean complete) {
|
||||
return new NameStringMatcher(word,
|
||||
(complete ?
|
||||
StringMatcherMode.CHECK_EQUALS_FROM_SPACE :
|
||||
|
@ -544,12 +564,12 @@ public class SearchPhrase {
|
|||
}
|
||||
}
|
||||
|
||||
public String getText(boolean includeLastWord) {
|
||||
public String getText(boolean includeUnknownPart) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(SearchWord s : words) {
|
||||
sb.append(s.getWord()).append(DELIMITER.trim() + " ");
|
||||
sb.append(s.getWord()).append(DELIMITER);
|
||||
}
|
||||
if(includeLastWord) {
|
||||
if(includeUnknownPart) {
|
||||
sb.append(unknownSearchPhrase);
|
||||
}
|
||||
return sb.toString();
|
||||
|
@ -558,11 +578,11 @@ public class SearchPhrase {
|
|||
public String getTextWithoutLastWord() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<SearchWord> words = new ArrayList<>(this.words);
|
||||
if(Algorithms.isEmpty(unknownSearchWordTrim) && words.size() > 0) {
|
||||
if (Algorithms.isEmpty(unknownSearchPhrase.trim()) && words.size() > 0) {
|
||||
words.remove(words.size() - 1);
|
||||
}
|
||||
for(SearchWord s : words) {
|
||||
sb.append(s.getWord()).append(DELIMITER.trim() + " ");
|
||||
sb.append(s.getWord()).append(DELIMITER);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -705,8 +725,8 @@ public class SearchPhrase {
|
|||
|
||||
private CollatorStringMatcher sm;
|
||||
|
||||
public NameStringMatcher(String lastWordTrim, StringMatcherMode mode) {
|
||||
sm = new CollatorStringMatcher(lastWordTrim, mode);
|
||||
public NameStringMatcher(String namePart, StringMatcherMode mode) {
|
||||
sm = new CollatorStringMatcher(namePart, mode);
|
||||
}
|
||||
|
||||
public boolean matches(Collection<String> map) {
|
||||
|
@ -728,35 +748,32 @@ public class SearchPhrase {
|
|||
|
||||
}
|
||||
|
||||
public void countUnknownWordsMatch(SearchResult sr) {
|
||||
public void countUnknownWordsMatchMainResult(SearchResult sr) {
|
||||
countUnknownWordsMatch(sr, sr.localeName, sr.otherNames);
|
||||
}
|
||||
|
||||
|
||||
public void countUnknownWordsMatch(SearchResult sr, String localeName, Collection<String> otherNames) {
|
||||
if (unknownWords.size() > 0) {
|
||||
for (int i = 0; i < unknownWords.size(); i++) {
|
||||
if (unknownWordsMatcher.size() == i) {
|
||||
unknownWordsMatcher.add(new NameStringMatcher(unknownWords.get(i),
|
||||
i < unknownWords.size() - 1 || isLastUnknownSearchWordComplete()
|
||||
? StringMatcherMode.CHECK_EQUALS_FROM_SPACE
|
||||
: StringMatcherMode.CHECK_STARTS_FROM_SPACE));
|
||||
}
|
||||
NameStringMatcher ms = unknownWordsMatcher.get(i);
|
||||
if (otherUnknownWords.size() > 0) {
|
||||
for (int i = 0; i < otherUnknownWords.size(); i++) {
|
||||
NameStringMatcher ms = getUnknownNameStringMatcher(i);
|
||||
if (ms.matches(localeName) || ms.matches(otherNames)) {
|
||||
if (sr.otherWordsMatch == null) {
|
||||
sr.otherWordsMatch = new TreeSet<>();
|
||||
}
|
||||
sr.otherWordsMatch.add(unknownWords.get(i));
|
||||
sr.otherWordsMatch.add(otherUnknownWords.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!sr.firstUnknownWordMatches) {
|
||||
sr.firstUnknownWordMatches = localeName.equals(getUnknownSearchWord()) ||
|
||||
getNameStringMatcher().matches(localeName) ||
|
||||
getNameStringMatcher().matches(otherNames);
|
||||
sr.firstUnknownWordMatches = localeName.equals(getFirstUnknownSearchWord()) ||
|
||||
getFirstUnknownNameStringMatcher().matches(localeName) ||
|
||||
getFirstUnknownNameStringMatcher().matches(otherNames);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public int getRadiusSearch(int meters, int radiusLevel) {
|
||||
int res = meters;
|
||||
for(int k = 0; k < radiusLevel; k++) {
|
||||
|
@ -777,17 +794,38 @@ public class SearchPhrase {
|
|||
return (x < y) ? -1 : ((x == y) ? 0 : 1);
|
||||
}
|
||||
|
||||
public String getUnknownWordToSearchBuilding() {
|
||||
List<String> unknownSearchWords = getUnknownSearchWords();
|
||||
if(unknownSearchWords.size() > 0 && Algorithms.extractFirstIntegerNumber(getUnknownSearchWord()) == 0) {
|
||||
for(String wrd : unknownSearchWords) {
|
||||
if(Algorithms.extractFirstIntegerNumber(wrd) != 0) {
|
||||
return wrd;
|
||||
private int getUnknownWordToSearchBuildingInd() {
|
||||
if (otherUnknownWords.size() > 0 && Algorithms.extractFirstIntegerNumber(getFirstUnknownSearchWord()) == 0) {
|
||||
int ind = 0;
|
||||
for (String wrd : otherUnknownWords) {
|
||||
ind++;
|
||||
if (Algorithms.extractFirstIntegerNumber(wrd) != 0) {
|
||||
return ind;
|
||||
}
|
||||
}
|
||||
}
|
||||
return getUnknownSearchWord();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public NameStringMatcher getUnknownWordToSearchBuildingNameMatcher() {
|
||||
int ind = getUnknownWordToSearchBuildingInd();
|
||||
if(ind > 0) {
|
||||
return getUnknownNameStringMatcher(ind - 1);
|
||||
} else {
|
||||
return getFirstUnknownNameStringMatcher();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnknownWordToSearchBuilding() {
|
||||
int ind = getUnknownWordToSearchBuildingInd();
|
||||
if(ind > 0) {
|
||||
return otherUnknownWords.get(ind - 1);
|
||||
} else {
|
||||
return firstUnknownSearchWord;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static int lengthWithoutNumbers(String s) {
|
||||
int len = 0;
|
||||
|
@ -802,19 +840,18 @@ public class SearchPhrase {
|
|||
}
|
||||
|
||||
public String getUnknownWordToSearch() {
|
||||
List<String> unknownSearchWords = getUnknownSearchWords();
|
||||
String wordToSearch = getUnknownSearchWord();
|
||||
if (unknownSearchWords.size() > 0) {
|
||||
List<String> searchWords = new ArrayList<>(unknownSearchWords);
|
||||
searchWords.add(0, getUnknownSearchWord());
|
||||
Collections.sort(searchWords, commonWordsComparator);
|
||||
for (String s : searchWords) {
|
||||
if (s.length() > 0 && !Character.isDigit(s.charAt(0)) && !LocationParser.isValidOLC(s)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
calcMainUnknownWordToSearch();
|
||||
return mainUnknownWordToSearch;
|
||||
}
|
||||
|
||||
private boolean isTextComplete(String fullText) {
|
||||
boolean lastUnknownSearchWordComplete = false;
|
||||
if (fullText.length() > 0 ) {
|
||||
char ch = fullText.charAt(fullText.length() - 1);
|
||||
lastUnknownSearchWordComplete = ch == ' ' || ch == ',' || ch == '\r' || ch == '\n'
|
||||
|| ch == ';';
|
||||
}
|
||||
return wordToSearch;
|
||||
return lastUnknownSearchWordComplete;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,18 +16,33 @@ import java.util.Collection;
|
|||
public class SearchResult {
|
||||
// search phrase that makes search result valid
|
||||
public SearchPhrase requiredSearchPhrase;
|
||||
|
||||
// internal package fields (used for sorting)
|
||||
public SearchResult parentSearchResult;
|
||||
String wordsSpan ;
|
||||
// TODO
|
||||
boolean firstUnknownWordMatches = true;
|
||||
Collection<String> otherWordsMatch = null;
|
||||
boolean unknownPhraseMatches = false;
|
||||
|
||||
|
||||
public Object object;
|
||||
public ObjectType objectType;
|
||||
public BinaryMapIndexReader file;
|
||||
|
||||
|
||||
public double priority;
|
||||
public double priorityDistance;
|
||||
public String wordsSpan ;
|
||||
public SearchResult parentSearchResult;
|
||||
public Collection<String> otherWordsMatch = null;
|
||||
public boolean firstUnknownWordMatches = true;
|
||||
public boolean unknownPhraseMatches = false;
|
||||
|
||||
public LatLon location;
|
||||
public int preferredZoom = 15;
|
||||
|
||||
public String localeName;
|
||||
public String alternateName;
|
||||
public Collection<String> otherNames;
|
||||
|
||||
public String localeRelatedObjectName;
|
||||
public Object relatedObject;
|
||||
public double distRelatedObjectName;
|
||||
|
||||
public SearchResult(SearchPhrase sp) {
|
||||
this.requiredSearchPhrase = sp;
|
||||
|
@ -40,9 +55,14 @@ public class SearchResult {
|
|||
res = ObjectType.getTypeWeight(objectType);
|
||||
}
|
||||
if (parentSearchResult != null) {
|
||||
// TODO
|
||||
// 10 > maximum type
|
||||
// res = Math.max(res,parentSearchResult.getUnknownPhraseMatchWeight()) ;
|
||||
res += parentSearchResult.getUnknownPhraseMatchWeight() / 10;
|
||||
// double x = parentSearchResult.getUnknownPhraseMatchWeight();
|
||||
// if (x == 0) {
|
||||
// return 0;
|
||||
// }
|
||||
// res = Math.max(res, parentSearchResult.getUnknownPhraseMatchWeight());
|
||||
res += parentSearchResult.getUnknownPhraseMatchWeight() / 10;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -77,16 +97,6 @@ public class SearchResult {
|
|||
return priority - 1 / (1 + pd * distance);
|
||||
}
|
||||
|
||||
public LatLon location;
|
||||
public int preferredZoom = 15;
|
||||
public String localeName;
|
||||
public String alternateName;
|
||||
|
||||
public Collection<String> otherNames;
|
||||
|
||||
public String localeRelatedObjectName;
|
||||
public Object relatedObject;
|
||||
public double distRelatedObjectName;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
|
|
@ -17,7 +17,7 @@ public class LocationSearchTest {
|
|||
private void search(String string, LatLon latLon) throws IOException {
|
||||
SearchResultMatcher srm = new SearchUICore.SearchResultMatcher(null, null, 0, null, 100);
|
||||
new SearchCoreFactory.SearchLocationAndUrlAPI().
|
||||
search(new SearchPhrase(null, OsmAndCollator.primaryCollator()).generateNewPhrase(string, null), srm);
|
||||
search(SearchPhrase.emptyPhrase().generateNewPhrase(string, null), srm);
|
||||
Assert.assertEquals(1, srm.getRequestResults().size());
|
||||
Assert.assertEquals(latLon, srm.getRequestResults().get(0).location);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import org.junit.Assert;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.osmand.OsmAndCollator;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.search.SearchUICore.SearchResultCollection;
|
||||
import net.osmand.search.core.SearchPhrase;
|
||||
|
@ -29,7 +28,7 @@ public class SearchUICoreGenericTest {
|
|||
public void testDuplicates() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchPhrase phrase = SearchPhrase.emptyPhrase(ss);
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
|
@ -47,7 +46,7 @@ public class SearchUICoreGenericTest {
|
|||
public void testNoResort() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchPhrase phrase = SearchPhrase.emptyPhrase(ss);
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
|
@ -80,7 +79,7 @@ public class SearchUICoreGenericTest {
|
|||
public void testNoResortDuplicate() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchPhrase phrase = SearchPhrase.emptyPhrase(ss);
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
|
|
|
@ -152,7 +152,7 @@ public class SearchUICoreTest {
|
|||
SearchSettings s = SearchSettings.parseJSON(settingsJson);
|
||||
s.setOfflineIndexes(Collections.singletonList(reader));
|
||||
|
||||
SearchPhrase phrase = new SearchPhrase(s, OsmAndCollator.primaryCollator());
|
||||
SearchPhrase phrase = SearchPhrase.emptyPhrase(s);
|
||||
phrase = phrase.generateNewPhrase(phraseText, s);
|
||||
|
||||
final SearchUICore core = new SearchUICore(MapPoiTypes.getDefault(), "en", false);
|
||||
|
|
|
@ -351,11 +351,11 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
cancelSearch();
|
||||
SearchPhrase searchPhrase = searchUICore.getPhrase();
|
||||
if (foundPartialLocation) {
|
||||
QuickSearchCoordinatesFragment.showDialog(QuickSearchDialogFragment.this, searchPhrase.getUnknownSearchWord());
|
||||
QuickSearchCoordinatesFragment.showDialog(QuickSearchDialogFragment.this, searchPhrase.getFirstUnknownSearchWord());
|
||||
} else if (searchPhrase.isNoSelectedType() || searchPhrase.isLastWord(POI_TYPE)) {
|
||||
PoiUIFilter filter;
|
||||
if (searchPhrase.isNoSelectedType()) {
|
||||
if (isOnlineSearch() && !Algorithms.isEmpty(searchPhrase.getUnknownSearchWord())) {
|
||||
if (isOnlineSearch() && !Algorithms.isEmpty(searchPhrase.getFirstUnknownSearchWord())) {
|
||||
app.getPoiFilters().resetNominatimFilters();
|
||||
filter = app.getPoiFilters().getNominatimPOIFilter();
|
||||
filter.setFilterByName(searchPhrase.getUnknownSearchPhrase());
|
||||
|
@ -369,8 +369,8 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
}
|
||||
} else {
|
||||
filter = app.getPoiFilters().getSearchByNamePOIFilter();
|
||||
if (!Algorithms.isEmpty(searchPhrase.getUnknownSearchWord())) {
|
||||
filter.setFilterByName(searchPhrase.getUnknownSearchWord());
|
||||
if (!Algorithms.isEmpty(searchPhrase.getFirstUnknownSearchWord())) {
|
||||
filter.setFilterByName(searchPhrase.getFirstUnknownSearchWord());
|
||||
filter.clearCurrentResults();
|
||||
}
|
||||
}
|
||||
|
@ -382,8 +382,8 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
.getResult().object;
|
||||
filter = new PoiUIFilter(abstractPoiType, app, "");
|
||||
}
|
||||
if (!Algorithms.isEmpty(searchPhrase.getUnknownSearchWord())) {
|
||||
filter.setFilterByName(searchPhrase.getUnknownSearchWord());
|
||||
if (!Algorithms.isEmpty(searchPhrase.getFirstUnknownSearchWord())) {
|
||||
filter.setFilterByName(searchPhrase.getFirstUnknownSearchWord());
|
||||
}
|
||||
} else {
|
||||
filter = (PoiUIFilter) searchPhrase.getLastSelectedWord().getResult().object;
|
||||
|
@ -628,9 +628,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
if (searchEditText.getText().length() > 0) {
|
||||
String newText = searchUICore.getPhrase().getTextWithoutLastWord();
|
||||
searchEditText.setText(newText);
|
||||
searchEditText.setSelection(newText.length());
|
||||
clearLastWord();
|
||||
} else if (useMapCenter && location != null) {
|
||||
useMapCenter = false;
|
||||
centerLatLon = null;
|
||||
|
|
|
@ -123,7 +123,7 @@ public class QuickSearchHelper implements ResourceListener {
|
|||
|
||||
public void refreshFilterOrders() {
|
||||
PoiFiltersHelper filtersHelper = app.getPoiFilters();
|
||||
core.setFilterOrders(filtersHelper.getPoiFilterOrders(true));
|
||||
core.setActivePoiFiltersByOrder(filtersHelper.getPoiFilterOrders(true));
|
||||
}
|
||||
|
||||
public void setRepositoriesForSearchUICore(final OsmandApplication app) {
|
||||
|
@ -353,7 +353,7 @@ public class QuickSearchHelper implements ResourceListener {
|
|||
public boolean search(SearchPhrase phrase, SearchResultMatcher matcher) throws IOException {
|
||||
double lat = phrase.getSettings().getOriginalLocation().getLatitude();
|
||||
double lon = phrase.getSettings().getOriginalLocation().getLongitude();
|
||||
String text = phrase.getRawUnknownSearchPhrase();
|
||||
String text = phrase.getFullSearchPhrase();
|
||||
filter.setFilterByName(text);
|
||||
publishAmenities(phrase, matcher, filter.initializeNewSearch(lat, lon,
|
||||
-1, null, phrase.getRadiusLevel() + 3));
|
||||
|
|
|
@ -785,13 +785,6 @@ public class QuickSearchDialogFragment extends DialogFragment implements SampleC
|
|||
runCoreSearch(txt, false, false);
|
||||
}
|
||||
|
||||
public void clearLastWord() {
|
||||
if (searchEditText.getText().length() > 0) {
|
||||
String newText = searchUICore.getPhrase().getTextWithoutLastWord();
|
||||
searchEditText.setText(newText);
|
||||
searchEditText.setSelection(newText.length());
|
||||
}
|
||||
}
|
||||
|
||||
private void addMoreButton() {
|
||||
QuickSearchMoreListItem moreListItem =
|
||||
|
|
Loading…
Reference in a new issue