You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2016/01/18 13:49:52 UTC
[2/3] olingo-odata4 git commit: [OLINGO-834] parsing of most geo
literals in URI parser
[OLINGO-834] parsing of most geo literals in URI parser
Signed-off-by: Christian Amend <ch...@sap.com>
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/master
Commit: a283bddbbf1e6d16a7ec7926e183e367fd7ba544
Parents: c7aa842
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Jan 15 16:10:32 2016 +0100
Committer: Christian Amend <ch...@sap.com>
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));
}
}