Add exceptions to `GeoPointFieldMapper` when parsing `geo_point` object

* moved `geo_point` parsing to GeoUtils
* cleaned up `gzipped.json` for bulktest
* merged `GeoPointFieldMapper` and `GeoPoint` parsing methods

Closes #5390
This commit is contained in:
Florian Schilling 2014-03-12 17:29:05 +01:00
parent 12d1bf8485
commit 689fd15d78
15 changed files with 348 additions and 194 deletions

View File

@ -19,22 +19,12 @@
package org.elasticsearch.common.geo;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import java.io.IOException;
/**
*
*/
public final class GeoPoint {
public static final String LATITUDE = GeoPointFieldMapper.Names.LAT;
public static final String LONGITUDE = GeoPointFieldMapper.Names.LON;
public static final String GEOHASH = GeoPointFieldMapper.Names.GEOHASH;
private double lat;
private double lon;
@ -150,98 +140,4 @@ public final class GeoPoint {
point.resetFromString(latLon);
return point;
}
/**
* Parse a {@link GeoPoint} with a {@link XContentParser}:
*
* @param parser {@link XContentParser} to parse the value from
* @return new {@link GeoPoint} parsed from the parse
*
* @throws IOException
* @throws org.elasticsearch.ElasticsearchParseException
*/
public static GeoPoint parse(XContentParser parser) throws IOException, ElasticsearchParseException {
return parse(parser, new GeoPoint());
}
/**
* Parse a {@link GeoPoint} with a {@link XContentParser}. A geopoint has one of the following forms:
*
* <ul>
* <li>Object: <pre>{&quot;lat&quot;: <i>&lt;latitude&gt;</i>, &quot;lon&quot;: <i>&lt;longitude&gt;</i>}</pre></li>
* <li>String: <pre>&quot;<i>&lt;latitude&gt;</i>,<i>&lt;longitude&gt;</i>&quot;</pre></li>
* <li>Geohash: <pre>&quot;<i>&lt;geohash&gt;</i>&quot;</pre></li>
* <li>Array: <pre>[<i>&lt;longitude&gt;</i>,<i>&lt;latitude&gt;</i>]</pre></li>
* </ul>
*
* @param parser {@link XContentParser} to parse the value from
* @param point A {@link GeoPoint} that will be reset by the values parsed
* @return new {@link GeoPoint} parsed from the parse
*
* @throws IOException
* @throws org.elasticsearch.ElasticsearchParseException
*/
public static GeoPoint parse(XContentParser parser, GeoPoint point) throws IOException, ElasticsearchParseException {
if(parser.currentToken() == Token.START_OBJECT) {
while(parser.nextToken() != Token.END_OBJECT) {
if(parser.currentToken() == Token.FIELD_NAME) {
String field = parser.text();
if(LATITUDE.equals(field)) {
if(parser.nextToken() == Token.VALUE_NUMBER) {
point.resetLat(parser.doubleValue());
} else {
throw new ElasticsearchParseException("latitude must be a number");
}
} else if (LONGITUDE.equals(field)) {
if(parser.nextToken() == Token.VALUE_NUMBER) {
point.resetLon(parser.doubleValue());
} else {
throw new ElasticsearchParseException("latitude must be a number");
}
} else if (GEOHASH.equals(field)) {
if(parser.nextToken() == Token.VALUE_STRING) {
point.resetFromGeoHash(parser.text());
} else {
throw new ElasticsearchParseException("geohash must be a string");
}
} else {
throw new ElasticsearchParseException("field must be either '" + LATITUDE + "', '" + LONGITUDE + "' or '" + GEOHASH + "'");
}
} else {
throw new ElasticsearchParseException("Token '"+parser.currentToken()+"' not allowed");
}
}
return point;
} else if(parser.currentToken() == Token.START_ARRAY) {
int element = 0;
while(parser.nextToken() != Token.END_ARRAY) {
if(parser.currentToken() == Token.VALUE_NUMBER) {
element++;
if(element == 1) {
point.resetLon(parser.doubleValue());
} else if(element == 2) {
point.resetLat(parser.doubleValue());
} else {
throw new ElasticsearchParseException("only two values allowed");
}
} else {
throw new ElasticsearchParseException("Numeric value expected");
}
}
return point;
} else if(parser.currentToken() == Token.VALUE_STRING) {
String data = parser.text();
int comma = data.indexOf(',');
if(comma > 0) {
double lat = Double.parseDouble(data.substring(0, comma).trim());
double lon = Double.parseDouble(data.substring(comma + 1).trim());
return point.reset(lat, lon);
} else {
point.resetFromGeoHash(data);
return point;
}
} else {
throw new ElasticsearchParseException("geo_point expected");
}
}
}

View File

@ -22,12 +22,22 @@ package org.elasticsearch.common.geo;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree;
import org.apache.lucene.util.SloppyMath;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import java.io.IOException;
/**
*/
public class GeoUtils {
public static final String LATITUDE = GeoPointFieldMapper.Names.LAT;
public static final String LONGITUDE = GeoPointFieldMapper.Names.LON;
public static final String GEOHASH = GeoPointFieldMapper.Names.GEOHASH;
/** Earth ellipsoid major axis defined by WGS 84 in meters */
public static final double EARTH_SEMI_MAJOR_AXIS = 6378137.0; // meters (WGS 84)
@ -293,5 +303,114 @@ public class GeoUtils {
}
return rtn;
}
/**
* Parse a {@link GeoPoint} with a {@link XContentParser}:
*
* @param parser {@link XContentParser} to parse the value from
* @return new {@link GeoPoint} parsed from the parse
*
* @throws IOException
* @throws org.elasticsearch.ElasticsearchParseException
*/
public static GeoPoint parseGeoPoint(XContentParser parser) throws IOException, ElasticsearchParseException {
return parseGeoPoint(parser, new GeoPoint());
}
/**
* Parse a {@link GeoPoint} with a {@link XContentParser}. A geopoint has one of the following forms:
*
* <ul>
* <li>Object: <pre>{&quot;lat&quot;: <i>&lt;latitude&gt;</i>, &quot;lon&quot;: <i>&lt;longitude&gt;</i>}</pre></li>
* <li>String: <pre>&quot;<i>&lt;latitude&gt;</i>,<i>&lt;longitude&gt;</i>&quot;</pre></li>
* <li>Geohash: <pre>&quot;<i>&lt;geohash&gt;</i>&quot;</pre></li>
* <li>Array: <pre>[<i>&lt;longitude&gt;</i>,<i>&lt;latitude&gt;</i>]</pre></li>
* </ul>
*
* @param parser {@link XContentParser} to parse the value from
* @param point A {@link GeoPoint} that will be reset by the values parsed
* @return new {@link GeoPoint} parsed from the parse
*
* @throws IOException
* @throws org.elasticsearch.ElasticsearchParseException
*/
public static GeoPoint parseGeoPoint(XContentParser parser, GeoPoint point) throws IOException, ElasticsearchParseException {
double lat = Double.NaN;
double lon = Double.NaN;
String geohash = null;
if(parser.currentToken() == Token.START_OBJECT) {
while(parser.nextToken() != Token.END_OBJECT) {
if(parser.currentToken() == Token.FIELD_NAME) {
String field = parser.text();
if(LATITUDE.equals(field)) {
if(parser.nextToken() == Token.VALUE_NUMBER) {
lat = parser.doubleValue();
} else {
throw new ElasticsearchParseException("latitude must be a number");
}
} else if (LONGITUDE.equals(field)) {
if(parser.nextToken() == Token.VALUE_NUMBER) {
lon = parser.doubleValue();
} else {
throw new ElasticsearchParseException("latitude must be a number");
}
} else if (GEOHASH.equals(field)) {
if(parser.nextToken() == Token.VALUE_STRING) {
geohash = parser.text();
} else {
throw new ElasticsearchParseException("geohash must be a string");
}
} else {
throw new ElasticsearchParseException("field must be either '" + LATITUDE + "', '" + LONGITUDE + "' or '" + GEOHASH + "'");
}
} else {
throw new ElasticsearchParseException("Token '"+parser.currentToken()+"' not allowed");
}
}
if (geohash != null) {
if(!Double.isNaN(lat) || !Double.isNaN(lon)) {
throw new ElasticsearchParseException("field must be either lat/lon or geohash");
} else {
return point.resetFromGeoHash(geohash);
}
} else if (Double.isNaN(lat)) {
throw new ElasticsearchParseException("field [" + LATITUDE + "] missing");
} else if (Double.isNaN(lon)) {
throw new ElasticsearchParseException("field [" + LONGITUDE + "] missing");
} else {
return point.reset(lat, lon);
}
} else if(parser.currentToken() == Token.START_ARRAY) {
int element = 0;
while(parser.nextToken() != Token.END_ARRAY) {
if(parser.currentToken() == Token.VALUE_NUMBER) {
element++;
if(element == 1) {
lon = parser.doubleValue();
} else if(element == 2) {
lat = parser.doubleValue();
} else {
throw new ElasticsearchParseException("only two values allowed");
}
} else {
throw new ElasticsearchParseException("Numeric value expected");
}
}
return point.reset(lat, lon);
} else if(parser.currentToken() == Token.VALUE_STRING) {
String data = parser.text();
int comma = data.indexOf(',');
if(comma > 0) {
lat = Double.parseDouble(data.substring(0, comma).trim());
lon = Double.parseDouble(data.substring(comma + 1).trim());
return point.reset(lat, lon);
} else {
return point.resetFromGeoHash(data);
}
} else {
throw new ElasticsearchParseException("geo_point expected");
}
}
}

