New GEO URI parser

This commit is contained in:
Alexey Pelykh 2014-12-29 17:37:28 +02:00
parent deba789918
commit 3d7ca7e09c

View file

@ -1,6 +1,8 @@
package net.osmand.util; package net.osmand.util;
import java.net.URI; import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -82,15 +84,15 @@ public class GeoPointParserUtil {
// google calendar // google calendar
// geo:0,0?q=760 West Genesee Street Syracuse NY 13204 // geo:0,0?q=760 West Genesee Street Syracuse NY 13204
String qstr = "q=760 West Genesee Street Syracuse NY 13204"; String qstr = "760 West Genesee Street Syracuse NY 13204";
url = "geo:0,0?" + qstr; url = "geo:0,0?q=" + qstr;
System.out.println("url: " + url); System.out.println("url: " + url);
actual = GeoPointParserUtil.parse("geo", url); actual = GeoPointParserUtil.parse("geo", url);
assertGeoPoint(actual, new GeoParsedPoint(qstr.replaceAll("\\s+", "+"))); assertGeoPoint(actual, new GeoParsedPoint(qstr));
// geo:0,0?z=11&q=1600+Amphitheatre+Parkway,+CA // geo:0,0?z=11&q=1600+Amphitheatre+Parkway,+CA
qstr = "q=1600+Amphitheatre+Parkway,+CA"; qstr = "1600 Amphitheatre Parkway, CA";
url = "geo:0,0?z=11&" + qstr; url = "geo:0,0?z=11&q=" + URLEncoder.encode(qstr);
System.out.println("url: " + url); System.out.println("url: " + url);
actual = GeoPointParserUtil.parse("geo", url); actual = GeoPointParserUtil.parse("geo", url);
assertGeoPoint(actual, new GeoParsedPoint(qstr)); assertGeoPoint(actual, new GeoParsedPoint(qstr));
@ -450,48 +452,79 @@ public class GeoPointParserUtil {
return null; return null;
} }
if ("geo".equals(scheme) || "osmand.geo".equals(scheme)) { if ("geo".equals(scheme) || "osmand.geo".equals(scheme)) {
final String schemeSpecific = data.getSchemeSpecificPart(); String schemeSpecific = data.getSchemeSpecificPart();
if (schemeSpecific == null) { if (schemeSpecific == null) {
return null; return null;
} }
if (schemeSpecific.startsWith("0,0?")) {
// geo:0,0?q=34.99,-106.61(Treasure Island) String name = null;
// geo:0,0?z=11&q=34.99,-106.61(Treasure Island) final Pattern namePattern = Pattern.compile("[\\+\\s]*\\((.*)\\)[\\+\\s]*$");
String query = schemeSpecific.substring("0,0?".length()); final Matcher nameMatcher = namePattern.matcher(schemeSpecific);
final String pattern = "(?:z=(\\d{1,2}))?&?q=([+-]?\\d+(?:\\.\\d+)?),([+-]?\\d+(?:\\.\\d+)?)[\\+]?(?:\\((.+?)\\))?"; if (nameMatcher.find()) {
final Matcher matcher = Pattern.compile(pattern).matcher(query); name = URLDecoder.decode(nameMatcher.group(1));
if (matcher.matches()) { if (name != null) {
final String z = matcher.group(1); schemeSpecific = schemeSpecific.substring(0, nameMatcher.start());
final String name = matcher.group(4); }
final int zoom = z != null ? Integer.parseInt(z) : GeoParsedPoint.NO_ZOOM; }
final double lat = Double.parseDouble(matcher.group(2));
final double lon = Double.parseDouble(matcher.group(3)); String positionPart;
return new GeoParsedPoint(lat, lon, zoom, name); String queryPart = "";
} else { int queryStartIndex = schemeSpecific.indexOf('?');
// geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA if (queryStartIndex == -1) {
if (query.contains("z=")) positionPart = schemeSpecific;
query = query.substring(query.indexOf("&") + 1); } else {
return new GeoParsedPoint(query); positionPart = schemeSpecific.substring(0, queryStartIndex);
} if (queryStartIndex < schemeSpecific.length())
} else { queryPart = schemeSpecific.substring(queryStartIndex + 1);
// geo:47.6,-122.3 }
// geo:47.6,-122.3?z=11 (Treasure Island)
final String pattern = "([+-]?\\d+(?:\\.\\d+)?),([+-]?\\d+(?:\\.\\d+)?)(?:(?:\\?z=(\\d{1,2}))?|(?:\\?q=.*?)?)[\\+]?(?:\\((.*?)\\))?"; final Pattern positionPattern = Pattern.compile(
final Matcher matcher = Pattern.compile(pattern).matcher(schemeSpecific); "([+-]?\\d+(?:\\.\\d+)?),([+-]?\\d+(?:\\.\\d+)?)");
if (matcher.matches()) { final Matcher positionMatcher = positionPattern.matcher(positionPart);
final double lat = Double.valueOf(matcher.group(1)); if (!positionMatcher.find()) {
final double lon = Double.valueOf(matcher.group(2)); return null;
final String name = matcher.group(4); }
int zoom = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : GeoParsedPoint.NO_ZOOM; double lat = Double.valueOf(positionMatcher.group(1));
if (zoom != GeoParsedPoint.NO_ZOOM) { double lon = Double.valueOf(positionMatcher.group(2));
return new GeoParsedPoint(lat, lon, zoom, name);
} else { int zoom = GeoParsedPoint.NO_ZOOM;
return new GeoParsedPoint(lat, lon, name); String searchRequest = null;
} for (String param : queryPart.split("&")) {
} else { String paramName;
return null; String paramValue = null;
} int nameValueDelimititerIndex = param.indexOf('=');
} if (nameValueDelimititerIndex == -1) {
paramName = param;
} else {
paramName = param.substring(0, nameValueDelimititerIndex);
if (nameValueDelimititerIndex < param.length())
paramValue = param.substring(nameValueDelimititerIndex + 1);
}
if ("z".equals(paramName) && paramValue != null) {
zoom = Integer.parseInt(paramValue);
} else if ("q".equals(paramName) && paramValue != null) {
searchRequest = URLDecoder.decode(paramValue);
}
}
if (searchRequest != null) {
final Matcher positionInSearchRequestMatcher =
positionPattern.matcher(searchRequest);
if (lat == 0.0 && lon == 0.0 && positionInSearchRequestMatcher.find()) {
lat = Double.valueOf(positionInSearchRequestMatcher.group(1));
lon = Double.valueOf(positionInSearchRequestMatcher.group(2));
}
}
if (lat == 0.0 && lon == 0.0 && searchRequest != null) {
return new GeoParsedPoint(searchRequest);
}
if (zoom != GeoParsedPoint.NO_ZOOM) {
return new GeoParsedPoint(lat, lon, zoom, name);
}
return new GeoParsedPoint(lat, lon, name);
} }
return null; return null;
} }