Merge pull request #4418 from osmandapp/PaulsBranch
Improved search for OSM Live
This commit is contained in:
commit
2a7e5741d3
7 changed files with 160 additions and 60 deletions
|
@ -26,6 +26,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
@ -405,7 +407,24 @@ public class BinaryMapIndexReader {
|
||||||
}
|
}
|
||||||
String ls = rg.get(0);
|
String ls = rg.get(0);
|
||||||
if (ls.lastIndexOf('_') != -1) {
|
if (ls.lastIndexOf('_') != -1) {
|
||||||
|
if (ls.matches(".*([0-9]+_*){3}\\.obf")) {
|
||||||
|
Pattern osmDiffDateEnding = Pattern.compile("_([0-9]+_*){3}\\.obf");
|
||||||
|
Matcher m = osmDiffDateEnding.matcher(ls);
|
||||||
|
if (m.find()) {
|
||||||
|
ls = ls.substring(0, m.start());
|
||||||
|
}
|
||||||
return ls.substring(0, ls.lastIndexOf('_')).replace('_', ' ');
|
return ls.substring(0, ls.lastIndexOf('_')).replace('_', ' ');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (ls.contains(".")) {
|
||||||
|
ls = ls.substring(0, ls.indexOf("."));
|
||||||
|
}
|
||||||
|
if (ls.endsWith("_2")) {
|
||||||
|
ls = ls.substring(0, ls.length() - "_2".length());
|
||||||
|
}
|
||||||
|
return ls.substring(0, ls.lastIndexOf('_')).replace('_', ' ');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return ls;
|
return ls;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ public class Amenity extends MapObject {
|
||||||
public static final String OPENING_HOURS = "opening_hours";
|
public static final String OPENING_HOURS = "opening_hours";
|
||||||
public static final String CONTENT = "content";
|
public static final String CONTENT = "content";
|
||||||
public static final String CUISINE = "cuisine";
|
public static final String CUISINE = "cuisine";
|
||||||
|
public static final String OSM_DELETE_VALUE = "delete";
|
||||||
|
public static final String OSM_DELETE_TAG = "osmand_change";
|
||||||
|
|
||||||
private String subType;
|
private String subType;
|
||||||
private PoiCategory type;
|
private PoiCategory type;
|
||||||
|
@ -307,4 +309,8 @@ public class Amenity extends MapObject {
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return OSM_DELETE_VALUE.equals(getAdditionalInfo(OSM_DELETE_TAG));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,18 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import gnu.trove.list.array.TIntArrayList;
|
import gnu.trove.list.array.TIntArrayList;
|
||||||
|
import gnu.trove.set.hash.TLongHashSet;
|
||||||
|
|
||||||
|
|
||||||
public class SearchCoreFactory {
|
public class SearchCoreFactory {
|
||||||
|
@ -486,6 +490,7 @@ public class SearchCoreFactory {
|
||||||
SearchPhraseDataType.POI);
|
SearchPhraseDataType.POI);
|
||||||
final NameStringMatcher nm = phrase.getNameStringMatcher();
|
final NameStringMatcher nm = phrase.getNameStringMatcher();
|
||||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE);
|
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE);
|
||||||
|
final Set<String> ids = new HashSet<String>();
|
||||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||||
(int)bbox.centerX(), (int)bbox.centerY(),
|
(int)bbox.centerX(), (int)bbox.centerY(),
|
||||||
phrase.getUnknownSearchWord(),
|
phrase.getUnknownSearchWord(),
|
||||||
|
@ -498,6 +503,10 @@ public class SearchCoreFactory {
|
||||||
if (limit ++ > LIMIT) {
|
if (limit ++ > LIMIT) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
String poiID = object.getType().getKeyName() + "_" + object.getId();
|
||||||
|
if (ids.contains(poiID)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
SearchResult sr = new SearchResult(phrase);
|
SearchResult sr = new SearchResult(phrase);
|
||||||
sr.otherNames = object.getAllNames(true);
|
sr.otherNames = object.getAllNames(true);
|
||||||
sr.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
sr.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||||
|
@ -523,6 +532,7 @@ public class SearchCoreFactory {
|
||||||
phrase.countUnknownWordsMatch(sr);
|
phrase.countUnknownWordsMatch(sr);
|
||||||
sr.objectType = ObjectType.POI;
|
sr.objectType = ObjectType.POI;
|
||||||
resultMatcher.publish(sr);
|
resultMatcher.publish(sr);
|
||||||
|
ids.add(poiID);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,8 +736,9 @@ public class SearchCoreFactory {
|
||||||
|
|
||||||
QuadRect bbox = phrase.getRadiusBBoxToSearch(10000);
|
QuadRect bbox = phrase.getRadiusBBoxToSearch(10000);
|
||||||
List<BinaryMapIndexReader> oo = phrase.getOfflineIndexes();
|
List<BinaryMapIndexReader> oo = phrase.getOfflineIndexes();
|
||||||
|
Set<String> searchedPois = new TreeSet<>();
|
||||||
for (BinaryMapIndexReader o : oo) {
|
for (BinaryMapIndexReader o : oo) {
|
||||||
ResultMatcher<Amenity> rm = getResultMatcher(phrase, resultMatcher, o);
|
ResultMatcher<Amenity> rm = getResultMatcher(phrase, resultMatcher, o, searchedPois);
|
||||||
if (obj instanceof CustomSearchPoiFilter) {
|
if (obj instanceof CustomSearchPoiFilter) {
|
||||||
rm = ((CustomSearchPoiFilter) obj).wrapResultMatcher(rm);
|
rm = ((CustomSearchPoiFilter) obj).wrapResultMatcher(rm);
|
||||||
}
|
}
|
||||||
|
@ -743,13 +754,20 @@ public class SearchCoreFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultMatcher<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchResultMatcher resultMatcher,
|
private ResultMatcher<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchResultMatcher resultMatcher,
|
||||||
final BinaryMapIndexReader selected) {
|
final BinaryMapIndexReader selected, final Set<String> searchedPois) {
|
||||||
final NameStringMatcher ns = phrase.getNameStringMatcher();
|
final NameStringMatcher ns = phrase.getNameStringMatcher();
|
||||||
return new ResultMatcher<Amenity>() {
|
return new ResultMatcher<Amenity>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean publish(Amenity object) {
|
public boolean publish(Amenity object) {
|
||||||
SearchResult res = new SearchResult(phrase);
|
SearchResult res = new SearchResult(phrase);
|
||||||
|
String poiID = object.getType().getKeyName() + "_" + object.getId();
|
||||||
|
if(!searchedPois.add(poiID)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(object.isClosed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
res.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
res.localeName = object.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
|
||||||
res.otherNames = object.getAllNames(true);
|
res.otherNames = object.getAllNames(true);
|
||||||
if (Algorithms.isEmpty(res.localeName)) {
|
if (Algorithms.isEmpty(res.localeName)) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -535,6 +536,7 @@ public class SearchPhrase {
|
||||||
if (indexes == null) {
|
if (indexes == null) {
|
||||||
indexes = new ArrayList<>(getOfflineIndexes());
|
indexes = new ArrayList<>(getOfflineIndexes());
|
||||||
}
|
}
|
||||||
|
Map<String, List<BinaryMapIndexReader>> diffsByRegion = getDiffsByRegion();
|
||||||
final LatLon ll = getLastTokenLocation();
|
final LatLon ll = getLastTokenLocation();
|
||||||
if (ll != null) {
|
if (ll != null) {
|
||||||
Collections.sort(indexes, new Comparator<BinaryMapIndexReader>() {
|
Collections.sort(indexes, new Comparator<BinaryMapIndexReader>() {
|
||||||
|
@ -563,8 +565,40 @@ public class SearchPhrase {
|
||||||
return rc1;
|
return rc1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (!diffsByRegion.isEmpty()) {
|
||||||
|
List<BinaryMapIndexReader> finalSort = new ArrayList<>();
|
||||||
|
for (int i = 0; i < indexes.size(); i++) {
|
||||||
|
BinaryMapIndexReader currFile = indexes.get(i);
|
||||||
|
if (diffsByRegion.get(currFile.getRegionName()) != null) {
|
||||||
|
finalSort.addAll(diffsByRegion.get(currFile.getRegionName()));
|
||||||
|
finalSort.add(currFile);
|
||||||
|
} else {
|
||||||
|
finalSort.add(currFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
indexes.clear();
|
||||||
|
indexes.addAll(finalSort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<BinaryMapIndexReader>> getDiffsByRegion() {
|
||||||
|
Map<String, List<BinaryMapIndexReader>> result = new HashMap<>();
|
||||||
|
Iterator<BinaryMapIndexReader> it = indexes.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
BinaryMapIndexReader r = it.next();
|
||||||
|
if (r.getFile().getName().matches(".*([0-9]+_*){3}\\.obf")) {
|
||||||
|
String currRegionName = r.getRegionName();
|
||||||
|
if (result.containsKey(currRegionName)) {
|
||||||
|
result.get(currRegionName).add(r);
|
||||||
|
} else {
|
||||||
|
result.put(currRegionName, new ArrayList<>(Arrays.asList(r)));
|
||||||
|
}
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static class NameStringMatcher implements StringMatcher {
|
public static class NameStringMatcher implements StringMatcher {
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.util;
|
||||||
|
|
||||||
import net.osmand.IProgress;
|
import net.osmand.IProgress;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
|
@ -113,7 +114,10 @@ public class Algorithms {
|
||||||
return -simplifyFileName(o1.getName()).compareTo(simplifyFileName(o2.getName()));
|
return -simplifyFileName(o1.getName()).compareTo(simplifyFileName(o2.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String simplifyFileName(String fn) {
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String simplifyFileName(String fn) {
|
||||||
String lc = fn.toLowerCase();
|
String lc = fn.toLowerCase();
|
||||||
if (lc.contains(".")) {
|
if (lc.contains(".")) {
|
||||||
lc = lc.substring(0, lc.indexOf("."));
|
lc = lc.substring(0, lc.indexOf("."));
|
||||||
|
@ -133,6 +137,13 @@ public class Algorithms {
|
||||||
}
|
}
|
||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Comparator<String> getStringVersionComparator() {
|
||||||
|
return new Comparator<String>() {
|
||||||
|
@Override
|
||||||
|
public int compare(String o1, String o2) {
|
||||||
|
return -simplifyFileName(o1).compareTo(simplifyFileName(o2));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -421,12 +421,20 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
|
||||||
@Override
|
@Override
|
||||||
public ResultMatcher<Amenity> wrapResultMatcher(final ResultMatcher<Amenity> matcher) {
|
public ResultMatcher<Amenity> wrapResultMatcher(final ResultMatcher<Amenity> matcher) {
|
||||||
final AmenityNameFilter nm = getNameFilter(filterByName);
|
final AmenityNameFilter nm = getNameFilter(filterByName);
|
||||||
|
final Set<String> searchedPois = new TreeSet<>();
|
||||||
return new ResultMatcher<Amenity>() {
|
return new ResultMatcher<Amenity>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean publish(Amenity a) {
|
public boolean publish(Amenity a) {
|
||||||
if (nm.accept(a)) {
|
if (nm.accept(a)) {
|
||||||
if (matcher == null || matcher.publish(a)) {
|
if (matcher == null || matcher.publish(a)) {
|
||||||
|
String poiID = a.getType().getKeyName() + "_" + a.getId();
|
||||||
|
if (!searchedPois.add(poiID)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a.isClosed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -715,7 +716,10 @@ public class ResourceManager {
|
||||||
int left31 = MapUtils.get31TileNumberX(leftLongitude);
|
int left31 = MapUtils.get31TileNumberX(leftLongitude);
|
||||||
int bottom31 = MapUtils.get31TileNumberY(bottomLatitude);
|
int bottom31 = MapUtils.get31TileNumberY(bottomLatitude);
|
||||||
int right31 = MapUtils.get31TileNumberX(rightLongitude);
|
int right31 = MapUtils.get31TileNumberX(rightLongitude);
|
||||||
for (AmenityIndexRepository index : amenityRepositories.values()) {
|
List<String> fileNames = new ArrayList<String>(amenityRepositories.keySet());
|
||||||
|
Collections.sort(fileNames, Algorithms.getStringVersionComparator());
|
||||||
|
for (String name : fileNames) {
|
||||||
|
AmenityIndexRepository index = amenityRepositories.get(name);
|
||||||
if (matcher != null && matcher.isCancelled()) {
|
if (matcher != null && matcher.isCancelled()) {
|
||||||
searchAmenitiesInProgress = false;
|
searchAmenitiesInProgress = false;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue