[OLINGO-834] parsing of most geo literals in URI parser Signed-off-by: Christian Amend <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/a283bddb Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/a283bddb Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/a283bddb Branch: refs/heads/OLINGO-832_StreamSerializerPoC Commit: a283bddbbf1e6d16a7ec7926e183e367fd7ba544 Parents: c7aa842 Author: Klaus Straubinger <[email protected]> Authored: Fri Jan 15 16:10:32 2016 +0100 Committer: Christian Amend <[email protected]> Committed: Mon Jan 18 13:36:18 2016 +0100 ---------------------------------------------------------------------- .../search/SearchUnaryOperatorKind.java | 2 +- .../core/uri/parser/ExpressionParser.java | 22 +- .../server/core/uri/parser/ParserHelper.java | 83 ++++++- .../server/core/uri/parser/UriTokenizer.java | 244 +++++++++++++++++++ .../core/uri/parser/ExpressionParserTest.java | 19 +- .../core/uri/parser/UriTokenizerTest.java | 64 +++++ .../core/uri/parser/TestUriParserImpl.java | 27 +- 7 files changed, 406 insertions(+), 55 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/search/SearchUnaryOperatorKind.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/search/SearchUnaryOperatorKind.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/search/SearchUnaryOperatorKind.java index bbc9ba6..f4122c7 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/search/SearchUnaryOperatorKind.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/search/SearchUnaryOperatorKind.java @@ -22,6 +22,6 @@ public enum SearchUnaryOperatorKind { NOT; public static SearchUnaryOperatorKind get(final String operator) { - return NOT.equals(operator) ? NOT : null; + return NOT.name().equals(operator) ? NOT : null; } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java index ef7d6da..8b28f6a 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java @@ -156,26 +156,6 @@ public class ExpressionParser { tokenToMethod = Collections.unmodifiableMap(temp); } - private static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType; - static { - /* Enum and null are not present in the map. These have to be handled differently. */ - Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>(); - temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean); - temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String); - // TODO: Check if int64 is correct here or if it has to be decimal or single or double instead. - temp.put(TokenKind.IntegerValue, EdmPrimitiveTypeKind.Int64); - temp.put(TokenKind.GuidValue, EdmPrimitiveTypeKind.Guid); - temp.put(TokenKind.DateValue, EdmPrimitiveTypeKind.Date); - temp.put(TokenKind.DateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset); - temp.put(TokenKind.TimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay); - temp.put(TokenKind.DecimalValue, EdmPrimitiveTypeKind.Decimal); - temp.put(TokenKind.DoubleValue, EdmPrimitiveTypeKind.Double); - temp.put(TokenKind.DurationValue, EdmPrimitiveTypeKind.Duration); - temp.put(TokenKind.BinaryValue, EdmPrimitiveTypeKind.Binary); - - tokenToPrimitiveType = Collections.unmodifiableMap(temp); - } - private final Edm edm; private final OData odata; @@ -408,7 +388,7 @@ public class ExpressionParser { if (primitiveTokenKind == TokenKind.EnumValue) { return createEnumExpression(primitiveValueLiteral); } else { - EdmPrimitiveTypeKind primitiveTypeKind = tokenToPrimitiveType.get(primitiveTokenKind); + EdmPrimitiveTypeKind primitiveTypeKind = ParserHelper.tokenToPrimitiveType.get(primitiveTokenKind); if (primitiveTypeKind == EdmPrimitiveTypeKind.Int64) { primitiveTypeKind = determineIntegerType(primitiveValueLiteral); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java index 852c43a..0ac888f 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java @@ -19,9 +19,11 @@ package org.apache.olingo.server.core.uri.parser; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntityType; @@ -50,6 +52,42 @@ public class ParserHelper { private static final OData odata = new ODataImpl(); + protected static final Map<TokenKind, EdmPrimitiveTypeKind> tokenToPrimitiveType; + static { + /* Enum and null are not present in the map. These have to be handled differently. */ + Map<TokenKind, EdmPrimitiveTypeKind> temp = new HashMap<TokenKind, EdmPrimitiveTypeKind>(); + temp.put(TokenKind.BooleanValue, EdmPrimitiveTypeKind.Boolean); + temp.put(TokenKind.StringValue, EdmPrimitiveTypeKind.String); + // TODO: Check if int64 is correct here or if it has to be decimal or single or double instead. + temp.put(TokenKind.IntegerValue, EdmPrimitiveTypeKind.Int64); + temp.put(TokenKind.GuidValue, EdmPrimitiveTypeKind.Guid); + temp.put(TokenKind.DateValue, EdmPrimitiveTypeKind.Date); + temp.put(TokenKind.DateTimeOffsetValue, EdmPrimitiveTypeKind.DateTimeOffset); + temp.put(TokenKind.TimeOfDayValue, EdmPrimitiveTypeKind.TimeOfDay); + temp.put(TokenKind.DecimalValue, EdmPrimitiveTypeKind.Decimal); + temp.put(TokenKind.DoubleValue, EdmPrimitiveTypeKind.Double); + temp.put(TokenKind.DurationValue, EdmPrimitiveTypeKind.Duration); + temp.put(TokenKind.BinaryValue, EdmPrimitiveTypeKind.Binary); + + temp.put(TokenKind.GeographyPoint, EdmPrimitiveTypeKind.GeographyPoint); + temp.put(TokenKind.GeometryPoint, EdmPrimitiveTypeKind.GeometryPoint); + temp.put(TokenKind.GeographyLineString, EdmPrimitiveTypeKind.GeographyLineString); + temp.put(TokenKind.GeometryLineString, EdmPrimitiveTypeKind.GeometryLineString); + temp.put(TokenKind.GeographyPolygon, EdmPrimitiveTypeKind.GeographyPolygon); + temp.put(TokenKind.GeometryPolygon, EdmPrimitiveTypeKind.GeometryPolygon); + temp.put(TokenKind.GeographyMultiPoint, EdmPrimitiveTypeKind.GeographyMultiPoint); + temp.put(TokenKind.GeometryMultiPoint, EdmPrimitiveTypeKind.GeometryMultiPoint); + temp.put(TokenKind.GeographyMultiLineString, EdmPrimitiveTypeKind.GeographyMultiLineString); + temp.put(TokenKind.GeometryMultiLineString, EdmPrimitiveTypeKind.GeometryMultiLineString); + temp.put(TokenKind.GeographyMultiPolygon, EdmPrimitiveTypeKind.GeographyMultiPolygon); + temp.put(TokenKind.GeometryMultiPolygon, EdmPrimitiveTypeKind.GeometryMultiPolygon); + // TODO: Geo collections +// temp.put(TokenKind.GeographyCollection, EdmPrimitiveTypeKind.GeographyCollection); +// temp.put(TokenKind.GeometryCollection, EdmPrimitiveTypeKind.GeometryCollection); + + tokenToPrimitiveType = Collections.unmodifiableMap(temp); + } + public static void requireNext(UriTokenizer tokenizer, final TokenKind required) throws UriParserException { if (!tokenizer.next(required)) { throw new UriParserSyntaxException("Expected token '" + required.toString() + "' not found.", @@ -88,7 +126,25 @@ public class ParserHelper { TokenKind.DurationValue, TokenKind.BinaryValue, - TokenKind.EnumValue); + TokenKind.EnumValue, + + // Geography and geometry literals are defined to be primitive, + // although they contain several parts with their own meaning. + TokenKind.GeographyPoint, + TokenKind.GeometryPoint, + TokenKind.GeographyLineString, + TokenKind.GeometryLineString, + TokenKind.GeographyPolygon, + TokenKind.GeometryPolygon, + TokenKind.GeographyMultiPoint, + TokenKind.GeometryMultiPoint, + TokenKind.GeographyMultiLineString, + TokenKind.GeometryMultiLineString, + TokenKind.GeographyMultiPolygon, + TokenKind.GeometryMultiPolygon); + // TODO: Geo collections +// TokenKind.GeographyCollection, +// TokenKind.GeometryCollection); } protected static List<UriParameter> parseFunctionParameters(UriTokenizer tokenizer, @@ -326,6 +382,7 @@ public class ParserHelper { } else if (nullable && tokenizer.next(TokenKind.NULL)) { return true; + // Special handling for frequently-used types and types with more than one token kind. } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean).equals(type)) { return tokenizer.next(TokenKind.BooleanValue); } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String).equals(type)) { @@ -338,31 +395,33 @@ public class ParserHelper { return tokenizer.next(TokenKind.IntegerValue); } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Guid).equals(type)) { return tokenizer.next(TokenKind.GuidValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date).equals(type)) { - return tokenizer.next(TokenKind.DateValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset).equals(type)) { - return tokenizer.next(TokenKind.DateTimeOffsetValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.TimeOfDay).equals(type)) { - return tokenizer.next(TokenKind.TimeOfDayValue); } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Decimal).equals(type)) { // The order is important. // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point. return tokenizer.next(TokenKind.DecimalValue) || tokenizer.next(TokenKind.IntegerValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type)) { + } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double).equals(type) + || odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Single).equals(type)) { // The order is important. // A floating-point value should not be parsed as decimal and let the tokenizer stop at 'E'. // A decimal value should not be parsed as integer and let the tokenizer stop at the decimal point. return tokenizer.next(TokenKind.DoubleValue) || tokenizer.next(TokenKind.DecimalValue) || tokenizer.next(TokenKind.IntegerValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration).equals(type)) { - return tokenizer.next(TokenKind.DurationValue); - } else if (odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Binary).equals(type)) { - return tokenizer.next(TokenKind.BinaryValue); } else if (type.getKind() == EdmTypeKind.ENUM) { return tokenizer.next(TokenKind.EnumValue); } else { + // Check the types that have not been checked already above. + for (final Entry<TokenKind, EdmPrimitiveTypeKind> entry : tokenToPrimitiveType.entrySet()) { + final EdmPrimitiveTypeKind kind = entry.getValue(); + if ((kind == EdmPrimitiveTypeKind.Date || kind == EdmPrimitiveTypeKind.DateTimeOffset + || kind == EdmPrimitiveTypeKind.TimeOfDay || kind == EdmPrimitiveTypeKind.Duration + || kind == EdmPrimitiveTypeKind.Binary + || kind.isGeospatial()) + && odata.createPrimitiveTypeInstance(kind).equals(type)) { + return tokenizer.next(entry.getKey()); + } + } return false; } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java index 3b673a6..5a48cc1 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java @@ -84,6 +84,19 @@ public class UriTokenizer { BinaryValue, EnumValue, + GeographyPoint, + GeometryPoint, + GeographyLineString, + GeometryLineString, + GeographyPolygon, + GeometryPolygon, + GeographyMultiPoint, + GeometryMultiPoint, + GeographyMultiLineString, + GeometryMultiLineString, + GeographyMultiPolygon, + GeometryMultiPolygon, + jsonArrayOrObject, Word, @@ -322,6 +335,44 @@ public class UriTokenizer { found = nextEnumValue(); break; + // Geo Values + case GeographyPoint: + found = nextGeoPoint(true); + break; + case GeometryPoint: + found = nextGeoPoint(false); + break; + case GeographyLineString: + found = nextGeoLineString(true); + break; + case GeometryLineString: + found = nextGeoLineString(false); + break; + case GeographyPolygon: + found = nextGeoPolygon(true); + break; + case GeometryPolygon: + found = nextGeoPolygon(false); + break; + case GeographyMultiPoint: + found = nextGeoMultiPoint(true); + break; + case GeometryMultiPoint: + found = nextGeoMultiPoint(false); + break; + case GeographyMultiLineString: + found = nextGeoMultiLineString(true); + break; + case GeometryMultiLineString: + found = nextGeoMultiLineString(false); + break; + case GeographyMultiPolygon: + found = nextGeoMultiPolygon(true); + break; + case GeometryMultiPolygon: + found = nextGeoMultiPolygon(false); + break; + // Complex or Collection Value case jsonArrayOrObject: found = nextJsonArrayOrObject(); @@ -950,6 +1001,199 @@ public class UriTokenizer { } /** + * Moves past a geo prefix if found; otherwise leaves the index unchanged. + * @return whether a geo prefix has been found at the current index + */ + private boolean nextGeoPrefix(final boolean isGeography) { + return nextConstantIgnoreCase(isGeography ? "geography" : "geometry"); + } + + /** + * Moves past an SRID if found; otherwise leaves the index unchanged. + * @return whether an SRID has been found at the current index + */ + private boolean nextSrid() { + final int lastGoodIndex = index; + if (nextConstantIgnoreCase("SRID") && nextCharacter('=') && nextDigit()) { + // The digit checked above is mandatory, four more digits are optional. + nextDigit(); + nextDigit(); + nextDigit(); + nextDigit(); + return true; + } else { + index = lastGoodIndex; + return false; + } + } + + /** + * Moves past a geo position if found; otherwise leaves the index unchanged. + * @return whether a geo position has been found at the current index + */ + private boolean nextPosition() { + final int lastGoodIndex = index; + if ((nextDoubleValue() || nextDecimalValue() || nextIntegerValue(true)) + && nextCharacter(' ') + && (nextDoubleValue() || nextDecimalValue() || nextIntegerValue(true))) { + return true; + } else { + index = lastGoodIndex; + return false; + } + } + + /** + * Moves past a geo-point data instance if found; otherwise leaves the index unchanged. + * @return whether a geo-point data instance has been found at the current index + */ + private boolean nextPointData() { + final int lastGoodIndex = index; + if (nextCharacter('(') && nextPosition() && nextCharacter(')')) { + return true; + } else { + index = lastGoodIndex; + return false; + } + } + + private boolean nextGeoPoint(final boolean isGeography) { + return nextGeoPrefix(isGeography) && nextCharacter('\'') + && nextSrid() && nextCharacter(';') + && nextConstantIgnoreCase("Point") && nextPointData() + && nextCharacter('\''); + } + + /** + * Moves past geo LineString data if found; otherwise leaves the index unchanged. + * @param isRing whether the line is a closed ring (in that case it must have at least four positions, + * and the last position must have the same coordinates as the first position) + * @return whether geo LineString data has been found at the current index + */ + private boolean nextLineStringData(final boolean isRing) { + final int lastGoodIndex = index; + if (nextCharacter('(') && nextPosition()) { + int count = 1; + while (nextCharacter(',')) { + if (nextPosition()) { + count++; + } else { + index = lastGoodIndex; + return false; + } + } + // TODO: Check that the first and last ring positions are identical. + if (count < (isRing ? 4 : 2)) { + index = lastGoodIndex; + return false; + } + if (!nextCharacter(')')) { + index = lastGoodIndex; + return false; + } + return true; + } else { + index = lastGoodIndex; + return false; + } + } + + private boolean nextGeoLineString(final boolean isGeography) { + return nextGeoPrefix(isGeography) && nextCharacter('\'') + && nextSrid() && nextCharacter(';') + && nextConstantIgnoreCase("LineString") && nextLineStringData(false) + && nextCharacter('\''); + } + + /** + * Moves past geo polygon data if found; otherwise leaves the index unchanged. + * @return whether geo polygon data have been found at the current index + */ + private boolean nextPolygonData() { + final int lastGoodIndex = index; + if (nextCharacter('(') && nextLineStringData(true)) { + // The polygon can have holes, described by further rings. + while (nextCharacter(',')) { + if (!nextLineStringData(true)) { + index = lastGoodIndex; + return false; + } + } + if (!nextCharacter(')')) { + index = lastGoodIndex; + return false; + } + return true; + } else { + index = lastGoodIndex; + return false; + } + } + + private boolean nextGeoPolygon(final boolean isGeography) { + return nextGeoPrefix(isGeography) && nextCharacter('\'') + && nextSrid() && nextCharacter(';') + && nextConstantIgnoreCase("Polygon") && nextPolygonData() + && nextCharacter('\''); + } + + private boolean nextMultiPoint() { + if (nextPointData()) { + while (nextCharacter(',')) { + if (!nextPointData()) { + return false; + } + } + } + return true; + } + + private boolean nextGeoMultiPoint(final boolean isGeography) { + return nextGeoPrefix(isGeography) && nextCharacter('\'') + && nextSrid() && nextCharacter(';') + && nextConstantIgnoreCase("MultiPoint") && nextCharacter('(') && nextMultiPoint() && nextCharacter(')') + && nextCharacter('\''); + } + + private boolean nextMultiLineString() { + if (nextLineStringData(false)) { + while (nextCharacter(',')) { + if (!nextLineStringData(false)) { + return false; + } + } + } + return true; + } + + private boolean nextGeoMultiLineString(final boolean isGeography) { + return nextGeoPrefix(isGeography) && nextCharacter('\'') + && nextSrid() && nextCharacter(';') + && nextConstantIgnoreCase("MultiLineString") + && nextCharacter('(') && nextMultiLineString() && nextCharacter(')') + && nextCharacter('\''); + } + + private boolean nextMultiPolygon() { + if (nextPolygonData()) { + while (nextCharacter(',')) { + if (!nextPolygonData()) { + return false; + } + } + } + return true; + } + + private boolean nextGeoMultiPolygon(final boolean isGeography) { + return nextGeoPrefix(isGeography) && nextCharacter('\'') + && nextSrid() && nextCharacter(';') + && nextConstantIgnoreCase("MultiPolygon") + && nextCharacter('(') && nextMultiPolygon() && nextCharacter(')') + && nextCharacter('\''); + } + + /** * Moves past a JSON string if found; otherwise leaves the index unchanged. * @return whether a JSON string has been found at the current index */ http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java index f495c5b..c764999 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/ExpressionParserTest.java @@ -239,14 +239,17 @@ public class ExpressionParserTest { expression = parseMethod(TokenKind.ConcatMethod, "'a'", "'b'"); assertEquals("{concat ['a', 'b']}", expression.toString()); - // TODO: Geo methods. -// expression = parseMethod(TokenKind.GeoDistanceMethod, -// "geography'SRID=0;Point(1.2 3.4)'", "geography'SRID=0;Point(5.6 7.8)'"); -// assertEquals("{geo.distance [geography'SRID=0;Point(1.2 3.4)', geography'SRID=0;Point(5.6 7.8)']}", -// expression.toString()); -// -// expression = parseMethod(TokenKind.GeoIntersectsMethod); -// assertEquals("{geo.intersects []}", expression.toString()); + expression = parseMethod(TokenKind.GeoDistanceMethod, + "geography'SRID=0;Point(1.2 3.4)'", "geography'SRID=0;Point(5.6 7.8)'"); + assertEquals("{geo.distance [geography'SRID=0;Point(1.2 3.4)', geography'SRID=0;Point(5.6 7.8)']}", + expression.toString()); + + expression = parseMethod(TokenKind.GeoIntersectsMethod, + "geometry'SRID=0;Point(1.2 3.4)'", + "geometry'SRID=0;Polygon((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))'"); + assertEquals("{geo.intersects [geometry'SRID=0;Point(1.2 3.4)', " + + "geometry'SRID=0;Polygon((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))']}", + expression.toString()); assertEquals("{startswith [null, 'b']}", parseMethod(TokenKind.StartswithMethod, null, "'b'").toString()); assertEquals("{indexof ['a', null]}", parseMethod(TokenKind.IndexofMethod, "'a'", null).toString()); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java index e130457..78c6204 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java @@ -560,6 +560,70 @@ public class UriTokenizerTest { assertFalse(new UriTokenizer("NOT").next(TokenKind.Word)); } + @Test + public void geoPoint() { + assertTrue(new UriTokenizer("geography'SRID=4326;Point(1.23 4.56)'").next(TokenKind.GeographyPoint)); + assertTrue(new UriTokenizer("GeOgRaPhY'SrId=4326;pOiNt(1 2)'").next(TokenKind.GeographyPoint)); + assertTrue(new UriTokenizer("geography'srid=4326;point(1.2E3 4.5E-6)'").next(TokenKind.GeographyPoint)); + wrongToken(TokenKind.GeographyPoint, "geography'SRID=4326;Point(1.23 4.56)'", 'x'); + + assertTrue(new UriTokenizer("geometry'SRID=0;Point(1 2)'").next(TokenKind.GeometryPoint)); + assertFalse(new UriTokenizer("geometry'SRID=123456;Point(1 2)'").next(TokenKind.GeometryPoint)); + assertFalse(new UriTokenizer("geometry'SRID=123456;Point(1)'").next(TokenKind.GeometryPoint)); + wrongToken(TokenKind.GeometryPoint, "geometry'SRID=0;Point(1.23 4.56)'", ','); + } + + @Test + public void geoLineString() { + assertTrue(new UriTokenizer("geography'SRID=4326;LineString(1.23 4.56,7 8)'") + .next(TokenKind.GeographyLineString)); + wrongToken(TokenKind.GeographyLineString, "geography'SRID=4326;LineString(1.23 4.56,7 8)'", '{'); + + assertTrue(new UriTokenizer("geometry'SRID=0;LineString(1 2,3 4,5 6,7 8)'") + .next(TokenKind.GeometryLineString)); + wrongToken(TokenKind.GeometryLineString, "geometry'SRID=0;LineString(1 2,3 4,5 6,7 8)'", '.'); + } + + @Test + public void geoPolygon() { + assertTrue(new UriTokenizer("geography'SRID=4326;Polygon((0 0,1 0,0 1,0 0))'").next(TokenKind.GeographyPolygon)); + assertTrue(new UriTokenizer("geometry'SRID=0;Polygon((0 0,1 0,0 1,0 0))'").next(TokenKind.GeometryPolygon)); + wrongToken(TokenKind.GeometryPolygon, + "geometry'SRID=0;Polygon((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))'", + 'x'); + } + + @Test + public void geoMultiPoint() { + assertTrue(new UriTokenizer("geography'SRID=4326;MultiPoint()'").next(TokenKind.GeographyMultiPoint)); + assertTrue(new UriTokenizer("geography'SRID=4326;MultiPoint((0 0))'").next(TokenKind.GeographyMultiPoint)); + assertTrue(new UriTokenizer("geometry'SRID=0;MultiPoint((0 0),(1 1))'").next(TokenKind.GeometryMultiPoint)); + wrongToken(TokenKind.GeometryMultiPoint, "geometry'SRID=0;MultiPoint((0 0),(1 1),(2.3 4.5))'", 'x'); + } + + @Test + public void geoMultiLineString() { + assertTrue(new UriTokenizer("geography'SRID=4326;MultiLineString()'").next(TokenKind.GeographyMultiLineString)); + assertTrue(new UriTokenizer("geography'SRID=4326;MultiLineString((1 2,3 4))'") + .next(TokenKind.GeographyMultiLineString)); + + wrongToken(TokenKind.GeometryMultiLineString, + "geometry'SRID=0;MultiLineString((1.23 4.56,7 8),(0 0,1 1),(2 2,3 3))'", + '}'); + } + + @Test + public void geoMultiPolygon() { + assertTrue(new UriTokenizer("geography'SRID=4326;MultiPolygon()'").next(TokenKind.GeographyMultiPolygon)); + assertTrue(new UriTokenizer("geography'SRID=4326;MultiPolygon(((0 0,1 0,0 1,0 0)))'") + .next(TokenKind.GeographyMultiPolygon)); + + wrongToken(TokenKind.GeometryMultiPolygon, + "geometry'SRID=0;MultiPolygon(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))," + + "((0 0,40 0,40 40,0 40,0 0),(10 10,20 10,20 20,10 20,10 10)))'", + 'x'); + } + private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) { assertFalse(new UriTokenizer(disturbCharacter + value).next(kind)); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a283bddb/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestUriParserImpl.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestUriParserImpl.java index fa7a0df..138e598 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestUriParserImpl.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestUriParserImpl.java @@ -22,12 +22,12 @@ import java.util.Arrays; import java.util.Collections; import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.edmx.EdmxReference; import org.apache.olingo.server.api.uri.UriInfoKind; import org.apache.olingo.server.api.uri.UriResourceKind; import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind; -import org.apache.olingo.server.core.uri.parser.UriParserSemanticException; import org.apache.olingo.server.core.uri.testutil.FilterValidator; import org.apache.olingo.server.core.uri.testutil.ResourceValidator; import org.apache.olingo.server.core.uri.testutil.TestUriValidator; @@ -38,11 +38,11 @@ import org.apache.olingo.server.tecsvc.provider.ContainerProvider; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.apache.olingo.server.tecsvc.provider.EntityTypeProvider; import org.apache.olingo.server.tecsvc.provider.PropertyProvider; -import org.junit.Ignore; import org.junit.Test; public class TestUriParserImpl { - private final Edm edm = OData.newInstance().createServiceMetadata( + private static final OData oData = OData.newInstance(); + private final Edm edm = oData.createServiceMetadata( new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm(); private final TestUriValidator testUri = new TestUriValidator().setEdm(edm); private final ResourceValidator testRes = new ResourceValidator().setEdm(edm); @@ -1031,16 +1031,17 @@ public class TestUriParserImpl { } @Test - @Ignore("Geo types are not supported yet.") public void geo() throws Exception { - testFilter.runOnETAllPrim("geo.distance(PropertySByte,PropertySByte)") - .is("<geo.distance(<PropertySByte>,<PropertySByte>)>") - .isMethod(MethodKind.GEODISTANCE, 2); - testFilter.runOnETAllPrim("geo.length(PropertySByte)") - .is("<geo.length(<PropertySByte>)>") - .isMethod(MethodKind.GEOLENGTH, 1); - testFilter.runOnETAllPrim("geo.intersects(PropertySByte,PropertySByte)") - .is("<geo.intersects(<PropertySByte>,<PropertySByte>)>") - .isMethod(MethodKind.GEOINTERSECTS, 2); + testFilter.runOnETAllPrim("geo.distance(geometry'SRID=0;Point(0 0)',geometry'SRID=0;Point(1 1)') lt 1.5") + .left().isMethod(MethodKind.GEODISTANCE, 2) + .goParameter(0).isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.GeometryPoint)) + .root().left() + .goParameter(1).isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.GeometryPoint)); + testFilter.runOnETAllPrim("geo.length(geometry'SRID=0;LineString(0 0,1 1)') lt 1.5") + .left().isMethod(MethodKind.GEOLENGTH, 1) + .goParameter(0).isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.GeometryLineString)); + testFilter.runOnETAllPrim("geo.intersects(geometry'SRID=0;Point(0 0)',null)") + .isMethod(MethodKind.GEOINTERSECTS, 2) + .goParameter(0).isLiteralType(oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.GeometryPoint)); } }