View File

@ -57,9 +57,7 @@ import java.util.Locale;
import java.util.Map;
import static org.elasticsearch.index.mapper.MapperBuilders.*;
import static org.elasticsearch.index.mapper.core.TypeParsers.parseField;
import static org.elasticsearch.index.mapper.core.TypeParsers.parseMultiField;
import static org.elasticsearch.index.mapper.core.TypeParsers.parsePathType;
import static org.elasticsearch.index.mapper.core.TypeParsers.*;
/**
* Parsing: We handle:
@ -488,24 +486,19 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
context.path().pathType(pathType);
context.path().add(name());
GeoPoint value = context.parseExternalValue(GeoPoint.class);
if (value != null) {
parseLatLon(context, value.lat(), value.lon());
GeoPoint sparse = context.parseExternalValue(GeoPoint.class);
if (sparse != null) {
parse(context, sparse, null);
} else {
sparse = new GeoPoint();
XContentParser.Token token = context.parser().currentToken();
if (token == XContentParser.Token.START_ARRAY) {
token = context.parser().nextToken();
if (token == XContentParser.Token.START_ARRAY) {
// its an array of array of lon/lat [ [1.2, 1.3], [1.4, 1.5] ]
while (token != XContentParser.Token.END_ARRAY) {
token = context.parser().nextToken();
double lon = context.parser().doubleValue();
token = context.parser().nextToken();
double lat = context.parser().doubleValue();
while ((token = context.parser().nextToken()) != XContentParser.Token.END_ARRAY) {
}
parseLatLon(context, lat, lon);
parse(context, GeoUtils.parseGeoPoint(context.parser(), sparse), null);
token = context.parser().nextToken();
}
} else {
@ -517,22 +510,22 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
while ((token = context.parser().nextToken()) != XContentParser.Token.END_ARRAY) {
}
parseLatLon(context, lat, lon);
parse(context, sparse.reset(lat, lon), null);
} else {
while (token != XContentParser.Token.END_ARRAY) {
if (token == XContentParser.Token.START_OBJECT) {
parseObjectLatLon(context);
} else if (token == XContentParser.Token.VALUE_STRING) {
parseStringLatLon(context);
if (token == XContentParser.Token.VALUE_STRING) {
parsePointFromString(context, sparse, context.parser().text());
} else {
parse(context, GeoUtils.parseGeoPoint(context.parser(), sparse), null);
}
token = context.parser().nextToken();
}
}
}
} else if (token == XContentParser.Token.START_OBJECT) {
parseObjectLatLon(context);
} else if (token == XContentParser.Token.VALUE_STRING) {
parseStringLatLon(context);
parsePointFromString(context, sparse, context.parser().text());
} else {
parse(context, GeoUtils.parseGeoPoint(context.parser(), sparse), null);
}
}
@ -540,44 +533,6 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
context.path().pathType(origPathType);
}
private void parseStringLatLon(ParseContext context) throws IOException {
String value = context.parser().text();
int comma = value.indexOf(',');
if (comma != -1) {
double lat = Double.parseDouble(value.substring(0, comma).trim());
double lon = Double.parseDouble(value.substring(comma + 1).trim());
parseLatLon(context, lat, lon);
} else { // geo hash
parseGeohash(context, value);
}
}
private void parseObjectLatLon(ParseContext context) throws IOException {
XContentParser.Token token;
String currentName = context.parser().currentName();
Double lat = null;
Double lon = null;
String geohash = null;
while ((token = context.parser().nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentName = context.parser().currentName();
} else if (token.isValue()) {
if (currentName.equals(Names.LAT)) {
lat = context.parser().doubleValue();
} else if (currentName.equals(Names.LON)) {
lon = context.parser().doubleValue();
} else if (currentName.equals(Names.GEOHASH)) {
geohash = context.parser().text();
}
}
}
if (geohash != null) {
parseGeohash(context, geohash);
} else if (lat != null && lon != null) {
parseLatLon(context, lat, lon);
}
}
private void parseGeohashField(ParseContext context, String geohash) throws IOException {
int len = Math.min(geoHashPrecision, geohash.length());
int min = enableGeohashPrefix ? 1 : geohash.length();
@ -589,13 +544,12 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
}
}
private void parseLatLon(ParseContext context, double lat, double lon) throws IOException {
parse(context, new GeoPoint(lat, lon), null);
}
private void parseGeohash(ParseContext context, String geohash) throws IOException {
GeoPoint point = GeoHashUtils.decode(geohash);
parse(context, point, geohash);
private void parsePointFromString(ParseContext context, GeoPoint sparse, String point) throws IOException {
if (point.indexOf(',') < 0) {
parse(context, sparse.resetFromGeoHash(point), point);
} else {
parse(context, sparse.resetFromString(point), null);
}
}
private void parse(ParseContext context, GeoPoint point, String geohash) throws IOException {

View File

@ -113,19 +113,19 @@ public class GeoBoundingBoxFilterParser implements FilterParser {
right = parser.doubleValue();
} else {
if (TOP_LEFT.equals(currentFieldName) || TOPLEFT.equals(currentFieldName)) {
GeoPoint.parse(parser, sparse);
GeoUtils.parseGeoPoint(parser, sparse);
top = sparse.getLat();
left = sparse.getLon();
} else if (BOTTOM_RIGHT.equals(currentFieldName) || BOTTOMRIGHT.equals(currentFieldName)) {
GeoPoint.parse(parser, sparse);
GeoUtils.parseGeoPoint(parser, sparse);
bottom = sparse.getLat();
right = sparse.getLon();
} else if (TOP_RIGHT.equals(currentFieldName) || TOPRIGHT.equals(currentFieldName)) {
GeoPoint.parse(parser, sparse);
GeoUtils.parseGeoPoint(parser, sparse);
top = sparse.getLat();
right = sparse.getLon();
} else if (BOTTOM_LEFT.equals(currentFieldName) || BOTTOMLEFT.equals(currentFieldName)) {
GeoPoint.parse(parser, sparse);
GeoUtils.parseGeoPoint(parser, sparse);
bottom = sparse.getLat();
left = sparse.getLon();
} else {

View File

@ -83,7 +83,7 @@ public class GeoDistanceFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
fieldName = currentFieldName;
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
} else if (token == XContentParser.Token.START_OBJECT) {
// the json in the format of -> field : { lat : 30, lon : 12 }
String currentName = parser.currentName();

View File

@ -84,12 +84,12 @@ public class GeoDistanceRangeFilterParser implements FilterParser {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
fieldName = currentFieldName;
} else if (token == XContentParser.Token.START_OBJECT) {
// the json in the format of -> field : { lat : 30, lon : 12 }
fieldName = currentFieldName;
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
} else if (token.isValue()) {
if (currentFieldName.equals("from")) {
if (token == XContentParser.Token.VALUE_NULL) {

View File

@ -93,7 +93,7 @@ public class GeoPolygonFilterParser implements FilterParser {
} else if (token == XContentParser.Token.START_ARRAY) {
if (POINTS.equals(currentFieldName)) {
while ((token = parser.nextToken()) != Token.END_ARRAY) {
shell.add(GeoPoint.parse(parser));
shell.add(GeoUtils.parseGeoPoint(parser));
}
} else {
throw new QueryParsingException(parseContext.index(), "[geo_polygon] filter does not support [" + currentFieldName + "]");

View File

@ -217,12 +217,12 @@ public class GeohashCellFilter {
// A string indicates either a gehash or a lat/lon string
String location = parser.text();
if(location.indexOf(",")>0) {
geohash = GeoPoint.parse(parser).geohash();
geohash = GeoUtils.parseGeoPoint(parser).geohash();
} else {
geohash = location;
}
} else {
geohash = GeoPoint.parse(parser).geohash();
geohash = GeoUtils.parseGeoPoint(parser).geohash();
}
}
} else {

View File

@ -26,6 +26,7 @@ import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.lucene.search.function.ScoreFunction;
import org.elasticsearch.common.unit.DistanceUnit;
@ -206,7 +207,7 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
} else if (parameterName.equals(DecayFunctionBuilder.SCALE)) {
scaleString = parser.text();
} else if (parameterName.equals(DecayFunctionBuilder.ORIGIN)) {
origin = GeoPoint.parse(parser);
origin = GeoUtils.parseGeoPoint(parser);
} else if (parameterName.equals(DecayFunctionBuilder.DECAY)) {
decay = parser.doubleValue();
} else if (parameterName.equals(DecayFunctionBuilder.OFFSET)) {

View File

@ -109,7 +109,7 @@ public class GeoDistanceFacetParser extends AbstractComponent implements FacetPa
entries.add(new GeoDistanceFacet.Entry(from, to, 0, 0, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
}
} else {
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
fieldName = currentName;
}
} else if (token == XContentParser.Token.START_OBJECT) {
@ -118,7 +118,7 @@ public class GeoDistanceFacetParser extends AbstractComponent implements FacetPa
} else {
// the json in the format of -> field : { lat : 30, lon : 12 }
fieldName = currentName;
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
}
} else if (token.isValue()) {
if (currentName.equals("unit")) {

View File

@ -69,7 +69,7 @@ public class GeoDistanceSortParser implements SortParser {
if (token == XContentParser.Token.FIELD_NAME) {
currentName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
fieldName = currentName;
} else if (token == XContentParser.Token.START_OBJECT) {
// the json in the format of -> field : { lat : 30, lon : 12 }
@ -78,7 +78,7 @@ public class GeoDistanceSortParser implements SortParser {
nestedFilter = parsedFilter == null ? null : parsedFilter.filter();
} else {
fieldName = currentName;
GeoPoint.parse(parser, point);
GeoUtils.parseGeoPoint(parser, point);
}
} else if (token.isValue()) {
if ("reverse".equals(currentName)) {

View File

@ -210,13 +210,13 @@ public class GeolocationContextMapping extends ContextMapping {
// otherwise it's a list of locations
ArrayList<String> result = Lists.newArrayList();
while (token != Token.END_ARRAY) {
result.add(GeoPoint.parse(parser).geohash());
result.add(GeoUtils.parseGeoPoint(parser).geohash());
}
return result;
}
} else {
// or a single location
return Collections.singleton(GeoPoint.parse(parser).geohash());
return Collections.singleton(GeoUtils.parseGeoPoint(parser).geohash());
}
}
@ -337,8 +337,8 @@ public class GeolocationContextMapping extends ContextMapping {
precision = new int[] { parsePrecision(parser) };
}
} else if (FIELD_VALUE.equals(fieldName)) {
if(lat == Double.NaN && lon == Double.NaN) {
point = GeoPoint.parse(parser);
if(Double.isNaN(lon) && Double.isNaN(lat)) {
point = GeoUtils.parseGeoPoint(parser);
} else {
throw new ElasticsearchParseException("only lat/lon or [" + FIELD_VALUE + "] is allowed");
}
@ -348,7 +348,7 @@ public class GeolocationContextMapping extends ContextMapping {
}
if (point == null) {
if (lat == Double.NaN || lon == Double.NaN) {
if (Double.isNaN(lat) || Double.isNaN(lon)) {
throw new ElasticsearchParseException("location is missing");
} else {
point = new GeoPoint(lat, lon);
@ -357,7 +357,7 @@ public class GeolocationContextMapping extends ContextMapping {
return new GeoQuery(name, point.geohash(), precision);
} else {
return new GeoQuery(name, GeoPoint.parse(parser).getGeohash(), precision);
return new GeoQuery(name, GeoUtils.parseGeoPoint(parser).getGeohash(), precision);
}
}

View File

@ -0,0 +1,186 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.search.geo;
import org.elasticsearch.common.geo.GeoHashUtils;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.closeTo;
public class GeoPointParsingTests extends ElasticsearchTestCase {
// mind geohash precision and error
private static final double ERROR = 0.00001d;
@Test
public void testGeoPointReset() throws IOException {
double lat = 1 + randomDouble() * 89;
double lon = 1 + randomDouble() * 179;
GeoPoint point = new GeoPoint(0, 0);
assertCloseTo(point, 0, 0);
assertCloseTo(point.reset(lat, lon), lat, lon);
assertCloseTo(point.reset(0, 0), 0, 0);
assertCloseTo(point.resetLat(lat), lat, 0);
assertCloseTo(point.resetLat(0), 0, 0);
assertCloseTo(point.resetLon(lon), 0, lon);
assertCloseTo(point.resetLon(0), 0, 0);
assertCloseTo(point.resetFromGeoHash(GeoHashUtils.encode(lat, lon)), lat, lon);
assertCloseTo(point.reset(0, 0), 0, 0);
assertCloseTo(point.resetFromString(Double.toString(lat) + ", " + Double.toHexString(lon)), lat, lon);
assertCloseTo(point.reset(0, 0), 0, 0);
}
@Test
public void testGeoPointParsing() throws IOException {
double lat = randomDouble() * 180 - 90;
double lon = randomDouble() * 360 - 180;
GeoPoint point = GeoUtils.parseGeoPoint(objectLatLon(lat, lon));
assertCloseTo(point, lat, lon);
GeoUtils.parseGeoPoint(arrayLatLon(lat, lon), point);
assertCloseTo(point, lat, lon);
GeoUtils.parseGeoPoint(geohash(lat, lon), point);
assertCloseTo(point, lat, lon);
GeoUtils.parseGeoPoint(stringLatLon(lat, lon), point);
assertCloseTo(point, lat, lon);
}
// Based on issue5390
@Test
public void testInvalidPointEmbeddedObject() throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.startObject();
content.startObject("location");
content.field("lat", 0).field("lon", 0);
content.endObject();
content.endObject();
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
try {
GeoUtils.parseGeoPoint(parser);
assertTrue(false);
} catch (Throwable e) {}
}
@Test
public void testInvalidPointLatHashMix() throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.startObject();
content.field("lat", 0).field("geohash", GeoHashUtils.encode(0, 0));
content.endObject();
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
try {
GeoUtils.parseGeoPoint(parser);
assertTrue(false);
} catch (Throwable e) {}
}
@Test
public void testInvalidPointLonHashMix() throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.startObject();
content.field("lon", 0).field("geohash", GeoHashUtils.encode(0, 0));
content.endObject();
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
try {
GeoUtils.parseGeoPoint(parser);
assertTrue(false);
} catch (Throwable e) {}
}
@Test
public void testInvalidField() throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.startObject();
content.field("lon", 0).field("lat", 0).field("test", 0);
content.endObject();
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
try {
GeoUtils.parseGeoPoint(parser);
assertTrue(false);
} catch (Throwable e) {}
}
private static XContentParser objectLatLon(double lat, double lon) throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.startObject();
content.field("lat", lat).field("lon", lon);
content.endObject();
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
return parser;
}
private static XContentParser arrayLatLon(double lat, double lon) throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.startArray().value(lon).value(lat).endArray();
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
return parser;
}
private static XContentParser stringLatLon(double lat, double lon) throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.value(Double.toString(lat) + ", " + Double.toString(lon));
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
return parser;
}
private static XContentParser geohash(double lat, double lon) throws IOException {
XContentBuilder content = JsonXContent.contentBuilder();
content.value(GeoHashUtils.encode(lat, lon));
XContentParser parser = JsonXContent.jsonXContent.createParser(content.bytes());
parser.nextToken();
return parser;
}
public static void assertCloseTo(GeoPoint point, double lat, double lon) {
assertThat(point.lat(), closeTo(lat, ERROR));
assertThat(point.lon(), closeTo(lon, ERROR));
}
}

View File

@ -668,11 +668,9 @@ public class SimpleSortTests extends ElasticsearchIntegrationTest {
.field("lvalue", new long[]{i, i + 1, i + 2})
.field("dvalue", new double[]{i, i + 1, i + 2})
.startObject("gvalue")
.startObject("location")
.field("lat", (double) i + 1)
.field("lon", (double) i)
.endObject()
.endObject()
.endObject());
req.execute().actionGet();
}