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 2015/02/20 14:34:15 UTC

[4/4] olingo-odata4 git commit: [OLINGO-545] OrderBy and Filter System Query Option evaluation added to TecScenario

[OLINGO-545] OrderBy and Filter System Query Option evaluation added to TecScenario

Signed-off-by: Christian Amend <ch...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/0e6c9a11
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/0e6c9a11
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/0e6c9a11

Branch: refs/heads/master
Commit: 0e6c9a118366a0397594da74087b5812b6f52beb
Parents: cfb72de
Author: Christian Holzer <c....@sap.com>
Authored: Thu Feb 19 17:11:45 2015 +0100
Committer: Christian Amend <ch...@apache.org>
Committed: Fri Feb 20 14:23:32 2015 +0100

----------------------------------------------------------------------
 .../olingo/fit/AbstractBaseTestITCase.java      |  18 +-
 .../olingo/fit/CXFOAuth2HttpClientFactory.java  |   7 +-
 .../tecsvc/client/FilterSystemQueryITCase.java  | 976 +++++++++++++++++++
 .../tecsvc/client/OrderBySystemQueryITCase.java | 172 ++++
 .../client/core/uri/AbstractURIBuilder.java     |   1 -
 .../processor/TechnicalEntityProcessor.java     |  33 +-
 .../tecsvc/processor/TechnicalProcessor.java    |   2 -
 .../expression/ExpressionVisitorImpl.java       | 236 +++++
 .../expression/FilterRuntimeException.java      |  38 +
 .../expression/FilterSystemQueryHandler.java    | 135 +++
 .../expression/operand/TypedOperand.java        | 199 ++++
 .../expression/operand/UntypedOperand.java      | 155 +++
 .../expression/operand/VisitorOperand.java      |  93 ++
 .../expression/operation/BinaryOperator.java    | 318 ++++++
 .../operation/MethodCallOperator.java           | 334 +++++++
 .../expression/operation/UnaryOperator.java     |  63 ++
 .../processor/expression/primitive/EdmNull.java |  58 ++
 17 files changed, 2812 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/fit/src/test/java/org/apache/olingo/fit/AbstractBaseTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/AbstractBaseTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/AbstractBaseTestITCase.java
index 21dcce1..54658ae 100644
--- a/fit/src/test/java/org/apache/olingo/fit/AbstractBaseTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/AbstractBaseTestITCase.java
@@ -18,6 +18,15 @@
  */
 package org.apache.olingo.fit;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.catalina.LifecycleException;
 import org.apache.commons.io.IOUtils;
 import org.apache.olingo.client.api.CommonODataClient;
