Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
290caa6ee6
4 changed files with 249 additions and 177 deletions
|
@ -1,4 +1,14 @@
|
||||||
package net.osmand.search;
|
package net.osmand.search;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import net.osmand.Collator;
|
import net.osmand.Collator;
|
||||||
import net.osmand.OsmAndCollator;
|
import net.osmand.OsmAndCollator;
|
||||||
|
@ -25,23 +35,12 @@ import net.osmand.util.MapUtils;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class SearchUICore {
|
public class SearchUICore {
|
||||||
|
|
||||||
private static final int TIMEOUT_BETWEEN_CHARS = 200;
|
private static final int TIMEOUT_BETWEEN_CHARS = 200;
|
||||||
private static final Log LOG = PlatformUtil.getLog(SearchUICore.class);
|
private static final Log LOG = PlatformUtil.getLog(SearchUICore.class);
|
||||||
private SearchPhrase phrase;
|
private SearchPhrase phrase;
|
||||||
private SearchResultCollection currentSearchResult = new SearchResultCollection();
|
private SearchResultCollection currentSearchResult;
|
||||||
|
|
||||||
private ThreadPoolExecutor singleThreadedExecutor;
|
private ThreadPoolExecutor singleThreadedExecutor;
|
||||||
private LinkedBlockingQueue<Runnable> taskQueue;
|
private LinkedBlockingQueue<Runnable> taskQueue;
|
||||||
|
@ -52,7 +51,6 @@ public class SearchUICore {
|
||||||
List<SearchCoreAPI> apis = new ArrayList<>();
|
List<SearchCoreAPI> apis = new ArrayList<>();
|
||||||
private SearchSettings searchSettings;
|
private SearchSettings searchSettings;
|
||||||
private MapPoiTypes poiTypes;
|
private MapPoiTypes poiTypes;
|
||||||
private Collator collator;
|
|
||||||
|
|
||||||
|
|
||||||
public SearchUICore(MapPoiTypes poiTypes, String locale) {
|
public SearchUICore(MapPoiTypes poiTypes, String locale) {
|
||||||
|
@ -60,31 +58,146 @@ public class SearchUICore {
|
||||||
taskQueue = new LinkedBlockingQueue<Runnable>();
|
taskQueue = new LinkedBlockingQueue<Runnable>();
|
||||||
searchSettings = new SearchSettings(new ArrayList<BinaryMapIndexReader>());
|
searchSettings = new SearchSettings(new ArrayList<BinaryMapIndexReader>());
|
||||||
searchSettings = searchSettings.setLang(locale);
|
searchSettings = searchSettings.setLang(locale);
|
||||||
phrase = new SearchPhrase(searchSettings);
|
phrase = new SearchPhrase(searchSettings, OsmAndCollator.primaryCollator());
|
||||||
|
currentSearchResult = new SearchResultCollection(phrase);
|
||||||
singleThreadedExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, taskQueue);
|
singleThreadedExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, taskQueue);
|
||||||
collator = OsmAndCollator.primaryCollator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SearchResultCollection {
|
public static class SearchResultCollection {
|
||||||
private List<SearchResult> searchResults;
|
private List<SearchResult> searchResults;
|
||||||
private SearchPhrase phrase;
|
private SearchPhrase phrase;
|
||||||
|
|
||||||
public SearchResultCollection(List<SearchResult> requestResults, SearchPhrase phrase) {
|
public SearchResultCollection(SearchPhrase phrase) {
|
||||||
searchResults = requestResults;
|
searchResults = new ArrayList<>();
|
||||||
this.phrase = phrase;
|
this.phrase = phrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchResultCollection() {
|
public SearchResultCollection combineWithCollection(SearchResultCollection collection, boolean resort, boolean removeDuplicates) {
|
||||||
searchResults = new ArrayList<>();
|
SearchResultCollection src = new SearchResultCollection(phrase);
|
||||||
|
src.addSearchResults(searchResults, false, false);
|
||||||
|
src.addSearchResults(collection.searchResults, resort, removeDuplicates);
|
||||||
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void addSearchResults(List<SearchResult> sr, boolean resortAll, boolean removeDuplicates) {
|
||||||
|
if(resortAll) {
|
||||||
|
this.searchResults.addAll(sr);
|
||||||
|
sortSearchResults();
|
||||||
|
if(removeDuplicates) {
|
||||||
|
filterSearchDuplicateResults();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(removeDuplicates) {
|
||||||
|
ArrayList<SearchResult> addedResults = new ArrayList<>(sr);
|
||||||
|
SearchResultComparator cmp = new SearchResultComparator(phrase);
|
||||||
|
Collections.sort(addedResults, cmp);
|
||||||
|
filterSearchDuplicateResults(addedResults);
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
while(j < addedResults.size()) {
|
||||||
|
SearchResult addedResult = addedResults.get(j);
|
||||||
|
if(i >= searchResults.size()) {
|
||||||
|
if(searchResults.size() == 0 ||
|
||||||
|
!sameSearchResult(addedResult, searchResults.get(searchResults.size() - 1))) {
|
||||||
|
searchResults.add(addedResult);
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SearchResult existingResult = searchResults.get(i);
|
||||||
|
if(sameSearchResult(addedResult, existingResult)) {
|
||||||
|
j++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int compare = cmp.compare(existingResult, addedResult);
|
||||||
|
if(compare == 0) {
|
||||||
|
// existingResult == addedResult
|
||||||
|
j++;
|
||||||
|
} else if(compare > 0) {
|
||||||
|
// existingResult > addedResult
|
||||||
|
this.searchResults.add(addedResults.get(j));
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
// existingResult < addedResult
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public List<SearchResult> getCurrentSearchResults() {
|
public List<SearchResult> getCurrentSearchResults() {
|
||||||
return searchResults;
|
return Collections.unmodifiableList(searchResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchPhrase getPhrase() {
|
public SearchPhrase getPhrase() {
|
||||||
return phrase;
|
return phrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sortSearchResults() {
|
||||||
|
Collections.sort(searchResults, new SearchResultComparator(phrase));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void filterSearchDuplicateResults() {
|
||||||
|
filterSearchDuplicateResults(searchResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterSearchDuplicateResults(List<SearchResult> lst) {
|
||||||
|
Iterator<SearchResult> it = lst.iterator();
|
||||||
|
SearchResult found = null;
|
||||||
|
while(it.hasNext()) {
|
||||||
|
SearchResult r = it.next();
|
||||||
|
if(found != null && sameSearchResult(found, r)) {
|
||||||
|
it.remove();
|
||||||
|
} else {
|
||||||
|
found = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean sameSearchResult(SearchResult r1, SearchResult r2) {
|
||||||
|
if(r1.location != null && r2.location != null) {
|
||||||
|
Amenity a1 = null;
|
||||||
|
if(r1.object instanceof Amenity) {
|
||||||
|
a1 = (Amenity) r1.object;
|
||||||
|
}
|
||||||
|
Amenity a2 = null;
|
||||||
|
if(r2.object instanceof Amenity) {
|
||||||
|
a2 = (Amenity) r2.object;
|
||||||
|
}
|
||||||
|
if (r1.localeName.equals(r2.localeName)) {
|
||||||
|
double similarityRadius = 30;
|
||||||
|
if (a1 != null && a2 != null) {
|
||||||
|
// here 2 points are amenity
|
||||||
|
String type1 = a1.getType().getKeyName();
|
||||||
|
String type2 = a2.getType().getKeyName();
|
||||||
|
String subType1 = a1.getSubType();
|
||||||
|
String subType2 = a2.getSubType();
|
||||||
|
if (!type1.equals(type2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type1.equals("natural")) {
|
||||||
|
similarityRadius = 10000;
|
||||||
|
} else if (subType1.equals(subType2)) {
|
||||||
|
if (subType1.contains("cn_ref") || subType1.contains("wn_ref")
|
||||||
|
|| (subType1.startsWith("route_hiking_") && subType1.endsWith("n_poi"))) {
|
||||||
|
similarityRadius = 10000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(ObjectType.isAddress(r1.objectType) && ObjectType.isAddress(r2.objectType)) {
|
||||||
|
similarityRadius = 100;
|
||||||
|
}
|
||||||
|
return MapUtils.getDistance(r1.location, r2.location) < similarityRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPoiTypes(MapPoiTypes poiTypes) {
|
public void setPoiTypes(MapPoiTypes poiTypes) {
|
||||||
|
@ -111,7 +224,6 @@ public class SearchUICore {
|
||||||
|
|
||||||
public <T extends SearchCoreAPI> SearchResultCollection shallowSearch(Class<T> cl,
|
public <T extends SearchCoreAPI> SearchResultCollection shallowSearch(Class<T> cl,
|
||||||
String text, final ResultMatcher<SearchResult> matcher) throws IOException {
|
String text, final ResultMatcher<SearchResult> matcher) throws IOException {
|
||||||
SearchResultCollection quickRes = new SearchResultCollection();
|
|
||||||
T api = getApiByClass(cl);
|
T api = getApiByClass(cl);
|
||||||
if(api != null) {
|
if(api != null) {
|
||||||
SearchPhrase sphrase = this.phrase.generateNewPhrase(text, searchSettings);
|
SearchPhrase sphrase = this.phrase.generateNewPhrase(text, searchSettings);
|
||||||
|
@ -120,14 +232,13 @@ public class SearchUICore {
|
||||||
SearchResultMatcher rm = new SearchResultMatcher(matcher, ai.get(), ai, totalLimit);
|
SearchResultMatcher rm = new SearchResultMatcher(matcher, ai.get(), ai, totalLimit);
|
||||||
api.search(sphrase, rm);
|
api.search(sphrase, rm);
|
||||||
|
|
||||||
sortSearchResults(sphrase, rm.getRequestResults());
|
SearchResultCollection collection = new SearchResultCollection(
|
||||||
filterSearchDuplicateResults(sphrase, rm.getRequestResults());
|
|
||||||
|
|
||||||
LOG.info(">> Shallow Search phrase " + phrase + " " + rm.getRequestResults().size());
|
|
||||||
return new SearchResultCollection(rm.getRequestResults(),
|
|
||||||
sphrase);
|
sphrase);
|
||||||
|
collection.addSearchResults(rm.getRequestResults(), true, true);
|
||||||
|
LOG.info(">> Shallow Search phrase " + phrase + " " + rm.getRequestResults().size());
|
||||||
|
return collection;
|
||||||
}
|
}
|
||||||
return quickRes;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
|
@ -201,11 +312,10 @@ public class SearchUICore {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchResultCollection search(final String text, final ResultMatcher<SearchResult> matcher) {
|
public SearchResultCollection search(final String text, final ResultMatcher<SearchResult> matcher) {
|
||||||
SearchResultCollection quickRes = new SearchResultCollection();
|
|
||||||
final int request = requestNumber.incrementAndGet();
|
final int request = requestNumber.incrementAndGet();
|
||||||
final SearchPhrase phrase = this.phrase.generateNewPhrase(text, searchSettings);
|
final SearchPhrase phrase = this.phrase.generateNewPhrase(text, searchSettings);
|
||||||
this.phrase = phrase;
|
this.phrase = phrase;
|
||||||
quickRes.phrase = phrase;
|
SearchResultCollection quickRes = new SearchResultCollection(phrase);
|
||||||
filterCurrentResults(quickRes.searchResults, phrase);
|
filterCurrentResults(quickRes.searchResults, phrase);
|
||||||
LOG.info("> Search phrase " + phrase + " " + quickRes.searchResults.size());
|
LOG.info("> Search phrase " + phrase + " " + quickRes.searchResults.size());
|
||||||
singleThreadedExecutor.submit(new Runnable() {
|
singleThreadedExecutor.submit(new Runnable() {
|
||||||
|
@ -222,12 +332,11 @@ public class SearchUICore {
|
||||||
}
|
}
|
||||||
searchInBackground(phrase, rm);
|
searchInBackground(phrase, rm);
|
||||||
if (!rm.isCancelled()) {
|
if (!rm.isCancelled()) {
|
||||||
sortSearchResults(phrase, rm.getRequestResults());
|
|
||||||
filterSearchDuplicateResults(phrase, rm.getRequestResults());
|
|
||||||
|
|
||||||
LOG.info(">> Search phrase " + phrase + " " + rm.getRequestResults().size());
|
SearchResultCollection collection = new SearchResultCollection(
|
||||||
SearchResultCollection collection = new SearchResultCollection(rm.getRequestResults(),
|
|
||||||
phrase);
|
phrase);
|
||||||
|
collection.addSearchResults(rm.getRequestResults(), true, true);
|
||||||
|
LOG.info(">> Search phrase " + phrase + " " + rm.getRequestResults().size());
|
||||||
currentSearchResult = collection;
|
currentSearchResult = collection;
|
||||||
if (onResultsComplete != null) {
|
if (onResultsComplete != null) {
|
||||||
onResultsComplete.run();
|
onResultsComplete.run();
|
||||||
|
@ -267,6 +376,7 @@ public class SearchUICore {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
api.search(phrase, matcher);
|
api.search(phrase, matcher);
|
||||||
|
|
||||||
matcher.apiSearchFinished(api, phrase);
|
matcher.apiSearchFinished(api, phrase);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -284,92 +394,10 @@ public class SearchUICore {
|
||||||
phrase.sortFiles();
|
phrase.sortFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean sameSearchResult(SearchResult r1, SearchResult r2) {
|
|
||||||
if(r1.location != null && r2.location != null) {
|
|
||||||
Amenity a1 = null;
|
|
||||||
if(r1.object instanceof Amenity) {
|
|
||||||
a1 = (Amenity) r1.object;
|
|
||||||
}
|
|
||||||
Amenity a2 = null;
|
|
||||||
if(r2.object instanceof Amenity) {
|
|
||||||
a2 = (Amenity) r2.object;
|
|
||||||
}
|
|
||||||
if (r1.localeName.equals(r2.localeName)) {
|
|
||||||
double similarityRadius = 30;
|
|
||||||
if (a1 != null && a2 != null) {
|
|
||||||
// here 2 points are amenity
|
|
||||||
String type1 = a1.getType().getKeyName();
|
|
||||||
String type2 = a2.getType().getKeyName();
|
|
||||||
String subType1 = a1.getSubType();
|
|
||||||
String subType2 = a2.getSubType();
|
|
||||||
if (!type1.equals(type2)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (type1.equals("natural")) {
|
|
||||||
similarityRadius = 10000;
|
|
||||||
} else if (subType1.equals(subType2)) {
|
|
||||||
if (subType1.contains("cn_ref") || subType1.contains("wn_ref")
|
|
||||||
|| (subType1.startsWith("route_hiking_") && subType1.endsWith("n_poi"))) {
|
|
||||||
similarityRadius = 10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(ObjectType.isAddress(r1.objectType) && ObjectType.isAddress(r2.objectType)) {
|
|
||||||
similarityRadius = 100;
|
|
||||||
}
|
|
||||||
return MapUtils.getDistance(r1.location, r2.location) < similarityRadius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void filterSearchDuplicateResults(SearchPhrase sp, List<SearchResult> searchResults) {
|
|
||||||
Iterator<SearchResult> it = searchResults.iterator();
|
|
||||||
SearchResult found = null;
|
|
||||||
while(it.hasNext()) {
|
|
||||||
SearchResult r = it.next();
|
|
||||||
if(found != null && sameSearchResult(found, r)) {
|
|
||||||
it.remove();
|
|
||||||
} else {
|
|
||||||
found = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void sortSearchResults(SearchPhrase sp, List<SearchResult> searchResults) {
|
|
||||||
// sort SearchResult by 1. searchDistance 2. Name
|
|
||||||
final LatLon loc = sp.getLastTokenLocation();
|
|
||||||
Collections.sort(searchResults, new Comparator<SearchResult>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(SearchResult o1, SearchResult o2) {
|
|
||||||
if(o1.getFoundWordCount() != o2.getFoundWordCount()) {
|
|
||||||
return -Algorithms.compare(o1.getFoundWordCount(), o2.getFoundWordCount());
|
|
||||||
}
|
|
||||||
double s1 = o1.getSearchDistance(loc);
|
|
||||||
double s2 = o2.getSearchDistance(loc);
|
|
||||||
int cmp = Double.compare(s1, s2);
|
|
||||||
if(cmp != 0) {
|
|
||||||
return cmp;
|
|
||||||
}
|
|
||||||
int st1 = Algorithms.extractFirstIntegerNumber(o1.localeName);
|
|
||||||
int st2 = Algorithms.extractFirstIntegerNumber(o2.localeName);
|
|
||||||
if(st1 != st2) {
|
|
||||||
return Algorithms.compare(st1, st2);
|
|
||||||
}
|
|
||||||
cmp = collator.compare(o1.localeName, o2.localeName);
|
|
||||||
if(cmp != 0) {
|
|
||||||
return cmp;
|
|
||||||
}
|
|
||||||
s1 = o1.getSearchDistance(loc, 1);
|
|
||||||
s2 = o2.getSearchDistance(loc, 1);
|
|
||||||
return Double.compare(s1, s2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SearchResultMatcher
|
public static class SearchResultMatcher implements ResultMatcher<SearchResult>{
|
||||||
implements ResultMatcher<SearchResult>{
|
|
||||||
private final List<SearchResult> requestResults = new ArrayList<>();
|
private final List<SearchResult> requestResults = new ArrayList<>();
|
||||||
private final ResultMatcher<SearchResult> matcher;
|
private final ResultMatcher<SearchResult> matcher;
|
||||||
private final int request;
|
private final int request;
|
||||||
|
@ -439,5 +467,43 @@ public class SearchUICore {
|
||||||
boolean cancelled = request != requestNumber.get();
|
boolean cancelled = request != requestNumber.get();
|
||||||
return cancelled || (matcher != null && matcher.isCancelled());
|
return cancelled || (matcher != null && matcher.isCancelled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class SearchResultComparator implements Comparator<SearchResult> {
|
||||||
|
private SearchPhrase sp;
|
||||||
|
private Collator collator;
|
||||||
|
private LatLon loc;
|
||||||
|
|
||||||
|
public SearchResultComparator(SearchPhrase sp) {
|
||||||
|
this.sp = sp;
|
||||||
|
this.collator = sp.getCollator();
|
||||||
|
loc = sp.getLastTokenLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(SearchResult o1, SearchResult o2) {
|
||||||
|
if(o1.getFoundWordCount() != o2.getFoundWordCount()) {
|
||||||
|
return -Algorithms.compare(o1.getFoundWordCount(), o2.getFoundWordCount());
|
||||||
|
}
|
||||||
|
double s1 = o1.getSearchDistance(loc);
|
||||||
|
double s2 = o2.getSearchDistance(loc);
|
||||||
|
int cmp = Double.compare(s1, s2);
|
||||||
|
if(cmp != 0) {
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
int st1 = Algorithms.extractFirstIntegerNumber(o1.localeName);
|
||||||
|
int st2 = Algorithms.extractFirstIntegerNumber(o2.localeName);
|
||||||
|
if(st1 != st2) {
|
||||||
|
return Algorithms.compare(st1, st2);
|
||||||
|
}
|
||||||
|
cmp = collator.compare(o1.localeName, o2.localeName);
|
||||||
|
if(cmp != 0) {
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
s1 = o1.getSearchDistance(loc, 1);
|
||||||
|
s2 = o2.getSearchDistance(loc, 1);
|
||||||
|
return Double.compare(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,10 @@ import java.util.List;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import net.osmand.Collator;
|
||||||
import net.osmand.CollatorStringMatcher;
|
import net.osmand.CollatorStringMatcher;
|
||||||
import net.osmand.CollatorStringMatcher.StringMatcherMode;
|
import net.osmand.CollatorStringMatcher.StringMatcherMode;
|
||||||
|
import net.osmand.OsmAndCollator;
|
||||||
import net.osmand.StringMatcher;
|
import net.osmand.StringMatcher;
|
||||||
import net.osmand.binary.BinaryMapIndexReader;
|
import net.osmand.binary.BinaryMapIndexReader;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||||
|
@ -37,6 +39,7 @@ public class SearchPhrase {
|
||||||
private static final String DELIMITER = " ";
|
private static final String DELIMITER = " ";
|
||||||
private static final String ALLDELIMITERS = "\\s|,";
|
private static final String ALLDELIMITERS = "\\s|,";
|
||||||
private static final Pattern reg = Pattern.compile(ALLDELIMITERS);
|
private static final Pattern reg = Pattern.compile(ALLDELIMITERS);
|
||||||
|
private Collator clt;
|
||||||
|
|
||||||
|
|
||||||
public enum SearchPhraseDataType {
|
public enum SearchPhraseDataType {
|
||||||
|
@ -44,12 +47,17 @@ public class SearchPhrase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SearchPhrase(SearchSettings settings) {
|
public SearchPhrase(SearchSettings settings, Collator clt) {
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
this.clt = clt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collator getCollator() {
|
||||||
|
return clt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchPhrase generateNewPhrase(String text, SearchSettings settings) {
|
public SearchPhrase generateNewPhrase(String text, SearchSettings settings) {
|
||||||
SearchPhrase sp = new SearchPhrase(settings);
|
SearchPhrase sp = new SearchPhrase(settings, this.clt);
|
||||||
String restText = text;
|
String restText = text;
|
||||||
List<SearchWord> leftWords = this.words;
|
List<SearchWord> leftWords = this.words;
|
||||||
String thisTxt = getText(true);
|
String thisTxt = getText(true);
|
||||||
|
@ -259,7 +267,7 @@ public class SearchPhrase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchPhrase selectWord(SearchResult res, List<String> unknownWords, boolean lastComplete) {
|
public SearchPhrase selectWord(SearchResult res, List<String> unknownWords, boolean lastComplete) {
|
||||||
SearchPhrase sp = new SearchPhrase(this.settings);
|
SearchPhrase sp = new SearchPhrase(this.settings, this.clt);
|
||||||
addResult(res, sp);
|
addResult(res, sp);
|
||||||
SearchResult prnt = res.parentSearchResult;
|
SearchResult prnt = res.parentSearchResult;
|
||||||
while(prnt != null) {
|
while(prnt != null) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.search;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.osmand.OsmAndCollator;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.search.SearchUICore.SearchResultMatcher;
|
import net.osmand.search.SearchUICore.SearchResultMatcher;
|
||||||
import net.osmand.search.core.SearchCoreFactory;
|
import net.osmand.search.core.SearchCoreFactory;
|
||||||
|
@ -16,7 +17,7 @@ public class LocationSearchTest {
|
||||||
private void search(String string, LatLon latLon) throws IOException {
|
private void search(String string, LatLon latLon) throws IOException {
|
||||||
SearchResultMatcher srm = new SearchUICore.SearchResultMatcher(null, 0, null, 100);
|
SearchResultMatcher srm = new SearchUICore.SearchResultMatcher(null, 0, null, 100);
|
||||||
new SearchCoreFactory.SearchLocationAndUrlAPI().
|
new SearchCoreFactory.SearchLocationAndUrlAPI().
|
||||||
search(new SearchPhrase(null).generateNewPhrase(string, null), srm);
|
search(new SearchPhrase(null, OsmAndCollator.primaryCollator()).generateNewPhrase(string, null), srm);
|
||||||
Assert.assertEquals(1, srm.getRequestResults().size());
|
Assert.assertEquals(1, srm.getRequestResults().size());
|
||||||
Assert.assertEquals(latLon, srm.getRequestResults().get(0).location);
|
Assert.assertEquals(latLon, srm.getRequestResults().get(0).location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,45 @@
|
||||||
package net.osmand.plus.search;
|
package net.osmand.plus.search;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.Location;
|
||||||
|
import net.osmand.OsmAndCollator;
|
||||||
|
import net.osmand.ResultMatcher;
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.data.PointDescription;
|
||||||
|
import net.osmand.osm.AbstractPoiType;
|
||||||
|
import net.osmand.plus.AppInitializer;
|
||||||
|
import net.osmand.plus.AppInitializer.AppInitializeListener;
|
||||||
|
import net.osmand.plus.GPXUtilities;
|
||||||
|
import net.osmand.plus.GPXUtilities.GPXFile;
|
||||||
|
import net.osmand.plus.GPXUtilities.WptPt;
|
||||||
|
import net.osmand.plus.LockableViewPager;
|
||||||
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
|
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
|
||||||
|
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.OsmandSettings;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
import net.osmand.plus.helpers.SearchHistoryHelper;
|
||||||
|
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||||
|
import net.osmand.plus.poi.PoiUIFilter;
|
||||||
|
import net.osmand.plus.search.QuickSearchHelper.SearchHistoryAPI;
|
||||||
|
import net.osmand.search.SearchUICore;
|
||||||
|
import net.osmand.search.SearchUICore.SearchResultCollection;
|
||||||
|
import net.osmand.search.core.ObjectType;
|
||||||
|
import net.osmand.search.core.SearchCoreAPI;
|
||||||
|
import net.osmand.search.core.SearchCoreFactory.SearchAmenityTypesAPI;
|
||||||
|
import net.osmand.search.core.SearchPhrase;
|
||||||
|
import net.osmand.search.core.SearchResult;
|
||||||
|
import net.osmand.search.core.SearchSettings;
|
||||||
|
import net.osmand.search.core.SearchWord;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
import net.osmand.util.MapUtils;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
@ -34,46 +74,6 @@ import android.widget.ListView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
|
||||||
import net.osmand.Location;
|
|
||||||
import net.osmand.ResultMatcher;
|
|
||||||
import net.osmand.data.LatLon;
|
|
||||||
import net.osmand.data.PointDescription;
|
|
||||||
import net.osmand.osm.AbstractPoiType;
|
|
||||||
import net.osmand.plus.AppInitializer;
|
|
||||||
import net.osmand.plus.AppInitializer.AppInitializeListener;
|
|
||||||
import net.osmand.plus.GPXUtilities;
|
|
||||||
import net.osmand.plus.GPXUtilities.GPXFile;
|
|
||||||
import net.osmand.plus.GPXUtilities.WptPt;
|
|
||||||
import net.osmand.plus.LockableViewPager;
|
|
||||||
import net.osmand.plus.OsmAndFormatter;
|
|
||||||
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
|
|
||||||
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
|
|
||||||
import net.osmand.plus.OsmandApplication;
|
|
||||||
import net.osmand.plus.OsmandSettings;
|
|
||||||
import net.osmand.plus.R;
|
|
||||||
import net.osmand.plus.activities.MapActivity;
|
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper;
|
|
||||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
|
||||||
import net.osmand.plus.poi.PoiUIFilter;
|
|
||||||
import net.osmand.plus.search.QuickSearchHelper.SearchHistoryAPI;
|
|
||||||
import net.osmand.search.SearchUICore;
|
|
||||||
import net.osmand.search.SearchUICore.SearchResultCollection;
|
|
||||||
import net.osmand.search.core.ObjectType;
|
|
||||||
import net.osmand.search.core.SearchCoreAPI;
|
|
||||||
import net.osmand.search.core.SearchCoreFactory.SearchAmenityTypesAPI;
|
|
||||||
import net.osmand.search.core.SearchPhrase;
|
|
||||||
import net.osmand.search.core.SearchResult;
|
|
||||||
import net.osmand.search.core.SearchSettings;
|
|
||||||
import net.osmand.search.core.SearchWord;
|
|
||||||
import net.osmand.util.Algorithms;
|
|
||||||
import net.osmand.util.MapUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class QuickSearchDialogFragment extends DialogFragment implements OsmAndCompassListener, OsmAndLocationListener {
|
public class QuickSearchDialogFragment extends DialogFragment implements OsmAndCompassListener, OsmAndLocationListener {
|
||||||
|
|
||||||
public static final String TAG = "QuickSearchDialogFragment";
|
public static final String TAG = "QuickSearchDialogFragment";
|
||||||
|
@ -697,13 +697,13 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
||||||
try {
|
try {
|
||||||
SearchResultCollection res = searchUICore.shallowSearch(SearchHistoryAPI.class,
|
SearchResultCollection res = searchUICore.shallowSearch(SearchHistoryAPI.class,
|
||||||
"", null);
|
"", null);
|
||||||
|
List<QuickSearchListItem> rows = new ArrayList<>();
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
List<QuickSearchListItem> rows = new ArrayList<>();
|
|
||||||
for (SearchResult sr : res.getCurrentSearchResults()) {
|
for (SearchResult sr : res.getCurrentSearchResults()) {
|
||||||
rows.add(new QuickSearchListItem(app, sr));
|
rows.add(new QuickSearchListItem(app, sr));
|
||||||
}
|
}
|
||||||
historySearchFragment.updateListAdapter(rows, false);
|
|
||||||
}
|
}
|
||||||
|
historySearchFragment.updateListAdapter(rows, false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
app.showToastMessage(e.getMessage());
|
app.showToastMessage(e.getMessage());
|
||||||
|
@ -764,7 +764,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
||||||
|
|
||||||
if (paused) {
|
if (paused) {
|
||||||
if (results.size() > 0) {
|
if (results.size() > 0) {
|
||||||
getResultCollection().getCurrentSearchResults().addAll(results);
|
getResultCollection().addSearchResults(results, true, true);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -783,7 +783,6 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
||||||
apiResults = regionCollection.getCurrentSearchResults();
|
apiResults = regionCollection.getCurrentSearchResults();
|
||||||
} else {
|
} else {
|
||||||
apiResults = results;
|
apiResults = results;
|
||||||
searchUICore.sortSearchResults(phrase, apiResults);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
regionResultApi = null;
|
regionResultApi = null;
|
||||||
|
@ -796,9 +795,12 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
boolean appended = false;
|
boolean appended = false;
|
||||||
if (getResultCollection() == null || getResultCollection().getPhrase() != phrase) {
|
if (getResultCollection() == null || getResultCollection().getPhrase() != phrase) {
|
||||||
setResultCollection(new SearchResultCollection(apiResults, phrase));
|
SearchResultCollection resCollection =
|
||||||
|
new SearchResultCollection(phrase);
|
||||||
|
resCollection.addSearchResults(results, true, true);
|
||||||
|
setResultCollection(resCollection);
|
||||||
} else {
|
} else {
|
||||||
getResultCollection().getCurrentSearchResults().addAll(apiResults);
|
getResultCollection().addSearchResults(apiResults, false, true );
|
||||||
appended = true;
|
appended = true;
|
||||||
}
|
}
|
||||||
if (!hasRegionCollection) {
|
if (!hasRegionCollection) {
|
||||||
|
@ -810,22 +812,17 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
|
||||||
break;
|
break;
|
||||||
case SEARCH_API_REGION_FINISHED:
|
case SEARCH_API_REGION_FINISHED:
|
||||||
regionResultApi = (SearchCoreAPI) object.object;
|
regionResultApi = (SearchCoreAPI) object.object;
|
||||||
|
|
||||||
final List<SearchResult> regionResults = new ArrayList<>(results);
|
|
||||||
final SearchPhrase regionPhrase = object.requiredSearchPhrase;
|
final SearchPhrase regionPhrase = object.requiredSearchPhrase;
|
||||||
searchUICore.sortSearchResults(regionPhrase, regionResults);
|
regionResultCollection = new SearchResultCollection(regionPhrase);
|
||||||
|
regionResultCollection.addSearchResults(results, true, true);
|
||||||
app.runInUIThread(new Runnable() {
|
app.runInUIThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
boolean appended = getResultCollection() != null && getResultCollection().getPhrase() == regionPhrase;
|
boolean appended = getResultCollection() != null && getResultCollection().getPhrase() == regionPhrase;
|
||||||
regionResultCollection = new SearchResultCollection(regionResults, regionPhrase);
|
|
||||||
if (appended) {
|
if (appended) {
|
||||||
List<SearchResult> res = new ArrayList<>(getResultCollection().getCurrentSearchResults());
|
SearchResultCollection resCollection =
|
||||||
res.addAll(regionResults);
|
getResultCollection().combineWithCollection(regionResultCollection, false, true);
|
||||||
SearchResultCollection resCollection = new SearchResultCollection(res, regionPhrase);
|
|
||||||
searchUICore.filterSearchDuplicateResults(regionPhrase, resCollection.getCurrentSearchResults());
|
|
||||||
updateSearchResult(resCollection, true);
|
updateSearchResult(resCollection, true);
|
||||||
} else {
|
} else {
|
||||||
updateSearchResult(regionResultCollection, false);
|
updateSearchResult(regionResultCollection, false);
|
||||||
|
|
Loading…
Reference in a new issue