This commit is contained in:
Alexey Kulish 2016-07-24 18:56:22 +03:00
commit 7a9718078a
15 changed files with 175 additions and 141 deletions

View file

@ -14,7 +14,6 @@ import java.util.Map.Entry;
import java.util.TreeSet; import java.util.TreeSet;
import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.CollatorStringMatcher.StringMatcherMode;
import net.osmand.LocationConvert;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
import net.osmand.binary.BinaryMapAddressReaderAdapter; import net.osmand.binary.BinaryMapAddressReaderAdapter;
import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader;
@ -105,7 +104,7 @@ public class SearchCoreFactory {
sr.objectType = ObjectType.REGION; sr.objectType = ObjectType.REGION;
sr.location = bmir.getRegionCenter(); sr.location = bmir.getRegionCenter();
sr.preferredZoom = 6; sr.preferredZoom = 6;
if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) { } else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
@ -148,7 +147,7 @@ public class SearchCoreFactory {
@Override @Override
public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException { public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException {
if (phrase.getLastWord().isEmpty()) { if (!phrase.isUnknownSearchWordPresent()) {
return false; return false;
} }
// phrase.isLastWord(ObjectType.CITY, ObjectType.VILLAGE, ObjectType.POSTCODE) || phrase.isLastWord(ObjectType.REGION) // phrase.isLastWord(ObjectType.CITY, ObjectType.VILLAGE, ObjectType.POSTCODE) || phrase.isLastWord(ObjectType.REGION)
@ -180,7 +179,7 @@ public class SearchCoreFactory {
} }
} }
} }
if (phrase.isNoSelectedType() && bbox != null && phrase.getLastWord().length() > 0) { if (phrase.isNoSelectedType() && bbox != null && phrase.isUnknownSearchWordPresent()) {
NameStringMatcher nm = phrase.getNameStringMatcher(); NameStringMatcher nm = phrase.getNameStringMatcher();
resArray.clear(); resArray.clear();
resArray = townCitiesQR.queryInBox(bbox, resArray); resArray = townCitiesQR.queryInBox(bbox, resArray);
@ -210,7 +209,7 @@ public class SearchCoreFactory {
private void searchByName(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) private void searchByName(final SearchPhrase phrase, final SearchResultMatcher resultMatcher)
throws IOException { throws IOException {
if(phrase.getRadiusLevel() > 1 || phrase.getLastWord().length() > 3) { if(phrase.getRadiusLevel() > 1 || phrase.getUnknownSearchWordLength() > 3) {
final boolean locSpecified = phrase.getLastTokenLocation() != null; final boolean locSpecified = phrase.getLastTokenLocation() != null;
LatLon loc = phrase.getLastTokenLocation(); LatLon loc = phrase.getLastTokenLocation();
final QuadRect streetBbox = phrase.getRadiusBBoxToSearch(DEFAULT_ADDRESS_BBOX_RADIUS); final QuadRect streetBbox = phrase.getRadiusBBoxToSearch(DEFAULT_ADDRESS_BBOX_RADIUS);
@ -314,7 +313,9 @@ public class SearchCoreFactory {
BinaryMapIndexReader r = offlineIterator.next(); BinaryMapIndexReader r = offlineIterator.next();
currentFile[0] = r; currentFile[0] = r;
SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, phrase SearchRequest<MapObject> req = BinaryMapIndexReader.buildAddressByNameRequest(rm, phrase
.getLastWord().toLowerCase(), StringMatcherMode.CHECK_STARTS_FROM_SPACE); .getUnknownSearchWord().toLowerCase(),
phrase.isUnknownSearchWordComplete() ? StringMatcherMode.CHECK_EQUALS_FROM_SPACE :
StringMatcherMode.CHECK_STARTS_FROM_SPACE);
if (locSpecified) { if (locSpecified) {
req.setBBoxRadius(loc.getLatitude(), loc.getLongitude(), phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10)); req.setBBoxRadius(loc.getLatitude(), loc.getLongitude(), phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10));
} }
@ -335,16 +336,17 @@ public class SearchCoreFactory {
@Override @Override
public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException { public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException {
if(phrase.getLastWord().length() == 0) { if(!phrase.isUnknownSearchWordPresent()) {
return false; return false;
} }
final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1]; final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1];
Iterator<BinaryMapIndexReader> offlineIterator = phrase.getRadiusOfflineIndexes(BBOX_RADIUS, Iterator<BinaryMapIndexReader> offlineIterator = phrase.getRadiusOfflineIndexes(BBOX_RADIUS,
SearchPhraseDataType.POI); SearchPhraseDataType.POI);
final NameStringMatcher nm = phrase.getNameStringMatcher();
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE); QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE);
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest( SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
(int)bbox.centerX(), (int)bbox.centerY(), (int)bbox.centerX(), (int)bbox.centerY(),
phrase.getLastWord(), phrase.getUnknownSearchWord(),
(int)bbox.left, (int)bbox.right, (int)bbox.left, (int)bbox.right,
(int)bbox.top, (int)bbox.bottom, (int)bbox.top, (int)bbox.bottom,
new ResultMatcher<Amenity>() { new ResultMatcher<Amenity>() {
@ -357,6 +359,11 @@ public class SearchCoreFactory {
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(), true); sr.localeName = object.getName(phrase.getSettings().getLang(), true);
if(phrase.isUnknownSearchWordComplete()) {
if(!nm.matches(sr.localeName) || !nm.matches(sr.otherNames)) {
return false;
}
}
sr.object = object; sr.object = object;
sr.preferredZoom = 17; sr.preferredZoom = 17;
sr.file = currentFile[0]; sr.file = currentFile[0];
@ -364,7 +371,7 @@ public class SearchCoreFactory {
if(object.getSubType().equals("city") || if(object.getSubType().equals("city") ||
object.getSubType().equals("country")) { object.getSubType().equals("country")) {
sr.priorityDistance = SEARCH_AMENITY_BY_NAME_CITY_PRIORITY_DISTANCE; sr.priorityDistance = SEARCH_AMENITY_BY_NAME_CITY_PRIORITY_DISTANCE;
sr.preferredZoom = object.getSubType().equals("country") ? 8 : 13; sr.preferredZoom = object.getSubType().equals("country") ? 7 : 13;
} else if(object.getSubType().equals("town")) { } else if(object.getSubType().equals("town")) {
sr.priorityDistance = SEARCH_AMENITY_BY_NAME_TOWN_PRIORITY_DISTANCE; sr.priorityDistance = SEARCH_AMENITY_BY_NAME_TOWN_PRIORITY_DISTANCE;
} else { } else {
@ -395,7 +402,7 @@ public class SearchCoreFactory {
@Override @Override
public int getSearchPriority(SearchPhrase p) { public int getSearchPriority(SearchPhrase p) {
if(p.hasObjectType(ObjectType.POI) || if(p.hasObjectType(ObjectType.POI) ||
p.getLastWord().length() == 0) { !p.isUnknownSearchWordPresent()) {
return -1; return -1;
} }
if(p.hasObjectType(ObjectType.POI_TYPE)) { if(p.hasObjectType(ObjectType.POI_TYPE)) {
@ -405,7 +412,7 @@ public class SearchCoreFactory {
return -1; return -1;
} }
} }
if(p.getLastWord().length() > 3 || p.getRadiusLevel() > 1) { if(p.getUnknownSearchWordLength() > 3 || p.getRadiusLevel() > 1) {
return SEARCH_AMENITY_BY_NAME_API_PRIORITY_IF_3_CHAR; return SEARCH_AMENITY_BY_NAME_API_PRIORITY_IF_3_CHAR;
} }
return -1; return -1;
@ -435,11 +442,11 @@ public class SearchCoreFactory {
}); });
NameStringMatcher nm = phrase.getNameStringMatcher(); NameStringMatcher nm = phrase.getNameStringMatcher();
for (PoiFilter pf : topVisibleFilters) { for (PoiFilter pf : topVisibleFilters) {
if (Algorithms.isEmpty(phrase.getLastWord()) || nm.matches(pf.getTranslation())) { if (!phrase.isUnknownSearchWordPresent() || nm.matches(pf.getTranslation())) {
results.add(pf); results.add(pf);
} }
} }
if (!Algorithms.isEmpty(phrase.getLastWord())) { if (phrase.isUnknownSearchWordPresent()) {
Iterator<Entry<String, PoiType>> it = translatedNames.entrySet().iterator(); Iterator<Entry<String, PoiType>> it = translatedNames.entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
Entry<String, PoiType> e = it.next(); Entry<String, PoiType> e = it.next();
@ -465,7 +472,7 @@ public class SearchCoreFactory {
if (p.hasObjectType(ObjectType.POI) || p.hasObjectType(ObjectType.POI_TYPE)) { if (p.hasObjectType(ObjectType.POI) || p.hasObjectType(ObjectType.POI_TYPE)) {
return -1; return -1;
} }
if(!p.isNoSelectedType() && p.getLastWord().isEmpty()) { if(!p.isNoSelectedType() && !p.isUnknownSearchWordPresent()) {
return -1; return -1;
} }
return SEARCH_AMENITY_TYPE_API_PRIORITY; return SEARCH_AMENITY_TYPE_API_PRIORITY;
@ -564,7 +571,7 @@ public class SearchCoreFactory {
res.localeName = object.getSubType(); res.localeName = object.getSubType();
} }
} }
if (!Algorithms.isEmpty(phrase.getLastWord()) if (phrase.isUnknownSearchWordPresent()
&& !(ns.matches(res.localeName) || ns.matches(res.otherNames))) { && !(ns.matches(res.localeName) || ns.matches(res.otherNames))) {
return false; return false;
} }
@ -628,7 +635,7 @@ public class SearchCoreFactory {
// streets related to city // streets related to city
continue; continue;
} }
if (!Algorithms.isEmpty(phrase.getLastWord()) if (phrase.isUnknownSearchWordPresent()
&& !(nm.matches(res.localeName) || nm.matches(res.otherNames))) { && !(nm.matches(res.localeName) || nm.matches(res.otherNames))) {
continue; continue;
} }
@ -697,7 +704,7 @@ public class SearchCoreFactory {
if(s != null) { if(s != null) {
BinaryMapIndexReader file = phrase.getLastSelectedWord().getResult().file; BinaryMapIndexReader file = phrase.getLastSelectedWord().getResult().file;
String lw = phrase.getLastWord(); String lw = phrase.getUnknownSearchWord();
NameStringMatcher sm = phrase.getNameStringMatcher(); NameStringMatcher sm = phrase.getNameStringMatcher();
if (cacheBuilding != s) { if (cacheBuilding != s) {
cacheBuilding = s; cacheBuilding = s;
@ -813,12 +820,12 @@ public class SearchCoreFactory {
@Override @Override
public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException { public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException {
if(phrase.getLastWord().length() == 0) { if(!phrase.isUnknownSearchWordPresent()) {
return false; return false;
} }
boolean parseUrl = parseUrl(phrase, resultMatcher); boolean parseUrl = parseUrl(phrase, resultMatcher);
if(!parseUrl) { if(!parseUrl) {
parseLocation2(phrase, resultMatcher); parseLocation(phrase, resultMatcher);
} }
return super.search(phrase, resultMatcher); return super.search(phrase, resultMatcher);
} }
@ -1106,23 +1113,16 @@ public class SearchCoreFactory {
} }
} }
private void parseLocation2(SearchPhrase phrase, SearchResultMatcher resultMatcher) { private void parseLocation(SearchPhrase phrase, SearchResultMatcher resultMatcher) {
String lw = phrase.getLastWord(); String lw = phrase.getUnknownSearchPhrase();
SearchWord sw = phrase.getLastSelectedWord(); LatLon l = parseLocation(lw);
LatLon l = null;
if (sw != null && sw.getType() == ObjectType.UNKNOWN_NAME_FILTER) {
l = parseLocation(sw.getWord() + ", " + lw);
}
if (l == null) {
l = parseLocation(lw);
}
if (l != null) { if (l != null) {
SearchResult sp = new SearchResult(phrase); SearchResult sp = new SearchResult(phrase);
sp.priority = SEARCH_LOCATION_PRIORITY; sp.priority = SEARCH_LOCATION_PRIORITY;
sp.object = sp.location = l; sp.object = sp.location = l;
sp.localeName = ((float) sp.location.getLatitude()) + ", " + ((float) sp.location.getLongitude()); sp.localeName = ((float) sp.location.getLatitude()) + ", " + ((float) sp.location.getLongitude());
sp.objectType = ObjectType.LOCATION; sp.objectType = ObjectType.LOCATION;
sp.wordsSpan = 2; sp.wordsSpan = lw;
resultMatcher.publish(sp); resultMatcher.publish(sp);
} else if (phrase.isNoSelectedType()) { } else if (phrase.isNoSelectedType()) {
LatLon ll = parsePartialLocation(lw); LatLon ll = parsePartialLocation(lw);
@ -1138,59 +1138,16 @@ public class SearchCoreFactory {
} }
} }
private void parseLocation(SearchPhrase phrase, SearchResultMatcher resultMatcher) {
String lw = phrase.getLastWord();
SearchWord sw = phrase.getLastSelectedWord();
double dd = LocationConvert.convert(lw, false);
if(!Double.isNaN(dd)) {
double pd = Double.NaN;
if(sw != null && sw.getType() == ObjectType.UNKNOWN_NAME_FILTER) {
if(isKindOfNumber(sw.getWord())) {
pd = LocationConvert.convert(sw.getWord(), false);
}
}
if(!Double.isNaN(pd)) {
SearchResult sp = new SearchResult(phrase);
sp.priority = SEARCH_LOCATION_PRIORITY;
sp.object = sp.location = new LatLon(pd, dd);
sp.localeName = ((float)sp.location.getLatitude()) +" " + ((float) sp.location.getLongitude());
sp.objectType = ObjectType.LOCATION;
sp.wordsSpan = 2;
resultMatcher.publish(sp);
} else if (phrase.isNoSelectedType()) {
SearchResult sp = new SearchResult(phrase);
sp.priority = SEARCH_LOCATION_PRIORITY;
sp.object = sp.location = new LatLon(dd, 0);
sp.localeName = ((float) sp.location.getLatitude()) + " <longitude> ";
sp.objectType = ObjectType.PARTIAL_LOCATION;
resultMatcher.publish(sp);
}
}
}
private boolean parseUrl(SearchPhrase phrase, SearchResultMatcher resultMatcher) { private boolean parseUrl(SearchPhrase phrase, SearchResultMatcher resultMatcher) {
String text = phrase.getLastWord(); String text = phrase.getUnknownSearchPhrase();
GeoParsedPoint pnt = GeoPointParserUtil.parse(text); GeoParsedPoint pnt = GeoPointParserUtil.parse(text);
int wordsSpan= 1;
List<SearchWord> lst = phrase.getWords();
for (int i = lst.size() - 1; i >= 0 && (pnt == null || !pnt.isGeoPoint()); i--) {
SearchWord w = lst.get(i);
if (w.getType() != ObjectType.UNKNOWN_NAME_FILTER) {
break;
}
text = w.getWord() + "," + text;
wordsSpan++;
pnt = GeoPointParserUtil.parse(text);
if (pnt != null && pnt.isGeoPoint()) {
break;
}
}
if(pnt != null && pnt.isGeoPoint()) { if(pnt != null && pnt.isGeoPoint()) {
SearchResult sp = new SearchResult(phrase); SearchResult sp = new SearchResult(phrase);
sp.priority = 0; sp.priority = 0;
sp.object = pnt; sp.object = pnt;
sp.wordsSpan = wordsSpan; sp.wordsSpan = text;
sp.location = new LatLon(pnt.getLatitude(), pnt.getLongitude()); sp.location = new LatLon(pnt.getLatitude(), pnt.getLongitude());
sp.localeName = ((float)pnt.getLatitude()) +", " + ((float) pnt.getLongitude()); sp.localeName = ((float)pnt.getLatitude()) +", " + ((float) pnt.getLongitude());
if(pnt.getZoom() > 0) { if(pnt.getZoom() > 0) {

View file

@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher;
import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.CollatorStringMatcher.StringMatcherMode;
@ -21,13 +22,19 @@ import net.osmand.util.MapUtils;
public class SearchPhrase { public class SearchPhrase {
private List<SearchWord> words = new ArrayList<>(); private List<SearchWord> words = new ArrayList<>();
private String lastWord = ""; private List<String> unknownWords = new ArrayList<>();
private String unknownSearchWordTrim;
private String unknownSearchPhrase = "";
private NameStringMatcher sm; private NameStringMatcher sm;
private SearchSettings settings; private SearchSettings settings;
private List<BinaryMapIndexReader> indexes; private List<BinaryMapIndexReader> indexes;
private String lastWordTrim;
private QuadRect cache1kmRect; private QuadRect cache1kmRect;
private boolean unknownSearchWordComplete;
private static final String DELIMITER = ","; private static final String DELIMITER = ",";
private static final String ALLDELIMITERS = "\\s|,";
private static final Pattern reg = Pattern.compile(ALLDELIMITERS);
public enum SearchPhraseDataType { public enum SearchPhraseDataType {
@ -50,24 +57,40 @@ public class SearchPhrase {
sp.words = new ArrayList<>(this.words); sp.words = new ArrayList<>(this.words);
leftWords = leftWords.subList(leftWords.size(), leftWords.size()); leftWords = leftWords.subList(leftWords.size(), leftWords.size());
} }
if (!restText.contains(DELIMITER)) { for(SearchWord w : leftWords) {
sp.lastWord = restText; if(restText.startsWith(w.getWord() + DELIMITER)) {
sp.words.add(w);
restText = restText.substring(w.getWord().length() + DELIMITER.length()).trim();
} else {
break;
}
}
sp.unknownSearchPhrase = restText;
sp.unknownWords.clear();
if (!reg.matcher(restText).find()) {
sp.unknownSearchWordTrim = sp.unknownSearchPhrase.trim();
} else { } else {
for(SearchWord w : leftWords) { sp.unknownSearchWordTrim = "";
if(restText.startsWith(w.getWord() + DELIMITER)) { String[] ws = restText.split(ALLDELIMITERS);
sp.words.add(w); for (int i = 0; i < ws.length ; i++) {
restText = restText.substring(w.getWord().length() + DELIMITER.length()).trim(); String wd = ws[i].trim();
} else { if (wd.length() > 0) {
break; if (i == 0) {
sp.unknownSearchWordTrim = wd;
} else {
sp.unknownWords.add(wd);
}
} }
} }
String[] ws = restText.split(DELIMITER);
for (int i = 0; i < ws.length - 1; i++) {
sp.words.add(new SearchWord(ws[i].trim()));
}
sp.lastWord = ws[ws.length - 1];
} }
sp.lastWordTrim = sp.lastWord.trim(); sp.unknownSearchWordComplete = sp.unknownWords.size() > 0;
if (text.length() > 0 && !sp.unknownSearchWordComplete) {
char ch = text.charAt(text.length() - 1);
sp.unknownSearchWordComplete = ch == ' ' || ch == ',' || ch == '\r' || ch == '\n'
|| ch == ';';
}
return sp; return sp;
} }
@ -77,6 +100,30 @@ public class SearchPhrase {
} }
public boolean isUnknownSearchWordComplete() {
return unknownSearchWordComplete;
}
public List<String> getUnknownSearchWords() {
return unknownWords;
}
public String getUnknownSearchWord() {
return unknownSearchWordTrim;
}
public String getUnknownSearchPhrase() {
return unknownSearchPhrase;
}
public boolean isUnknownSearchWordPresent() {
return unknownSearchWordTrim.length() > 0;
}
public int getUnknownSearchWordLength() {
return unknownSearchWordTrim.length() ;
}
public QuadRect getRadiusBBoxToSearch(int radius) { public QuadRect getRadiusBBoxToSearch(int radius) {
@ -189,13 +236,7 @@ public class SearchPhrase {
public SearchPhrase selectWord(SearchResult res) { public SearchPhrase selectWord(SearchResult res) {
SearchPhrase sp = new SearchPhrase(this.settings); SearchPhrase sp = new SearchPhrase(this.settings);
sp.words.addAll(this.words); sp.words.addAll(this.words);
while(res.wordsSpan > 1) { SearchWord sw = new SearchWord(res.wordsSpan != null ? res.wordsSpan : res.localeName.trim(), res);
if(sp.words.size() > 0) {
sp.words.remove(sp.words.size() - 1);
}
res.wordsSpan--;
}
SearchWord sw = new SearchWord(res.localeName.trim(), res);
sp.words.add(sw); sp.words.add(sw);
return sp; return sp;
} }
@ -229,16 +270,14 @@ public class SearchPhrase {
return false; return false;
} }
public NameStringMatcher getNameStringMatcher() { public NameStringMatcher getNameStringMatcher() {
if(sm != null) { if(sm != null) {
return sm; return sm;
} }
sm = new NameStringMatcher(lastWordTrim, StringMatcherMode.CHECK_STARTS_FROM_SPACE); sm = new NameStringMatcher(unknownSearchWordTrim,
(unknownSearchWordComplete ?
StringMatcherMode.CHECK_EQUALS_FROM_SPACE :
StringMatcherMode.CHECK_STARTS_FROM_SPACE));
return sm; return sm;
} }
@ -261,7 +300,7 @@ public class SearchPhrase {
sb.append(s.getWord()).append(DELIMITER.trim() + " "); sb.append(s.getWord()).append(DELIMITER.trim() + " ");
} }
if(includeLastWord) { if(includeLastWord) {
sb.append(lastWord); sb.append(unknownSearchPhrase);
} }
return sb.toString(); return sb.toString();
} }
@ -269,11 +308,11 @@ public class SearchPhrase {
public String getTextWithoutLastWord() { public String getTextWithoutLastWord() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
List<SearchWord> words = new ArrayList<>(this.words); List<SearchWord> words = new ArrayList<>(this.words);
if(Algorithms.isEmpty(lastWordTrim) && words.size() > 0) { if(Algorithms.isEmpty(unknownSearchWordTrim) && words.size() > 0) {
words.remove(words.size() - 1); words.remove(words.size() - 1);
} }
for(SearchWord s : words) { for(SearchWord s : words) {
sb.append(s.getWord()).append(", "); sb.append(s.getWord()).append(DELIMITER.trim() + " ");
} }
return sb.toString(); return sb.toString();
} }
@ -283,7 +322,7 @@ public class SearchPhrase {
for(SearchWord s : words) { for(SearchWord s : words) {
sb.append(s.getWord()).append(" [" + s.getType() + "], "); sb.append(s.getWord()).append(" [" + s.getType() + "], ");
} }
sb.append(lastWord); sb.append(unknownSearchPhrase);
return sb.toString(); return sb.toString();
} }
@ -297,12 +336,7 @@ public class SearchPhrase {
} }
public boolean isEmpty() { public boolean isEmpty() {
return words.isEmpty() && lastWord.isEmpty(); return words.isEmpty() && unknownSearchPhrase.isEmpty();
}
public String getLastWord() {
return lastWordTrim;
} }
@ -369,8 +403,8 @@ public class SearchPhrase {
private CollatorStringMatcher sm; private CollatorStringMatcher sm;
public NameStringMatcher(String lastWordTrim, StringMatcherMode checkStartsFromSpace) { public NameStringMatcher(String lastWordTrim, StringMatcherMode mode) {
sm = new CollatorStringMatcher(lastWordTrim, StringMatcherMode.CHECK_STARTS_FROM_SPACE); sm = new CollatorStringMatcher(lastWordTrim, mode);
} }
public boolean matches(Collection<String> map) { public boolean matches(Collection<String> map) {

View file

@ -17,6 +17,7 @@ public class SearchResult {
public double priority; public double priority;
public double priorityDistance; public double priorityDistance;
public SearchResult(SearchPhrase sp) { public SearchResult(SearchPhrase sp) {
this.requiredSearchPhrase = sp; this.requiredSearchPhrase = sp;
} }
@ -39,8 +40,8 @@ public class SearchResult {
public Object relatedObject; public Object relatedObject;
public double distRelatedObjectName; public double distRelatedObjectName;
public int wordsSpan = 1; public String wordsSpan ;
public SearchResult preciseSearchResult;

View file

@ -6,10 +6,6 @@ public class SearchWord {
private String word; private String word;
private SearchResult result; private SearchResult result;
public SearchWord(String word) {
this.word = word.trim();
}
public SearchWord(String word, SearchResult res) { public SearchWord(String word, SearchResult res) {
this.word = word.trim(); this.word = word.trim();
this.result = res; this.result = res;

View file

@ -1839,4 +1839,43 @@
<string name="poi_architecture_romanesque">Arĥitekturo: romanika</string> <string name="poi_architecture_romanesque">Arĥitekturo: romanika</string>
<string name="poi_cross">Kruco</string> <string name="poi_cross">Kruco</string>
<string name="poi_tunnel_waterway">Tunelo akvovoja</string>
<string name="poi_tunnel_car">Tunelo voja</string>
<string name="poi_tunnel_pedestrian">Tunelo piedirada</string>
<string name="poi_tunnel_railway">Tunelo fervoja</string>
<string name="poi_bridge_car">Ponto voja</string>
<string name="poi_bridge_pedestrian">Ponto piedirada</string>
<string name="poi_bridge_bicycle">Ponto bicikla</string>
<string name="poi_bridge_railway">Ponto fervoja</string>
<string name="poi_bridge_waterway">Ponto akvovoja</string>
<string name="poi_bridge_structure_beam">Strukturo: traboponto</string>
<string name="poi_bridge_structure_simple_suspension">Strukturo: ŝnurponto</string>
<string name="poi_bridge_structure_suspension">Strukturo: pendoponto</string>
<string name="poi_bridge_structure_arch">Strukturo: arkoponto</string>
<string name="poi_bridge_structure_truss">Strukturo: ĵaluziponto</string>
<string name="poi_bridge_structure_floating">Strukturo: flosponto</string>
<string name="poi_bridge_structure_humpback">Strukturo: arkoponto ĝiba</string>
<string name="poi_bridge_structure_cable_stayed">Strukturo: stajponto</string>
<string name="poi_bridge_structure_boardwalk">Strukturo: tramalsekejo</string>
<string name="poi_bridge_structure_simple_wooden">Strukturo: ligna simpla</string>
<string name="poi_bridge_structure_viaduct">Strukturo: viadukto</string>
<string name="poi_bridge_structure_aqueduct">Strukturo: akvedukto</string>
<string name="poi_bridge_structure_log">Strukturo: arbotrunka travadejo</string>
<string name="poi_bridge_type_movable">Ponto-speco: movebla</string>
<string name="poi_bridge_movable_bascule">Speco de moveblaponto: baskula</string>
<string name="poi_bridge_movable_swing">Speco de moveblaponto: turnebla</string>
<string name="poi_bridge_movable_lift">Speco de moveblaponto: liftoponto</string>
<string name="poi_bridge_movable_drawbridge">Speco de moveblaponto: levoponto</string>
<string name="poi_bridge_movable_submersible">Speco de moveblaponto: submergebla</string>
<string name="poi_bridge_movable_transporter">Speco de moveblaponto: transporta</string>
<string name="poi_bridge_movable_retractable">Speco de moveblaponto: ŝovebla</string>
<string name="poi_lit_yes">Prilumado: jes</string>
<string name="poi_lit_no">Prilumado: ne</string>
<string name="poi_surface_unpaved">Pavimo: malfirma</string>
<string name="poi_surface_paved">Pavimo: firma</string>
<string name="poi_surface_asphalt">Pavimo: asfalto</string>
<string name="poi_surface_concrete">Pavimo: betono</string>
<string name="poi_surface_sett">Pavimo: ŝtona</string>
</resources> </resources>

View file

@ -2019,5 +2019,6 @@
<string name="postcode">Poŝtkodo</string> <string name="postcode">Poŝtkodo</string>
<string name="search_categories">Kategorioj</string> <string name="search_categories">Kategorioj</string>
<string name="lang_hsb">Soraba Supra</string> <string name="lang_hsb">Soraba Supra</string>
<string name="share_history_subject">Historio kunhavigita per OsmAnd</string> <string name="share_history_subject">" kunhavigita per OsmAnd"</string>
<string name="show_on_map">Montri sur la mapo</string>
</resources> </resources>

View file

@ -300,7 +300,7 @@
<string name="poi_observatory">Observatorio</string> <string name="poi_observatory">Observatorio</string>
<string name="poi_astronomical_observatory">Observatorio astronómico</string> <string name="poi_astronomical_observatory">Observatorio astronómico</string>
<string name="poi_tower">Torre</string> <string name="poi_tower">Torre</string>
<string name="poi_mast">Mástil</string> <string name="poi_mast">Antena de comunicación</string>
<string name="poi_radar">Radar</string> <string name="poi_radar">Radar</string>
<string name="poi_construction">Construcción</string> <string name="poi_construction">Construcción</string>
<string name="poi_works">Fábrica</string> <string name="poi_works">Fábrica</string>
@ -2958,7 +2958,7 @@
<string name="poi_pump_status_broken">Bomba en mal estado</string> <string name="poi_pump_status_broken">Bomba en mal estado</string>
<string name="poi_pump_status_locked">Bomba bloqueada</string> <string name="poi_pump_status_locked">Bomba bloqueada</string>
<string name="poi_valley_balka">Montes Balcanes</string> <string name="poi_valley_balka">Balka (cauce seco)</string>
<string name="poi_payment_troika_yes">Acepta tarjeta Troika</string> <string name="poi_payment_troika_yes">Acepta tarjeta Troika</string>
<string name="poi_payment_troika_no">No acepta tarjeta Troika</string> <string name="poi_payment_troika_no">No acepta tarjeta Troika</string>

View file

@ -2200,5 +2200,6 @@
<string name="postcode">Código postal</string> <string name="postcode">Código postal</string>
<string name="search_categories">Categorías</string> <string name="search_categories">Categorías</string>
<string name="lang_hsb">Sorabo (Alto)</string> <string name="lang_hsb">Sorabo (Alto)</string>
<string name="share_history_subject">Historial compartido vía OsmAnd</string> <string name="share_history_subject">" compartido vía OsmAnd"</string>
<string name="show_on_map">Mostrar en el mapa</string>
</resources> </resources>

View file

@ -281,7 +281,7 @@
<string name="poi_observatory">Observatorio</string> <string name="poi_observatory">Observatorio</string>
<string name="poi_astronomical_observatory">Observatorio astronómico</string> <string name="poi_astronomical_observatory">Observatorio astronómico</string>
<string name="poi_tower">Torre</string> <string name="poi_tower">Torre</string>
<string name="poi_mast">Mástil</string> <string name="poi_mast">Antena de comunicación</string>
<string name="poi_radar">Radar</string> <string name="poi_radar">Radar</string>
<string name="poi_construction">Construcción</string> <string name="poi_construction">Construcción</string>
<string name="poi_works">Fábrica</string> <string name="poi_works">Fábrica</string>
@ -2721,7 +2721,7 @@
<string name="poi_pump_status_broken">Bomba en mal estado</string> <string name="poi_pump_status_broken">Bomba en mal estado</string>
<string name="poi_pump_status_locked">Bomba bloqueada</string> <string name="poi_pump_status_locked">Bomba bloqueada</string>
<string name="poi_valley_balka">Montes Balcanes</string> <string name="poi_valley_balka">Balka (cauce seco)</string>
<string name="poi_payment_troika_yes">Acepta tarjeta Troika</string> <string name="poi_payment_troika_yes">Acepta tarjeta Troika</string>
<string name="poi_payment_troika_no">No acepta tarjeta Troika</string> <string name="poi_payment_troika_no">No acepta tarjeta Troika</string>

View file

@ -2200,5 +2200,6 @@
<string name="postcode">Código postal</string> <string name="postcode">Código postal</string>
<string name="search_categories">Categorías</string> <string name="search_categories">Categorías</string>
<string name="lang_hsb">Sorabo (Alto)</string> <string name="lang_hsb">Sorabo (Alto)</string>
<string name="share_history_subject">Historial compartido vía OsmAnd</string> <string name="share_history_subject">" compartido vía OsmAnd"</string>
<string name="show_on_map">Mostrar en el mapa</string>
</resources> </resources>

View file

@ -2186,5 +2186,6 @@
<string name="lang_en_gb">Inglés (Reino Unido)</string> <string name="lang_en_gb">Inglés (Reino Unido)</string>
<string name="lang_be_BY">Bielorruso (latino)</string> <string name="lang_be_BY">Bielorruso (latino)</string>
<string name="lang_kn">Canarés</string> <string name="lang_kn">Canarés</string>
<string name="share_history_subject">Historial compartido vía OsmAnd</string> <string name="share_history_subject">" compartido vía OsmAnd"</string>
<string name="show_on_map">Mostrar en el mapa</string>
</resources> </resources>

View file

@ -2129,7 +2129,7 @@
<string name="upload_osm_note">Envoyer la Note OSM</string> <string name="upload_osm_note">Envoyer la Note OSM</string>
<string name="download_files_error_not_enough_space">Espace insuffisant ! Cette opération requiert temporairement {3} MB et {1} MB seront utilisés de manière permanente. Actuellement {2} MB sont disponibles.</string> <string name="download_files_error_not_enough_space">Espace insuffisant ! Cette opération requiert temporairement {3} MB et {1} MB seront utilisés de manière permanente. Actuellement {2} MB sont disponibles.</string>
<string name="download_files_question_space_with_temp">Souhaitez-vous télécharger {0} fichier(s) ? Cette opération requiert temporairement {3} MB et {1} MB seront utilisés de manière permanente. Actuellement {2} MB sont disponibles.</string> <string name="download_files_question_space_with_temp">Souhaitez-vous télécharger {0} fichier(s) ? Cette opération requiert temporairement {3} MB et {1} MB seront utilisés de manière permanente. Actuellement {2} MB sont disponibles.</string>
<string name="osmand_plus_extended_description_4000_chars_v2">" OsmAnd Maps &amp; Navigation- Visualisez des cartes, calculez des itinéraires et laissez-vous guidez sur le trajet sans connexion Internet ! Commencez par télécharger une carte.\nBasic options: • Detailed maps of 200 countries • Offline navigator with voice prompts • Address search in offline mode • Info about locations on the map: places of interest, cafes, parking lots, shops • Adding locations to favorites • Driving, cycling and pedestrian navigation Additional options: • Ability to view and record GPX tracks • Wikipedia description of POI • Adding photo, audio, and video notes to the map • Day and Night map modes for more convenient driving • Information about public transport routes and stops • Bicycle paths and footpaths • Walking trails for tourism all over the world • Online maps from numerous sources • Info about road pavement quality and street lighting • Adding, editing and deleting POI (for OpenStreetMap.org users) • OsMo - live monitoring of other devices Get a reliable navigator in your country - be it France, Germany, Mexico, United Kingdom, Spain, the Netherlands, USA, Russia, Brazil or any other state. Plugins: • Contour maps and terrain shading https://goo.gl/7mojP8 Contour lines data and terrain visualization added to the basic OsmAnd map. • Ski maps https://goo.gl/pX6DxJ The info about ski pistes, cross-country skiing tracks, cable railways and ski lifts. • Nautical map https://goo.gl/0hEdxm Special map style for viewing nautical navigation signs for arterial and nearshore marine navigation. • Parking position https://goo.gl/6JxQXF Helps you mark the location of your parked vehicle and see how much time left if the parking is time-limited. Stay tuned! Twitter: https://twitter.com/osmandapp Facebook: https://www.facebook.com/osmandapp Site: http://osmand.net If you need help with OsmAnd application, please contact our support team: support@osmand.net. "</string> <string name="osmand_plus_extended_description_4000_chars_v2">" OsmAnd Maps &amp; Navigation - Visualisez des cartes, calculez des itinéraires et laissez-vous guidez sur le trajet sans connexion Internet ! Commencez par télécharger une carte.\nBasic options: • Detailed maps of 200 countries • Offline navigator with voice prompts • Address search in offline mode • Info about locations on the map: places of interest, cafes, parking lots, shops • Adding locations to favorites • Driving, cycling and pedestrian navigation Additional options: • Ability to view and record GPX tracks • Wikipedia description of POI • Adding photo, audio, and video notes to the map • Day and Night map modes for more convenient driving • Information about public transport routes and stops • Bicycle paths and footpaths • Walking trails for tourism all over the world • Online maps from numerous sources • Info about road pavement quality and street lighting • Adding, editing and deleting POI (for OpenStreetMap.org users) • OsMo - live monitoring of other devices Get a reliable navigator in your country - be it France, Germany, Mexico, United Kingdom, Spain, the Netherlands, USA, Russia, Brazil or any other state. Plugins: • Contour maps and terrain shading https://goo.gl/7mojP8 Contour lines data and terrain visualization added to the basic OsmAnd map. • Ski maps https://goo.gl/pX6DxJ The info about ski pistes, cross-country skiing tracks, cable railways and ski lifts. • Nautical map https://goo.gl/0hEdxm Special map style for viewing nautical navigation signs for arterial and nearshore marine navigation. • Parking position https://goo.gl/6JxQXF Helps you mark the location of your parked vehicle and see how much time is left if the parking is time-limited. Stay tuned! Twitter: https://twitter.com/osmandapp Facebook: https://www.facebook.com/osmandapp Site: http://osmand.net If you need help with OsmAnd application, please contact our support team: support@osmand.net. "</string>
<string name="donations">Donations</string> <string name="donations">Donations</string>
<string name="number_of_recipients">Nombre de destinataires</string> <string name="number_of_recipients">Nombre de destinataires</string>
<string name="osm_live_subscribe_btn">S\'abonner</string> <string name="osm_live_subscribe_btn">S\'abonner</string>
@ -2244,5 +2244,6 @@
<string name="city_type_neighbourhood">Quartier</string> <string name="city_type_neighbourhood">Quartier</string>
<string name="postcode">Code postal</string> <string name="postcode">Code postal</string>
<string name="search_categories">Catégories</string> <string name="search_categories">Catégories</string>
<string name="share_history_subject">Historique partagé via OsmAnd</string> <string name="share_history_subject">" Partagé via OsmAnd"</string>
<string name="show_on_map">Afficher sur la carte</string>
</resources> </resources>

View file

@ -2224,5 +2224,6 @@
<string name="postcode">Kod pocztowy</string> <string name="postcode">Kod pocztowy</string>
<string name="search_categories">Kategorie</string> <string name="search_categories">Kategorie</string>
<string name="lang_hsb">Górnołużycki</string> <string name="lang_hsb">Górnołużycki</string>
<string name="share_history_subject">Historia udostępniona przez OsmAnd</string> <string name="share_history_subject">" udostępnione przez OsmAnd"</string>
<string name="show_on_map">Pokaż na mapie</string>
</resources> </resources>

View file

@ -505,6 +505,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment {
sendIntent.setType("text/plain"); sendIntent.setType("text/plain");
startActivity(sendIntent); startActivity(sendIntent);
} catch (IOException e) { } catch (IOException e) {
Toast.makeText(getActivity(), "Error sharing favorites: " + e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace(); e.printStackTrace();
} }
} }

View file

@ -155,8 +155,8 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
OsmandSettings settings = app.getSettings(); OsmandSettings settings = app.getSettings();
AbstractPoiType abstractPoiType = (AbstractPoiType) searchPhrase.getLastSelectedWord().getResult().object; AbstractPoiType abstractPoiType = (AbstractPoiType) searchPhrase.getLastSelectedWord().getResult().object;
PoiUIFilter filter = new PoiUIFilter(abstractPoiType, app, ""); PoiUIFilter filter = new PoiUIFilter(abstractPoiType, app, "");
if (!Algorithms.isEmpty(searchPhrase.getLastWord())) { if (!Algorithms.isEmpty(searchPhrase.getUnknownSearchWord())) {
filter.setFilterByName(searchPhrase.getLastWord()); filter.setFilterByName(searchPhrase.getUnknownSearchWord());
} }
app.getPoiFilters().clearSelectedPoiFilters(); app.getPoiFilters().clearSelectedPoiFilters();
app.getPoiFilters().addSelectedPoiFilter(filter); app.getPoiFilters().addSelectedPoiFilter(filter);
@ -370,7 +370,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
sr.objectType = ObjectType.FAVORITE; sr.objectType = ObjectType.FAVORITE;
sr.location = new LatLon(point.getLatitude(), point.getLongitude()); sr.location = new LatLon(point.getLatitude(), point.getLongitude());
sr.preferredZoom = 17; sr.preferredZoom = 17;
if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) { } else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
@ -381,7 +381,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
@Override @Override
public int getSearchPriority(SearchPhrase p) { public int getSearchPriority(SearchPhrase p) {
if(!p.isNoSelectedType() || p.getLastWord().isEmpty()) { if(!p.isNoSelectedType() || !p.isUnknownSearchWordPresent()) {
return -1; return -1;
} }
return SEARCH_FAVORITE_API_PRIORITY; return SEARCH_FAVORITE_API_PRIORITY;
@ -664,7 +664,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
private void addMoreButton() { private void addMoreButton() {
OsmandApplication app = getMyApplication(); OsmandApplication app = getMyApplication();
if ((!searchUICore.getPhrase().getLastWord().isEmpty() || searchUICore.getPhrase().isLastWord(ObjectType.POI_TYPE)) if ((searchUICore.getPhrase().isUnknownSearchWordPresent() || searchUICore.getPhrase().isLastWord(ObjectType.POI_TYPE))
&& searchUICore.getPhrase().getSettings().getRadiusLevel() < 7) { && searchUICore.getPhrase().getSettings().getRadiusLevel() < 7) {
QuickSearchMoreListItem moreListItem = QuickSearchMoreListItem moreListItem =
@ -1006,7 +1006,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
sr.objectType = ObjectType.RECENT_OBJ; sr.objectType = ObjectType.RECENT_OBJ;
sr.location = new LatLon(point.getLat(), point.getLon()); sr.location = new LatLon(point.getLat(), point.getLon());
sr.preferredZoom = 17; sr.preferredZoom = 17;
if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) { } else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
@ -1051,7 +1051,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC
sr.location = new LatLon(point.getLatitude(), point.getLongitude()); sr.location = new LatLon(point.getLatitude(), point.getLongitude());
sr.localeRelatedObjectName = info.getFileName(); sr.localeRelatedObjectName = info.getFileName();
sr.preferredZoom = 17; sr.preferredZoom = 17;
if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) {
resultMatcher.publish(sr); resultMatcher.publish(sr);
} else if (phrase.getNameStringMatcher().matches(sr.localeName)) { } else if (phrase.getNameStringMatcher().matches(sr.localeName)) {
resultMatcher.publish(sr); resultMatcher.publish(sr);