Add aditional types to search
This commit is contained in:
parent
13d3741fea
commit
b540b5b2e7
1 changed files with 121 additions and 51 deletions
|
@ -35,6 +35,7 @@ import net.osmand.util.MapUtils;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -670,6 +671,11 @@ public class SearchCoreFactory {
|
|||
}
|
||||
}
|
||||
|
||||
protected static class PoiTypeResult {
|
||||
public AbstractPoiType pt;
|
||||
public Set<String> foundWords = new LinkedHashSet<String>();
|
||||
}
|
||||
|
||||
public static class SearchAmenityTypesAPI extends SearchBaseAPI {
|
||||
|
||||
public final static String STD_POI_FILTER_PREFIX = "std_";
|
||||
|
@ -704,68 +710,102 @@ public class SearchCoreFactory {
|
|||
}
|
||||
}
|
||||
|
||||
public Map<AbstractPoiType, List<String>> getPoiTypeResults(NameStringMatcher nm, boolean includeAdditionals) {
|
||||
Map<AbstractPoiType, List<String>> results = new LinkedHashMap<>();
|
||||
public Map<String, PoiTypeResult> getPoiTypeResults(NameStringMatcher nm, boolean includeAdditionals) {
|
||||
Map<String, PoiTypeResult> results = new LinkedHashMap<>();
|
||||
for (AbstractPoiType pf : topVisibleFilters) {
|
||||
checkPoiType(nm, pf, results);
|
||||
PoiTypeResult res = checkPoiType(nm, pf);
|
||||
if(res != null) {
|
||||
results.put(res.pt.getKeyName(), res);
|
||||
}
|
||||
}
|
||||
if (includeAdditionals) {
|
||||
addAditonals(nm, results, types.getOtherMapCategory());
|
||||
}
|
||||
for (PoiCategory c : categories) {
|
||||
checkPoiType(nm, c, results);
|
||||
PoiTypeResult res = checkPoiType(nm, c);
|
||||
if(res != null) {
|
||||
results.put(res.pt.getKeyName(), res);
|
||||
}
|
||||
if (includeAdditionals) {
|
||||
addAditonals(nm, results, 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()) {
|
||||
checkPoiType(nm, pt, results);
|
||||
List<PoiType> additionals = pt.getPoiAdditionals();
|
||||
if (additionals != null && includeAdditionals) {
|
||||
for (PoiType a : additionals) {
|
||||
if (!results.containsKey(a)) {
|
||||
String enTranslation = a.getEnTranslation().toLowerCase();
|
||||
if (!"yes".equals(enTranslation) && !"no".equals(enTranslation)) {
|
||||
checkPoiType(nm, a, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pt.getCategory() != types.getOtherMapCategory() && !pt.isReference()) {
|
||||
PoiTypeResult res = checkPoiType(nm, pt);
|
||||
if(res != null) {
|
||||
results.put(res.pt.getKeyName(), res);
|
||||
}
|
||||
if (includeAdditionals) {
|
||||
addAditonals(nm, results, pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private void checkPoiType(NameStringMatcher nm, AbstractPoiType pf, Map<AbstractPoiType, List<String>> results) {
|
||||
List<String> lst = results.get(pf);
|
||||
boolean nl = lst == null;
|
||||
private void addAditonals(NameStringMatcher nm, Map<String, PoiTypeResult> results, AbstractPoiType pt) {
|
||||
List<PoiType> additionals = pt.getPoiAdditionals();
|
||||
if (additionals != null) {
|
||||
for (PoiType a : additionals) {
|
||||
PoiTypeResult existingResult = results.get(a.getKeyName());
|
||||
if (existingResult != null) {
|
||||
PoiAdditionalCustomFilter f ;
|
||||
if (existingResult.pt instanceof PoiAdditionalCustomFilter) {
|
||||
f = (PoiAdditionalCustomFilter) existingResult.pt;
|
||||
} else {
|
||||
f = new PoiAdditionalCustomFilter(types, (PoiType) existingResult.pt);
|
||||
}
|
||||
f.additionalPoiTypes.add(a);
|
||||
existingResult.pt = f;
|
||||
} else {
|
||||
String enTranslation = a.getEnTranslation().toLowerCase();
|
||||
if (!"no".equals(enTranslation) // && !"yes".equals(enTranslation)
|
||||
) {
|
||||
PoiTypeResult ptr = checkPoiType(nm, a);
|
||||
if (ptr != null) {
|
||||
results.put(a.getKeyName(), ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PoiTypeResult checkPoiType(NameStringMatcher nm, AbstractPoiType pf) {
|
||||
PoiTypeResult res = null;
|
||||
if (nm.matches(pf.getTranslation())) {
|
||||
lst = addToList(pf.getTranslation(), lst);
|
||||
res = addIfMatch(nm, pf.getTranslation(), pf, res);
|
||||
}
|
||||
if (nm.matches(pf.getEnTranslation())) {
|
||||
lst = addToList(pf.getEnTranslation(), lst);
|
||||
res = addIfMatch(nm, pf.getEnTranslation(), pf, res);
|
||||
}
|
||||
if (nm.matches(pf.getKeyName())) {
|
||||
lst = addToList(pf.getKeyName().replace('_', ' '), lst);
|
||||
res = addIfMatch(nm, pf.getKeyName().replace('_', ' '), pf, res);
|
||||
}
|
||||
|
||||
if (nm.matches(pf.getSynonyms())) {
|
||||
String[] synonyms = pf.getSynonyms().split(";");
|
||||
for (String synonym : synonyms) {
|
||||
if (nm.matches(synonym)) {
|
||||
lst = addToList(synonym, lst);
|
||||
}
|
||||
res = addIfMatch(nm, synonym, pf, res);
|
||||
}
|
||||
}
|
||||
if(lst != null && nl) {
|
||||
results.put(pf, lst);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private List<String> addToList(String s, List<String> lst) {
|
||||
if(lst == null) {
|
||||
lst = new ArrayList<>();
|
||||
private PoiTypeResult addIfMatch(NameStringMatcher nm, String s, AbstractPoiType pf, PoiTypeResult res) {
|
||||
if (nm.matches(s)) {
|
||||
if (res == null) {
|
||||
res = new PoiTypeResult();
|
||||
res.pt = pf;
|
||||
}
|
||||
res.foundWords.add(s);
|
||||
|
||||
}
|
||||
lst.add(s);
|
||||
return lst;
|
||||
return res;
|
||||
}
|
||||
|
||||
private void initPoiTypes() {
|
||||
|
@ -792,11 +832,11 @@ public class SearchCoreFactory {
|
|||
|
||||
} else {
|
||||
boolean includeAdditional = !phrase.hasMoreThanOneUnknownSearchWord();
|
||||
Map<AbstractPoiType, List<String>> poiTypes = getPoiTypeResults(nm, includeAdditional);
|
||||
for (Entry<AbstractPoiType, List<String>> pt : poiTypes.entrySet()) {
|
||||
Map<String, PoiTypeResult> poiTypes = getPoiTypeResults(nm, includeAdditional);
|
||||
for (PoiTypeResult ptr : poiTypes.values()) {
|
||||
boolean match = !phrase.isFirstUnknownSearchWordComplete();
|
||||
if (!match) {
|
||||
for (String foundName : pt.getValue()) {
|
||||
for (String foundName : ptr.foundWords) {
|
||||
CollatorStringMatcher csm = new CollatorStringMatcher(foundName, StringMatcherMode.CHECK_ONLY_STARTS_WITH);
|
||||
match = csm.matches(phrase.getUnknownSearchPhrase());
|
||||
if (match) {
|
||||
|
@ -806,9 +846,9 @@ public class SearchCoreFactory {
|
|||
}
|
||||
if (match) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = pt.getKey().getTranslation();
|
||||
res.object = pt.getKey();
|
||||
addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(pt.getKey()),
|
||||
res.localeName = ptr.pt.getTranslation();
|
||||
res.object = ptr.pt;
|
||||
addPoiTypeResult(phrase, resultMatcher, showTopFiltersOnly, getStandardFilterId(ptr.pt),
|
||||
res);
|
||||
}
|
||||
}
|
||||
|
@ -826,7 +866,7 @@ public class SearchCoreFactory {
|
|||
}
|
||||
|
||||
private void addPoiTypeResult(SearchPhrase phrase, SearchResultMatcher resultMatcher, boolean showTopFiltersOnly,
|
||||
String stdFilterId , SearchResult res) {
|
||||
String stdFilterId, SearchResult res) {
|
||||
res.priorityDistance = 0;
|
||||
res.objectType = ObjectType.POI_TYPE;
|
||||
res.firstUnknownWordMatches = true;
|
||||
|
@ -919,7 +959,7 @@ public class SearchCoreFactory {
|
|||
SearchPoiTypeFilter poiTypeFilter = null;
|
||||
String nameFilter = null;
|
||||
int countExtraWords = 0;
|
||||
Map<String, PoiType> poiAdditionals = new LinkedHashMap<String, PoiType>();
|
||||
Set<String> poiAdditionals = new LinkedHashSet<>();
|
||||
if (phrase.isLastWord(ObjectType.POI_TYPE)) {
|
||||
Object obj = phrase.getLastSelectedWord().getResult().object;
|
||||
if (obj instanceof AbstractPoiType) {
|
||||
|
@ -933,10 +973,10 @@ public class SearchCoreFactory {
|
|||
} else if (searchAmenityTypesAPI != null && phrase.isFirstUnknownSearchWordComplete()) {
|
||||
NameStringMatcher nm = phrase.getFirstUnknownNameStringMatcher();
|
||||
searchAmenityTypesAPI.initPoiTypes();
|
||||
Map<AbstractPoiType, List<String>> poiTypeResults = searchAmenityTypesAPI.getPoiTypeResults(nm, true);
|
||||
Map<String, PoiTypeResult> poiTypeResults = searchAmenityTypesAPI.getPoiTypeResults(nm, true);
|
||||
// find first full match only
|
||||
for (Entry<AbstractPoiType, List<String>> poiType : poiTypeResults.entrySet()) {
|
||||
for (String foundName : poiType.getValue()) {
|
||||
for (PoiTypeResult poiTypeResult : poiTypeResults.values()) {
|
||||
for (String foundName : poiTypeResult.foundWords) {
|
||||
CollatorStringMatcher csm = new CollatorStringMatcher(foundName, StringMatcherMode.CHECK_ONLY_STARTS_WITH);
|
||||
// matches only completely
|
||||
int mwords = phrase.countWords(foundName) ;
|
||||
|
@ -953,8 +993,8 @@ public class SearchCoreFactory {
|
|||
nameFilter += otherSearchWords.get(k);
|
||||
}
|
||||
}
|
||||
poiTypeFilter = getPoiTypeFilter(poiType.getKey(), poiAdditionals);
|
||||
unselectedPoiType = poiType.getKey();
|
||||
poiTypeFilter = getPoiTypeFilter(poiTypeResult.pt, poiAdditionals);
|
||||
unselectedPoiType = poiTypeResult.pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -983,7 +1023,7 @@ public class SearchCoreFactory {
|
|||
private ResultMatcher<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchPoiTypeFilter poiTypeFilter,
|
||||
final SearchResultMatcher resultMatcher, final String nameFilter,
|
||||
final BinaryMapIndexReader selected, final Set<String> searchedPois,
|
||||
final Map<String, PoiType> poiAdditionals, final int countExtraWords) {
|
||||
final Collection<String> poiAdditionals, final int countExtraWords) {
|
||||
|
||||
|
||||
final NameStringMatcher ns = nameFilter == null ? null : new NameStringMatcher(nameFilter, StringMatcherMode.CHECK_STARTS_FROM_SPACE);
|
||||
|
@ -1004,7 +1044,7 @@ public class SearchCoreFactory {
|
|||
}
|
||||
if (!poiAdditionals.isEmpty()) {
|
||||
boolean found = false;
|
||||
for (String add : poiAdditionals.keySet()) {
|
||||
for (String add : poiAdditionals) {
|
||||
if(object.getAdditionalInfo().containsKey(add)) {
|
||||
found = true;
|
||||
break;
|
||||
|
@ -1058,13 +1098,13 @@ public class SearchCoreFactory {
|
|||
};
|
||||
}
|
||||
|
||||
private SearchPoiTypeFilter getPoiTypeFilter(AbstractPoiType pt, Map<String, PoiType> poiAdditionals ) {
|
||||
private SearchPoiTypeFilter getPoiTypeFilter(AbstractPoiType pt, Set<String> poiAdditionals ) {
|
||||
final Map<PoiCategory, LinkedHashSet<String>> acceptedTypes = new LinkedHashMap<PoiCategory,
|
||||
LinkedHashSet<String>>();
|
||||
pt.putTypes(acceptedTypes);
|
||||
poiAdditionals.clear();
|
||||
if (pt instanceof PoiType && ((PoiType) pt).isAdditional() && ((PoiType) pt).getParentType() != null) {
|
||||
poiAdditionals.put(pt.getKeyName(), (PoiType) pt);
|
||||
if (pt.isAdditional()) {
|
||||
poiAdditionals.add(pt.getKeyName());
|
||||
}
|
||||
return new SearchPoiTypeFilter() {
|
||||
|
||||
|
@ -1325,6 +1365,36 @@ public class SearchCoreFactory {
|
|||
}
|
||||
}
|
||||
|
||||
protected static class PoiAdditionalCustomFilter extends AbstractPoiType {
|
||||
|
||||
protected List<PoiType> additionalPoiTypes = new ArrayList<PoiType>();
|
||||
|
||||
public PoiAdditionalCustomFilter(MapPoiTypes registry, PoiType pt) {
|
||||
super(pt.getKeyName(), registry);
|
||||
additionalPoiTypes.add(pt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdditional() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Map<PoiCategory, LinkedHashSet<String>> putTypes(Map<PoiCategory, LinkedHashSet<String>> acceptedTypes) {
|
||||
for (PoiType p : additionalPoiTypes) {
|
||||
if (p.getParentType() == registry.getOtherMapCategory()) {
|
||||
for (PoiCategory c : registry.getCategories(false)) {
|
||||
c.putTypes(acceptedTypes);
|
||||
}
|
||||
} else {
|
||||
p.getParentType().putTypes(acceptedTypes);
|
||||
}
|
||||
|
||||
}
|
||||
return acceptedTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SearchLocationAndUrlAPI extends SearchBaseAPI {
|
||||
|
||||
private static final int OLC_RECALC_DISTANCE_THRESHOLD = 100000; // 100 km
|
||||
|
|
Loading…
Reference in a new issue