diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java index 359ab84468..ef53e7cf7e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java @@ -1,6 +1,7 @@ package net.osmand.search.core; +import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapAddressReaderAdapter; @@ -624,38 +625,27 @@ public class SearchCoreFactory { } } - public List getPoiTypeResults(NameStringMatcher nm, boolean includeAdditionals) { - List results = new ArrayList(); + public Map> getPoiTypeResults(NameStringMatcher nm, boolean includeAdditionals) { + Map> results = new LinkedHashMap<>(); for (AbstractPoiType pf : topVisibleFilters) { - if (nm.matches(pf.getTranslation()) || nm.matches(pf.getEnTranslation()) - || nm.matches(pf.getSynonyms())) { - results.add(pf); - } + checkPoiType(nm, pf, results); } for (PoiCategory c : categories) { - if (!results.contains(c) && (nm.matches(c.getTranslation()) || nm.matches(c.getEnTranslation()) - || nm.matches(c.getSynonyms()))) { - results.add(c); - } + checkPoiType(nm, c, results); } Iterator> it = translatedNames.entrySet().iterator(); while (it.hasNext()) { Entry 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); - } + checkPoiType(nm, pt, results); List additionals = pt.getPoiAdditionals(); if (additionals != null && includeAdditionals) { for (PoiType a : additionals) { - if (!results.contains(a)) { + if (!results.containsKey(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); + if (!"yes".equals(enTranslation) && !"no".equals(enTranslation)) { + checkPoiType(nm, a, results); } } } @@ -665,6 +655,33 @@ public class SearchCoreFactory { return results; } + private void checkPoiType(NameStringMatcher nm, AbstractPoiType pf, Map> results) { + List lst = results.get(pf); + if (nm.matches(pf.getTranslation())) { + lst = addToList(pf.getTranslation(), lst); + } + if (nm.matches(pf.getEnTranslation())) { + lst = addToList(pf.getEnTranslation(), lst); + } + + if (nm.matches(pf.getSynonyms())) { + String[] synonyms = pf.getSynonyms().split(";"); + for (String synonym : synonyms) { + if (nm.matches(synonym)) { + lst = addToList(synonym, lst); + } + } + } + } + + private List addToList(String s, List lst) { + if(lst == null) { + lst = new ArrayList<>(); + } + lst.add(s); + return lst; + } + private void initPoiTypes() { if (translatedNames.isEmpty()) { translatedNames = types.getAllTranslatedNames(false); @@ -678,15 +695,36 @@ public class SearchCoreFactory { boolean showTopFiltersOnly = !phrase.isUnknownSearchWordPresent(); NameStringMatcher nm = phrase.getFirstUnknownNameStringMatcher(); initPoiTypes(); - List 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); + if (showTopFiltersOnly) { + for (AbstractPoiType pt : topVisibleFilters) { + SearchResult res = new SearchResult(phrase); + res.localeName = pt.getTranslation(); + res.object = pt; + addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(pt), res); + } + + } else { + Map> poiTypes = getPoiTypeResults(nm, true); + for (Entry> pt : poiTypes.entrySet()) { + boolean match = !phrase.isFirstUnknownSearchWordComplete(); + if (!match) { + for (String foundName : pt.getValue()) { + CollatorStringMatcher csm = new CollatorStringMatcher(foundName, StringMatcherMode.CHECK_ONLY_STARTS_WITH); + match = csm.matches(phrase.getUnknownSearchPhrase()); + if (match) { + break; + } + } + // TODO properly count matching words + } + if (match) { + SearchResult res = new SearchResult(phrase); + res.localeName = pt.getKey().getTranslation(); + res.object = pt.getKey(); + addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(pt.getKey()), + res); + } + } } for (int i = 0; i < customPoiFilters.size(); i++) { CustomSearchPoiFilter csf = customPoiFilters.get(i); @@ -815,25 +853,31 @@ public class SearchCoreFactory { } else { throw new UnsupportedOperationException(); } - } else if (searchAmenityTypesAPI != null) { + } else if (searchAmenityTypesAPI != null && phrase.isFirstUnknownSearchWordComplete()) { NameStringMatcher nm = phrase.getFirstUnknownNameStringMatcher(); searchAmenityTypesAPI.initPoiTypes(); - List presentPoiTypes = searchAmenityTypesAPI.getPoiTypeResults(nm, false); - - // TODO get first ? !!! - // TODO SELECT WORD -// AbstractPoiType poiType = phrase.getUnknownSearchWordPoiType(); -// if (poiType != null) { -// poiTypeFilter = getPoiTypeFilter(poiType); -// nameFilter = phrase.getPoiNameFilter(poiType); -// if (nameFilter != null) { -// phrase.setUnknownSearchWordPoiType(poiType); -// } -// } -// unknownPhraseMatches = !phraseMatcher.matches(unknownSearchWordPoiType.getTranslation()) -// && !phraseMatcher.matches(unknownSearchWordPoiType.getEnTranslation()) -// && !phraseMatcher.matches(unknownSearchWordPoiType.getSynonyms()); -// } + Map> poiTypeResults = searchAmenityTypesAPI.getPoiTypeResults(nm, false); + // find first full match only + for (Entry> poiType : poiTypeResults.entrySet()) { + for (String foundName : poiType.getValue()) { + CollatorStringMatcher csm = new CollatorStringMatcher(foundName, StringMatcherMode.CHECK_ONLY_STARTS_WITH); + // matches only completely + if (csm.matches(phrase.getUnknownSearchPhrase())) { + int words = phrase.countWords(foundName) - 1; + List otherSearchWords = phrase.getUnknownSearchWords(null); + if (words < otherSearchWords.size()) { + nameFilter = ""; + for(int k = words; k < otherSearchWords.size(); k++) { + nameFilter = otherSearchWords.get(k) + SearchPhrase.DELIMITER; + } + nameFilter = nameFilter.trim(); + } + poiTypeFilter = getPoiTypeFilter(poiType.getKey()); + break; + } + } + } + // TODO count correctly matching words ! } if (poiTypeFilter != null) { QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS); diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java index 5e8a0e4092..6a4bfe9083 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java @@ -28,7 +28,7 @@ import java.util.regex.Pattern; // Immutable object ! public class SearchPhrase { - private static final String DELIMITER = " "; + public static final String DELIMITER = " "; private static final String ALLDELIMITERS = "\\s|,"; private static final Pattern reg = Pattern.compile(ALLDELIMITERS); private static Comparator commonWordsComparator; @@ -223,6 +223,18 @@ public class SearchPhrase { return sp; } + public int countWords(String w) { + String[] ws = w.split(ALLDELIMITERS); + int cnt = 0; + for (int i = 0; i < ws.length; i++) { + String wd = ws[i].trim(); + if (wd.length() > 0) { + cnt++; + } + } + return cnt; + } + public SearchPhrase selectWord(SearchResult res, List unknownWords, boolean lastComplete) { SearchPhrase sp = new SearchPhrase(this.settings, this.clt); addResult(res, sp); @@ -311,6 +323,10 @@ public class SearchPhrase { public String getFirstUnknownSearchWord() { return firstUnknownSearchWord; } + + public boolean isFirstUnknownSearchWordComplete() { + return hasMoreThanOneUnknownSearchWord() || isLastUnknownSearchWordComplete(); + } public String getFullSearchPhrase() { return fullTextSearchPhrase; @@ -843,4 +859,6 @@ public class SearchPhrase { } + + }