@@ -34,15 +43,6 @@ import org.junit.BeforeClass;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-
 public abstract class AbstractBaseTestITCase {
 
   /**

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/fit/src/test/java/org/apache/olingo/fit/CXFOAuth2HttpClientFactory.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/CXFOAuth2HttpClientFactory.java b/fit/src/test/java/org/apache/olingo/fit/CXFOAuth2HttpClientFactory.java
index d35b6b0..3a72508 100644
--- a/fit/src/test/java/org/apache/olingo/fit/CXFOAuth2HttpClientFactory.java
+++ b/fit/src/test/java/org/apache/olingo/fit/CXFOAuth2HttpClientFactory.java
@@ -18,11 +18,11 @@
  */
 package org.apache.olingo.fit;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.dataformat.xml.XmlMapper;
 import java.io.IOException;
 import java.net.URI;
+
 import javax.ws.rs.core.MediaType;
+
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
@@ -50,6 +50,9 @@ import org.apache.olingo.client.core.http.AbstractOAuth2HttpClientFactory;
 import org.apache.olingo.client.core.http.OAuth2Exception;
 import org.apache.olingo.fit.rest.OAuth2Provider;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+
 public class CXFOAuth2HttpClientFactory extends AbstractOAuth2HttpClientFactory {
 
   private static final OAuthClientUtils.Consumer OAUTH2_CONSUMER =

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
new file mode 100644
index 0000000..65da795
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java
@@ -0,0 +1,976 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.olingo.fit.tecsvc.client;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.domain.ODataEntity;
+import org.apache.olingo.commons.api.domain.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.ODataObjectFactory;
+import org.apache.olingo.commons.api.domain.ODataValuable;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FilterSystemQueryITCase extends AbstractBaseTestITCase {
+
+  private static final String ES_COMP_ALL_PRIM = "ESCompAllPrim";
+  private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+  private static final String ES_TWO_KEY_NAV = "ESTwoKeyNav";
+  private static final String ES_ALL_PRIM = "ESAllPrim";
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {}
+
+  @Test
+  public void testTimeOfDayLiteral() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "PropertyTimeOfDay eq 03:26:05");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDateLiteral() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "PropertyDate eq 2012-12-03");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDateTimeOffsetLiteral() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "PropertyDateTimeOffset eq 2012-12-03T07:16:23Z");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testInt64Literal() {
+    long value = Integer.MAX_VALUE + 1L;
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "PropertyInt64 gt " + value);
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDoubleLiteral() {
+    Double value = -17900000000000000000.0;
+
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "PropertyDouble le " + value.toString());
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testSimpleEq() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq 1");
+
+    assertEquals(2, result.getBody().getEntities().size());
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testBinaryIntegerOperations() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 add 1 eq (1 sub 3) div 2 mul 3 add 7");
+
+    assertEquals(1, result.getBody().getEntities().size());
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testClientEscaping() {
+    final ODataClient client = getClient();
+    final String filter = client.getFilterFactory().eq(
+        client.getFilterFactory().getArgFactory().property("PropertyString"),
+        client.getFilterFactory().getArgFactory().literal("First Resource - positive values")).build();
+
+    final URI uri = client.newURIBuilder(SERVICE_URI)
+        .appendEntitySetSegment(ES_ALL_PRIM)
+        .filter(filter)
+        .build();
+
+    final ODataRetrieveResponse<ODataEntitySet> response = client.getRetrieveRequestFactory()
+        .getEntitySetRequest(uri).execute();
+
+    assertEquals(1, response.getBody().getEntities().size());
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testStringProperty() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyString eq '2'");
+
+    assertEquals(1, result.getBody().getEntities().size());
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testBooleanOperator() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_TWO_KEY_NAV, "PropertyString eq '2' and PropertyInt16 eq 1");
+    assertEquals(1, result.getBody().getEntities().size());
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyString eq '2' or PropertyInt16 eq 1");
+    assertEquals(2, result.getBody().getEntities().size());
+    oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testBooleanOperatorWithNull() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq null");
+    assertEquals(0, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "null eq null");
+    assertEquals(4, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "null ne null");
+    assertEquals(0, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testUnaryWithNullLiterals() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyBoolean eq not null");
+    assertEquals(0, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyComp/PropertyComp/PropertyBoolean eq 0 add -(5 add null)");
+    assertEquals(0, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testUnaryWithWrongTypes() {
+    fail(ES_ALL_PRIM, "PropertyInt16 eq 6 add - 'test'", HttpStatusCode.BAD_REQUEST);
+    fail(ES_ALL_PRIM, "PropertyBoolean eq not 'test'", HttpStatusCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void testMethodCallsWithNull() {
+    // One representative of "stringFuntion" "residue class"
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "endswith(PropertyString, null) eq null"); // null eq null => true
+    assertEquals(3, result.getBody().getEntities().size());
+
+    // One representative of "stringifiedValueFunction" "residue class"
+    result = sendRequest(ES_ALL_PRIM, "substring(PropertyString, null) eq null"); // null eq null => true
+    assertEquals(3, result.getBody().getEntities().size());
+
+    // Substring
+    result = sendRequest(ES_ALL_PRIM, "hour(null) eq null"); // null eq null => true
+    assertEquals(3, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_ALL_PRIM, "substring(PropertyString, 0, null) eq null"); // null eq null => true
+    assertEquals(3, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testUnknownLiteral() {
+    // Check if the error code is equals to 400
+    fail(ES_ALL_PRIM, "PropertyInt16 eq ThisIsNotAValidLiteral", HttpStatusCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void testErrorCodeArithmetic() {
+    fail(ES_ALL_PRIM, "PropertyInt16 eq 'hey' add 5", HttpStatusCode.BAD_REQUEST);
+    fail(ES_ALL_PRIM, "PropertyDate eq 5.0 add 2012-12-03", HttpStatusCode.BAD_REQUEST);
+    fail(ES_ALL_PRIM, "PropertyDouble mod 5 eq 0", HttpStatusCode.BAD_REQUEST);
+    fail(ES_ALL_PRIM, "UnkownProperty eq null", HttpStatusCode.BAD_REQUEST);
+  }
+
+  @Test
+  public void testNumericBinaryOperationWithNullValues() {
+    // Create new Entries
+    final String filterString = "PropertyString eq null";
+
+    ODataClient client = getClient();
+    ODataObjectFactory objectFactory = client.getObjectFactory();
+
+    ODataEntity entity = objectFactory.newEntity(new FullQualifiedName("olingo.odata.test1.ETAllPrim"));
+
+    entity.getProperties().add(
+        objectFactory.newPrimitiveProperty("PropertyInt16", objectFactory.newPrimitiveValueBuilder()
+            .buildInt16((short) 1)));
+
+    final URI uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").build();
+    ODataEntityCreateResponse<ODataEntity> createResponse =
+        client.getCUDRequestFactory().getEntityCreateRequest(uri, entity).execute();
+
+    final URI receiveURI =
+        client.newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESAllPrim")
+            .filter(filterString)
+            .build();
+
+    ODataEntitySetRequest<ODataEntitySet> filterRequest =
+        client.getRetrieveRequestFactory().getEntitySetRequest(receiveURI);
+    filterRequest.addCustomHeader(HttpHeader.COOKIE, createResponse.getHeader(HttpHeader.SET_COOKIE).iterator().next());
+    ODataRetrieveResponse<ODataEntitySet> filterResponse = filterRequest.execute();
+
+    assertEquals(1, filterResponse.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testNumericComparisionOperators() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 ge 1");
+    assertEquals(4, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt 1");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 lt 2");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 le 2");
+    assertEquals(3, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_ALL_PRIM, "PropertyDouble ge -179000");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_ALL_PRIM, "PropertyDouble gt -179000");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_ALL_PRIM, "PropertyDouble lt -179000");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    result = sendRequest(ES_ALL_PRIM, "PropertyDouble le -179000");
+    assertEquals(2, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testBinaryOperationIntegerDecimalWithPromotion() {
+    String filterString = ""
+        + "PropertyInt16 mod 2 eq " // Choose mod 2 == 1 => { 1, 3, .. }
+        + "(((5 sub 1) div 5) " // Integer Division 4 / 5 == 0
+        + "add 1) " // 0 + 1 = 1
+        + "and "
+        + "PropertyComp/PropertyInt16 eq " // Complex Property
+        + "5.5 mul 2"; // Single * Int16 => Single => Int16 eq Single => Single eq Single
+
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, filterString);
+    assertEquals(3, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+    assertEquals("11", ((ODataValuable) ((ODataValuable) oDataEntity.getProperty("PropertyComp")).getComplexValue()
+        .get("PropertyInt16")).getValue()
+        .toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+    assertEquals("11", ((ODataValuable) ((ODataValuable) oDataEntity.getProperty("PropertyComp")).getComplexValue()
+        .get("PropertyInt16")).getValue()
+        .toString());
+
+    oDataEntity = result.getBody().getEntities().get(2);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+    assertEquals("11", ((ODataValuable) ((ODataValuable) oDataEntity.getProperty("PropertyComp")).getComplexValue()
+        .get("PropertyInt16")).getValue()
+        .toString());
+  }
+
+  @Test
+  public void testNotOperator() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "not (PropertyInt16 eq 1)");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testUnaryMinusOperator() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt -2 add - -3");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testUnaryMinusOperatorDecimal() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 gt -2.0 add - -3.0");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testStringPropertyEqualsNull() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyString eq null");
+    assertEquals(0, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testAddNullLiteral() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 add null eq 1");
+    assertEquals(0, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testAddNullLiteralEqualsNull() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 add null eq null");
+    assertEquals(4, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testSubstringStartAndEndGiven() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "substring(PropertyString, length('First') add 1, 8) eq ('Resource')");
+
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testSubstringStartGiven() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_TWO_KEY_NAV, "substring(PropertyComp/PropertyComp/PropertyString, 6) eq 'Value'");
+
+    assertEquals(4, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(2);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(3);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  @SuppressWarnings("unused")
+  public void testSubstringDouble() {
+    try {
+      ODataRetrieveResponse<ODataEntitySet> result =
+          sendRequest(ES_ALL_PRIM, "substring(PropertyString, length('First')"
+              + "add 1, 2.0 * 4) eq ('Resource')");
+    } catch (ODataClientErrorException e) {
+      assertEquals(400, e.getStatusLine().getStatusCode());
+    }
+  }
+
+  @Test
+  public void testYearFunctionDate() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "year(PropertyDate) eq 2015");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testYearFunctionDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "year(PropertyDateTimeOffset) eq 2012");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testMonthFunctionDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "month(PropertyDateTimeOffset) eq 12");
+    assertEquals(3, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(2);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testMonthFunctionDate() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "month(PropertyDate) eq 11");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDayFunctionDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "day(PropertyDateTimeOffset) eq 3");
+    assertEquals(3, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(2);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDayFunctionDate() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "day(PropertyDate) eq 5");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testHourFunctionDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "hour(PropertyDateTimeOffset) eq 7");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testHourFuntionTimeOfDay() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "hour(PropertyTimeOfDay) eq 3");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testMinuteFunctionDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "minute(PropertyDateTimeOffset) eq 17");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testMinuteFuntionTimeOfDay() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "minute(PropertyTimeOfDay) eq 49");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testSecondFunctionDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> response = sendRequest(ES_ALL_PRIM, "second(PropertyDateTimeOffset) eq 8");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testSecondFuntionTimeOfDay() {
+    ODataRetrieveResponse<ODataEntitySet> response = sendRequest(ES_ALL_PRIM, "second(PropertyTimeOfDay) eq 14");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testFractionalsecondsDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_COMP_ALL_PRIM, "fractionalseconds(PropertyComp/PropertyDateTimeOffset) eq 0.1234567");
+    assertEquals(2, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(1);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testFractionalsecondsDateOfTime() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "fractionalseconds(PropertyTimeOfDay) eq 0");
+    assertEquals(3, response.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testDateTimeFunctionsNull() {
+    ODataRetrieveResponse<ODataEntitySet> response;
+
+    response = sendRequest(ES_ALL_PRIM, "year(null) eq null");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    response = sendRequest(ES_ALL_PRIM, "month(null) eq null");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    response = sendRequest(ES_ALL_PRIM, "day(null) eq null");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    response = sendRequest(ES_ALL_PRIM, "hour(null) eq null");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    response = sendRequest(ES_ALL_PRIM, "minute(null) eq null");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    response = sendRequest(ES_ALL_PRIM, "second(null) eq null");
+    assertEquals(3, response.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testFloor() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq floor(3.8)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq floor(3.1)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testCeiling() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq ceiling(2.1)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq ceiling(2.6)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testRound() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq round(2.5)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq round(2.4)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("2", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq round(2.6)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+
+    result = sendRequest(ES_TWO_KEY_NAV, "PropertyInt16 eq round(3.1)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("3", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+    assertEquals("1", ((ODataValuable) oDataEntity.getProperty("PropertyString")).getValue().toString());
+  }
+
+  @Test
+  public void testEndsWith() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "endswith(PropertyString, 'values')");
+    assertEquals(2, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = result.getBody().getEntities().get(1);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testIndexOf() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "indexof(PropertyString, 'positive') eq 17");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testStartsWith() {
+    ODataRetrieveResponse<ODataEntitySet> result = sendRequest(ES_ALL_PRIM, "startswith(PropertyString, 'First')");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testToLower() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "contains(PropertyString, tolower('POSITIVE'))");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testToUpper() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "contains(PropertyString, concat(toupper('f'), 'irst'))");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testTrim() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "trim(substring(PropertyString, 0, 6)) eq 'First'");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDecimalDiv() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "PropertyDouble eq 0 sub (358000 div 2)");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testNumericPromotionToInt64() {
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "PropertyInt64 eq 0");
+    assertEquals(1, result.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = result.getBody().getEntities().get(0);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void castEdm64ToDouble() {
+    double value = Float.MAX_VALUE + 1;
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest(ES_ALL_PRIM, "PropertyInt64 lt " + value);
+    assertEquals(3, result.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testDateTimeOffsetAddDuraton() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDateTimeOffset eq 2012-12-03T07:16:19Z add duration'PT4S'");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDurrationAddDuration() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDuration eq duration'PT2S' add duration'PT4S'");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDurrationLiteral() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDuration eq duration'P1DT'");
+    assertEquals(0, response.getBody().getEntities().size());
+  }
+
+  @Test
+  public void testDateAddDuration() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDateTimeOffset eq 2012-12-02 add duration'P1DT7H16M23S'");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDateTimeOffsetSubDuration() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDateTimeOffset eq 2012-12-03T07:16:27Z sub duration'PT4S'");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDurrationSubDuration() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDuration sub duration'PT2S' eq duration'PT4S'");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDateSubDuration() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDateTimeOffset eq 2012-12-04 sub duration'P0DT16H43M37S'");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDateSubDate() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDuration eq 2012-12-04 sub 2012-12-04");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testDateTimeOffsetSubDateTimeOffset() {
+    ODataRetrieveResponse<ODataEntitySet> response =
+        sendRequest(ES_ALL_PRIM, "PropertyDuration eq 2005-12-03T00:00:00Z sub 2005-12-03T00:00:00Z");
+    assertEquals(1, response.getBody().getEntities().size());
+
+    final ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testNumericPromotion() {
+    /*
+     * The idea is use the largest possible number of a specific type and add a another number to force an
+     * implicit conversion to an higher type
+     */
+    ODataRetrieveResponse<ODataEntitySet> response;
+
+    // SByte => Int16
+    byte byteValue = Byte.MAX_VALUE; // 2 ^ 7 -1 = 127
+    response = sendRequest(ES_ALL_PRIM, "PropertyInt32 eq " + byteValue + " add " + 1);
+    assertEquals(0, response.getBody().getEntities().size()); // No error occurs
+
+    // Int16 => Int32
+    short shortValue = Short.MAX_VALUE;
+    response = sendRequest(ES_ALL_PRIM, "PropertyInt32 eq " + shortValue + " add " + 1);
+    assertEquals(0, response.getBody().getEntities().size()); // No error occurs
+
+    // Int32 => Int64
+    int intValue = Integer.MAX_VALUE;
+    response = sendRequest(ES_ALL_PRIM, "PropertyInt32 eq " + intValue + " add " + 1);
+    assertEquals(0, response.getBody().getEntities().size()); // No error occurs
+
+    // Int64 => Double
+    Long longValue = Long.MAX_VALUE;
+    response = sendRequest(ES_ALL_PRIM, "PropertyInt32 eq " + longValue + " add " + 1);
+    assertEquals(0, response.getBody().getEntities().size()); // No error occurs
+
+    // Single => Double
+    Float floatValue = Float.MAX_VALUE;
+    response = sendRequest(ES_ALL_PRIM, "PropertyInt32 eq " + floatValue.toString() + " add " + 1.0);
+    assertEquals(0, response.getBody().getEntities().size()); // No error occurs
+  }
+
+  @Test
+  public void testNullComplexProperty() {
+    // Create a new entry.The complex property PropertyCompComp is set to null. So the structure of the property
+    // is still there, but filled is null value (primitive types)
+    // We define a filter, which returns all entry where PropertyCompComp/PropertyComp/PropertyInt16 is equals to 1
+
+    final ODataClient client = getClient();
+    final ODataObjectFactory factory = client.getObjectFactory();
+    ODataEntity newEntity = factory.newEntity(new FullQualifiedName("olingo.odata.test1", "ETKeyNav"));
+    newEntity.getProperties().add(factory.newComplexProperty("PropertyCompComp", null));
+    newEntity.getProperties().add(factory.newPrimitiveProperty("PropertyInt16",
+        factory.newPrimitiveValueBuilder().buildInt16((short) 4)));
+    newEntity.getProperties().add(factory.newPrimitiveProperty("PropertyString",
+        factory.newPrimitiveValueBuilder().buildString("Test")));
+    newEntity.getProperties().add(
+        factory.newComplexProperty("PropertyCompAllPrim",
+            factory.newComplexValue("CTAllPrim")
+                .add(factory.newPrimitiveProperty(
+                    "PropertyString",
+                    factory.newPrimitiveValueBuilder().buildString("Test 3")))));
+
+    newEntity.getProperties().add(
+        factory.newComplexProperty("PropertyCompTwoPrim",
+            factory.newComplexValue("CTTwoPrim")
+                .add(factory.newPrimitiveProperty(
+                    "PropertyInt16",
+                    factory.newPrimitiveValueBuilder().buildInt16((short) 1)))
+                .add(factory.newPrimitiveProperty(
+                    "PropertyString",
+                    factory.newPrimitiveValueBuilder().buildString("Test2")))));
+
+    final URI uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESKeyNav").build();
+    ODataEntityCreateRequest<ODataEntity> request =
+        client.getCUDRequestFactory().getEntityCreateRequest(uri, newEntity);
+    ODataEntityCreateResponse<ODataEntity> response = request.execute();
+    assertEquals(HttpStatusCode.CREATED.getStatusCode(), response.getStatusCode());
+
+    final String cookie = response.getHeader(HttpHeader.SET_COOKIE).iterator().next();
+
+    // Do the filter request
+    ODataRetrieveResponse<ODataEntitySet> result =
+        sendRequest("ESKeyNav", "PropertyCompComp/PropertyComp/PropertyInt16 eq 1", cookie);
+    assertEquals(3, result.getBody().getEntities().size());
+
+    // Try filter all entries where PropertyCompComp is null
+    result = sendRequest("ESKeyNav", "PropertyCompComp/PropertyComp/PropertyInt16 eq null", cookie);
+    assertEquals(1, result.getBody().getEntities().size());
+  }
+  
+  @Test
+  public void testSringFunctionWithoutStringParameters() {
+    fail("ESServerSidePaging", "filter=contains(PropertyInt16, 3) eq 'hallo'", HttpStatusCode.BAD_REQUEST);
+  }
+
+  private ODataRetrieveResponse<ODataEntitySet> sendRequest(String entitySet, String filterString) {
+    return sendRequest(entitySet, filterString, null);
+  }
+
+  private ODataRetrieveResponse<ODataEntitySet> sendRequest(String entitySet, String filterString, String cookie) {
+    final ODataClient client = getClient();
+
+    final URI uri =
+        client.newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment(entitySet)
+            .filter(filterString)
+            .build();
+
+    ODataEntitySetRequest<ODataEntitySet> request = client.getRetrieveRequestFactory().getEntitySetRequest(uri);
+    if (cookie != null) {
+      request.addCustomHeader(HttpHeader.COOKIE, cookie);
+    }
+
+    return request.execute();
+  }
+
+  private void fail(String entitySet, String filterString, HttpStatusCode errorCode) {
+    try {
+      sendRequest(entitySet, filterString);
+      Assert.fail();
+    } catch (ODataClientErrorException e) {
+      assertEquals(errorCode.getStatusCode(), e.getStatusLine().getStatusCode());
+    }
+  }
+
+  @Override
+  protected ODataClient getClient() {
+    ODataClient odata = ODataClientFactory.getV4();
+    odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON);
+    return odata;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
new file mode 100644
index 0000000..21d248c
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/OrderBySystemQueryITCase.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.olingo.fit.tecsvc.client;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.domain.ODataEntity;
+import org.apache.olingo.commons.api.domain.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.ODataValuable;
+import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class OrderBySystemQueryITCase extends AbstractBaseTestITCase {
+
+  private static final String ES_TWO_PRIM = "ESTwoPrim";
+  private static final String ES_ALL_PRIM = "ESAllPrim";
+
+  private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {}
+
+  @Test
+  public void testSimpleOrderBy() {
+    ODataRetrieveResponse<ODataEntitySet> response = null;
+
+    response = sendRequest(ES_ALL_PRIM, "PropertyDate");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(1);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(2);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testSimpleOrderByDecending() {
+    ODataRetrieveResponse<ODataEntitySet> response = null;
+
+    response = sendRequest(ES_ALL_PRIM, "PropertyDate desc");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(1);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(2);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testMultipleOrderBy() {
+    final ODataRetrieveResponse<ODataEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyByte, PropertyInt16");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(1);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(2);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testMultipleOrderByDecending() {
+    final ODataRetrieveResponse<ODataEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyByte, PropertyInt16 desc");
+    assertEquals(3, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("0", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(1);
+    assertEquals("-32768", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(2);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testOrderByWithNull() {
+    final ODataRetrieveResponse<ODataEntitySet> response = sendRequest(ES_TWO_PRIM, "PropertyString");
+    assertEquals(4, response.getBody().getEntities().size());
+
+    ODataEntity oDataEntity = response.getBody().getEntities().get(0);
+    assertEquals("-32766", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(1);
+    assertEquals("32766", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(2);
+    assertEquals("-365", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+
+    oDataEntity = response.getBody().getEntities().get(3);
+    assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
+  }
+
+  @Test
+  public void testOrderByInvalidExpression() {
+    fail(ES_TWO_PRIM, "PropertyString add 10", HttpStatusCode.BAD_REQUEST);   
+  }
+
+  private ODataRetrieveResponse<ODataEntitySet> sendRequest(String entitySet, String orderByString) {
+    final ODataClient client = getClient();
+    String escapedFilterString = escapeFilterString(orderByString);
+
+    final URI uri =
+        client.newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment(entitySet)
+            .orderBy(escapedFilterString)
+            .build();
+
+    ODataEntitySetRequest<ODataEntitySet> request = client.getRetrieveRequestFactory().getEntitySetRequest(uri);
+
+    return request.execute();
+  }
+
+  private void fail(String entitySet, String filterString, HttpStatusCode errorCode) {
+    try {
+      sendRequest(entitySet, filterString);
+      Assert.fail();
+    } catch (ODataClientErrorException e) {
+      assertEquals(errorCode.getStatusCode(), e.getStatusLine().getStatusCode());
+    }
+  }
+
+  private String escapeFilterString(String filterString) {
+    return filterString.replace(" ", "%20");
+  }
+
+  @Override
+  protected ODataClient getClient() {
+    ODataClient odata = ODataClientFactory.getV4();
+    odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON);
+    return odata;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java
index f80e394..5802ff3 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java
@@ -311,7 +311,6 @@ public abstract class AbstractURIBuilder<UB extends CommonURIBuilder<?>> impleme
         // it will try to call URLEncodedUtils.format(Iterable<>,Charset) method,
         // which works in desktop java application, however, throws NoSuchMethodError in android OS,
         // so here manually construct the URL by its overload URLEncodedUtils.format(List<>,String).
-        //String queryStr = URLEncodedUtils.format(list1, "UTF-8");
         final String queryStr = encodeQueryParameter(list1);
         sb.append(queryStr);
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
index 9868366..3113028 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
@@ -32,6 +32,7 @@ import org.apache.olingo.commons.api.http.HttpContentType;
 import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.commons.core.data.EntitySetImpl;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
@@ -52,13 +53,14 @@ import org.apache.olingo.server.api.uri.UriResourceEntitySet;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
 import org.apache.olingo.server.tecsvc.data.DataProvider;
+import org.apache.olingo.server.tecsvc.processor.expression.FilterSystemQueryHandler;
 
 /**
  * Technical Processor for entity-related functionality.
  */
 public class TechnicalEntityProcessor extends TechnicalProcessor
     implements EntityCollectionProcessor, ActionEntityCollectionProcessor, CountEntityCollectionProcessor,
-        EntityProcessor, ActionEntityProcessor, MediaEntityProcessor {
+    EntityProcessor, ActionEntityProcessor, MediaEntityProcessor {
 
   public TechnicalEntityProcessor(final DataProvider dataProvider) {
     super(dataProvider);
@@ -68,14 +70,21 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
   public void readEntityCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
       final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
     validateOptions(uriInfo.asUriInfoResource());
-    final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
-    EntitySet entitySet = readEntityCollection(uriInfo);
-    if (entitySet == null) {
+
+    final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
+    final EntitySet entitySetInitial = readEntityCollection(uriInfo);
+    if (entitySetInitial == null) {
       throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
     } else {
-      if (uriInfo.getCountOption() != null && uriInfo.getCountOption().getValue()) {
-        setCount(entitySet);
-      }
+      // Modifying the original entitySet means modifying the "database", so we have to make a shallow
+      // copy of the entity set (new EntitySet, but exactly the same data)
+      EntitySet entitySet = new EntitySetImpl();
+      entitySet.getEntities().addAll(entitySetInitial.getEntities());
+
+      // Apply system query options
+      FilterSystemQueryHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, edmEntitySet);
+      FilterSystemQueryHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, edmEntitySet);
+      
       final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
       ODataSerializer serializer = odata.createSerializer(format);
       final ExpandOption expand = uriInfo.getExpandOption();
@@ -95,7 +104,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
   @Override
   public void processActionEntityCollection(final ODataRequest request, final ODataResponse response,
       final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat)
-          throws ODataApplicationException, DeserializerException, SerializerException {
+      throws ODataApplicationException, DeserializerException, SerializerException {
     throw new ODataApplicationException("Process entity collection is not supported yet.",
         HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
   }
@@ -150,7 +159,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
   @Override
   public void createMediaEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
       final ContentType requestFormat, final ContentType responseFormat)
-          throws ODataApplicationException, DeserializerException, SerializerException {
+      throws ODataApplicationException, DeserializerException, SerializerException {
     createEntity(request, response, uriInfo, requestFormat, responseFormat);
   }
 
@@ -168,9 +177,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
     final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
 
     Entity entity = dataProvider.create(edmEntitySet);
-    if (edmEntityType.hasStream()) {  // called from createMediaEntity(...), not directly
+    if (edmEntityType.hasStream()) { // called from createMediaEntity(...), not directly
       dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()),
-              requestFormat.toContentTypeString());
+          requestFormat.toContentTypeString());
     } else {
       dataProvider.update(edmEntitySet, entity,
           odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
@@ -228,7 +237,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
   @Override
   public void processActionEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
       final ContentType requestFormat, final ContentType responseFormat)
-          throws ODataApplicationException, DeserializerException, SerializerException {
+      throws ODataApplicationException, DeserializerException, SerializerException {
     throw new ODataApplicationException("Process entity is not supported yet.",
         HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
index 3ecb4ed..31257cb 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
@@ -156,9 +156,7 @@ public abstract class TechnicalProcessor implements Processor {
   protected void validateOptions(final UriInfoResource uriInfo) throws ODataApplicationException {
     if (uriInfo.getCountOption() != null
         || !uriInfo.getCustomQueryOptions().isEmpty()
-        || uriInfo.getFilterOption() != null
         || uriInfo.getIdOption() != null
-        || uriInfo.getOrderByOption() != null
         || uriInfo.getSearchOption() != null
         || uriInfo.getSkipOption() != null
         || uriInfo.getSkipTokenOption() != null

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/ExpressionVisitorImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/ExpressionVisitorImpl.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/ExpressionVisitorImpl.java
new file mode 100644
index 0000000..12a4940
--- /dev/null
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/ExpressionVisitorImpl.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.olingo.server.tecsvc.processor.expression;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEnumType;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.uri.UriInfoResource;
+import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourcePartTyped;
+import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
+import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor;
+import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind;
+import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind;
+import org.apache.olingo.server.tecsvc.processor.expression.operand.TypedOperand;
+import org.apache.olingo.server.tecsvc.processor.expression.operand.UntypedOperand;
+import org.apache.olingo.server.tecsvc.processor.expression.operand.VisitorOperand;
+import org.apache.olingo.server.tecsvc.processor.expression.operation.BinaryOperator;
+import org.apache.olingo.server.tecsvc.processor.expression.operation.MethodCallOperator;
+import org.apache.olingo.server.tecsvc.processor.expression.operation.UnaryOperator;
+
+public class ExpressionVisitorImpl implements ExpressionVisitor<VisitorOperand> {
+
+  final private Entity entity;
+  final private EdmEntitySet edmEntitySet;
+
+  public ExpressionVisitorImpl(Entity entity, EdmEntitySet edmEntitySet) {
+    this.entity = entity;
+    this.edmEntitySet = edmEntitySet;
+  }
+
+  @Override
+  public VisitorOperand visitBinaryOperator(BinaryOperatorKind operator, VisitorOperand left, VisitorOperand right)
+      throws ExpressionVisitException, ODataApplicationException {
+
+    final BinaryOperator binaryOperator = new BinaryOperator(left, right);
+
+    switch (operator) {
+    case AND:
+      return binaryOperator.andOperator();
+    case OR:
+      return binaryOperator.orOperator();
+    case EQ:
+      return binaryOperator.equalsOperator();
+    case NE:
+      return binaryOperator.notEqualsOperator();
+    case GE:
+      return binaryOperator.greaterEqualsOperator();
+    case GT:
+      return binaryOperator.greaterThanOperator();
+    case LE:
+      return binaryOperator.lessEqualsOperator();
+    case LT:
+      return binaryOperator.lessThanOperator();
+    case ADD:
+    case SUB:
+    case MUL:
+    case DIV:
+    case MOD:
+      return binaryOperator.arithmeticOperator(operator);
+    default:
+      return throwNotImplemented();
+    }
+  }
+
+  @Override
+  public VisitorOperand visitUnaryOperator(UnaryOperatorKind operator, VisitorOperand operand)
+      throws ExpressionVisitException, ODataApplicationException {
+
+    final UnaryOperator unaryOperator = new UnaryOperator(operand);
+
+    switch (operator) {
+    case MINUS:
+      return unaryOperator.minusOperation();
+    case NOT:
+      return unaryOperator.notOperation();
+    default:
+      // Can`t happen
+      return throwNotImplemented();
+    }
+  }
+
+  @Override
+  public VisitorOperand visitMethodCall(MethodKind methodCall, List<VisitorOperand> parameters)
+      throws ExpressionVisitException, ODataApplicationException {
+
+    final MethodCallOperator methodCallOperation = new MethodCallOperator(parameters);
+
+    switch (methodCall) {
+    case ENDSWITH:
+      return methodCallOperation.endsWith();
+    case INDEXOF:
+      return methodCallOperation.indexOf();
+    case STARTSWITH:
+      return methodCallOperation.startsWith();
+    case TOLOWER:
+      return methodCallOperation.toLower();
+    case TOUPPER:
+      return methodCallOperation.toUpper();
+    case TRIM:
+      return methodCallOperation.trim();
+    case SUBSTRING:
+      return methodCallOperation.substring();
+    case CONTAINS:
+      return methodCallOperation.contains();
+    case CONCAT:
+      return methodCallOperation.concat();
+    case LENGTH:
+      return methodCallOperation.length();
+    case YEAR:
+      return methodCallOperation.year();
+    case MONTH:
+      return methodCallOperation.month();
+    case DAY:
+      return methodCallOperation.day();
+    case HOUR:
+      return methodCallOperation.hour();
+    case MINUTE:
+      return methodCallOperation.minute();
+    case SECOND:
+      return methodCallOperation.second();
+    case FRACTIONALSECONDS:
+      return methodCallOperation.fractionalseconds();
+    case ROUND:
+      return methodCallOperation.round();
+    case FLOOR:
+      return methodCallOperation.floor();
+    case CEILING:
+      return methodCallOperation.ceiling();
+
+    default:
+      return throwNotImplemented();
+    }
+  }
+
+  @Override
+  public VisitorOperand visitLambdaExpression(String lambdaFunction, String lambdaVariable, Expression expression)
+      throws ExpressionVisitException, ODataApplicationException {
+
+    return throwNotImplemented();
+  }
+
+  @Override
+  public VisitorOperand visitLiteral(String literal) throws ExpressionVisitException, ODataApplicationException {
+
+    return new UntypedOperand(literal);
+  }
+
+  @Override
+  public VisitorOperand visitMember(UriInfoResource member) throws ExpressionVisitException,
+      ODataApplicationException {
+
+    final List<UriResource> uriResourceParts = member.getUriResourceParts();
+
+    // UriResourceParts contains at least one UriResource
+    Property currentProperty = entity.getProperty(uriResourceParts.get(0).toString());
+    EdmType currentType = ((UriResourcePartTyped) uriResourceParts.get(0)).getType();
+
+    EdmProperty currentEdmProperty = edmEntitySet.getEntityType()
+        .getStructuralProperty(uriResourceParts.get(0).toString());
+
+    for (int i = 1; i < uriResourceParts.size(); i++) {
+      currentType = ((UriResourcePartTyped) uriResourceParts.get(i)).getType();
+
+      if (currentProperty.isComplex() || currentProperty.isLinkedComplex()) {
+        final List<Property> complex = currentProperty.isLinkedComplex() ?
+            currentProperty.asLinkedComplex().getValue() : currentProperty.asComplex();
+
+        for (final Property innerProperty : complex) {
+          if (innerProperty.getName().equals(uriResourceParts.get(i).toString())) {
+            EdmComplexType edmComplexType = (EdmComplexType) currentEdmProperty.getType();
+            currentEdmProperty = edmComplexType.getStructuralProperty(uriResourceParts.get(i).toString());
+            currentProperty = innerProperty;
+            break;
+          }
+        }
+      }
+    }
+
+    return new TypedOperand(((Property) currentProperty).getValue(), currentType, currentEdmProperty);
+  }
+
+  @Override
+  public VisitorOperand visitAlias(String aliasName) throws ExpressionVisitException, ODataApplicationException {
+    return throwNotImplemented();
+  }
+
+  @Override
+  public VisitorOperand visitTypeLiteral(EdmType type) throws ExpressionVisitException, ODataApplicationException {
+    return throwNotImplemented();
+  }
+
+  @Override
+  public VisitorOperand visitLambdaReference(String variableName) throws ExpressionVisitException,
+      ODataApplicationException {
+    return throwNotImplemented();
+  }
+
+  @Override
+  public VisitorOperand visitEnum(EdmEnumType type, List<String> enumValues) throws ExpressionVisitException,
+      ODataApplicationException {
+    return throwNotImplemented();
+  }
+
+  private VisitorOperand throwNotImplemented() throws ODataApplicationException {
+    throw new ODataApplicationException("Not implemented", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(),
+        Locale.ROOT);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterRuntimeException.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterRuntimeException.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterRuntimeException.java
new file mode 100644
index 0000000..21fc110
--- /dev/null
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterRuntimeException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.olingo.server.tecsvc.processor.expression;
+
+import org.apache.olingo.commons.api.ODataRuntimeException;
+
+public class FilterRuntimeException extends ODataRuntimeException {
+
+  private static final long serialVersionUID = 1L;
+
+  public FilterRuntimeException(Exception cause) {
+    super(cause);
+  }
+
+  public FilterRuntimeException(String msg, Exception cause) {
+    super(msg, cause);
+  }
+
+  public FilterRuntimeException(String msg) {
+    super(msg);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/0e6c9a11/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterSystemQueryHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterSystemQueryHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterSystemQueryHandler.java
new file mode 100644
index 0000000..5b5b506
--- /dev/null
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterSystemQueryHandler.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.olingo.server.tecsvc.processor.expression;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.EntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmBoolean;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.uri.queryoption.FilterOption;
+import org.apache.olingo.server.api.uri.queryoption.OrderByItem;
+import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
+import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException;
+import org.apache.olingo.server.tecsvc.processor.expression.operand.TypedOperand;
+import org.apache.olingo.server.tecsvc.processor.expression.operand.VisitorOperand;
+
+public class FilterSystemQueryHandler {
+
+  public static void applyFilterSystemQuery(FilterOption filterOption, EntitySet entitySet, EdmEntitySet edmEntitySet)
+      throws ODataApplicationException {
+
+    if (filterOption == null) {
+      return;
+    }
+
+    try {
+      final Iterator<Entity> iter = entitySet.getEntities().iterator();
+
+      while (iter.hasNext()) {
+        final VisitorOperand operand = filterOption.getExpression()
+            .accept(new ExpressionVisitorImpl(iter.next(), edmEntitySet));
+        final TypedOperand typedOperand = operand.asTypedOperand();
+
+        if (!(typedOperand.is(EdmBoolean.getInstance())
+        && Boolean.TRUE.equals(typedOperand.getTypedValue(Boolean.class)))) {
+          iter.remove();
+        }
+      }
+
+    } catch (ExpressionVisitException e) {
+      throw new ODataApplicationException("Exception in filter evaluation",
+          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+    }
+  }
+
+  public static void applyOrderByOption(final OrderByOption orderByOption, final EntitySet entitySet,
+      final EdmEntitySet edmEntitySet) throws ODataApplicationException {
+
+    if (orderByOption == null) {
+      return;
+    }
+
+    try {
+      applyOrderByOptionInternal(orderByOption, entitySet, edmEntitySet);
+    } catch (FilterRuntimeException e) {
+      if (e.getCause() instanceof ODataApplicationException) {
+        // Throw the nested exception, to send the correct HTTP status code in the HTTP response
+        throw (ODataApplicationException) e.getCause();
+      } else {
+        throw new ODataApplicationException("Exception in orderBy evaluation", HttpStatusCode.INTERNAL_SERVER_ERROR
+            .getStatusCode(), Locale.ROOT);
+      }
+    }
+  }
+
+  private static void applyOrderByOptionInternal(final OrderByOption orderByOption, final EntitySet entitySet,
+      final EdmEntitySet edmEntitySet) throws ODataApplicationException {
+    Collections.sort(entitySet.getEntities(), new Comparator<Entity>() {
+      @Override
+      @SuppressWarnings({ "unchecked", "rawtypes" })
+      public int compare(final Entity e1, final Entity e2) {
+        // Evaluate the first order option for both entity
+        // If and only if the result of the previous order option is equals to 0
+        // evaluate the next order option until all options are evaluated or they are not equals
+        int result = 0;
+
+        for (int i = 0; i < orderByOption.getOrders().size() && result == 0; i++) {
+          try {
+            final OrderByItem item = orderByOption.getOrders().get(i);
+            final TypedOperand op1 =
+                item.getExpression().accept(new ExpressionVisitorImpl(e1, edmEntitySet)).asTypedOperand();
+            final TypedOperand op2 =
+                item.getExpression().accept(new ExpressionVisitorImpl(e2, edmEntitySet)).asTypedOperand();
+
+            if (op1.isNull() || op2.isNull()) {
+              if (op1.isNull() && op2.isNull()) {
+                result = 0; // null is equals to null
+              } else {
+                result = op1.isNull() ? -1 : 1;
+              }
+            } else {
+              Object o1 = op1.getValue();
+              Object o2 = op2.getValue();
+
+              if (o1.getClass() == o2.getClass() && o1 instanceof Comparable) {
+                result = ((Comparable) o1).compareTo(o2);
+              } else {
+                result = 0;
+              }
+            }
+
+            result = item.isDescending() ? result * -1 : result;
+          } catch (ODataApplicationException e) {
+            throw new FilterRuntimeException(e);
+          } catch (ExpressionVisitException e) {
+            throw new FilterRuntimeException(e);
+          }
+        }
+        return result;
+      }
+    });
+  }
+}