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));
   }
 }