You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/02/26 10:23:15 UTC
[3/6] olingo-odata4 git commit: [OLINGO-545] Count, Skip,
Top System Query Options and Server-Driven Paging added to TecSvc
[OLINGO-545] Count, Skip, Top System Query Options and Server-Driven Paging added to TecSvc
Signed-off-by: Michael Bolz <mi...@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/2ebdea80
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/2ebdea80
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/2ebdea80
Branch: refs/heads/master
Commit: 2ebdea806c9d2129416f3396ef5e3db2d7c9dd0c
Parents: 394d0f8
Author: Christian Holzer <c....@sap.com>
Authored: Mon Feb 23 09:48:03 2015 +0100
Committer: Michael Bolz <mi...@sap.com>
Committed: Thu Feb 26 09:13:54 2015 +0100
----------------------------------------------------------------------
.../tecsvc/client/FilterSystemQueryITCase.java | 19 +-
.../tecsvc/client/SystemQueryOptionITCase.java | 309 +++++++++++++++++
.../processor/TechnicalEntityProcessor.java | 7 +-
.../tecsvc/processor/TechnicalProcessor.java | 11 +-
.../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 ----
.../queryoptions/SystemQueryOptions.java | 41 +++
.../expression/ExpressionVisitorImpl.java | 236 +++++++++++++
.../expression/FilterRuntimeException.java | 38 +++
.../expression/operand/TypedOperand.java | 199 +++++++++++
.../expression/operand/UntypedOperand.java | 161 +++++++++
.../expression/operand/VisitorOperand.java | 93 ++++++
.../expression/operation/BinaryOperator.java | 318 ++++++++++++++++++
.../operation/MethodCallOperator.java | 334 +++++++++++++++++++
.../expression/operation/UnaryOperator.java | 63 ++++
.../expression/primitive/EdmNull.java | 58 ++++
.../queryoptions/options/CountHandler.java | 31 ++
.../queryoptions/options/FilterHandler.java | 82 +++++
.../queryoptions/options/OrderByHandler.java | 105 ++++++
.../options/ServerSidePagingHandler.java | 110 ++++++
.../queryoptions/options/SkipHandler.java | 54 +++
.../queryoptions/options/TopHandler.java | 47 +++
30 files changed, 2304 insertions(+), 1641 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/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
index 65da795..e996763 100644
--- 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
@@ -61,7 +61,24 @@ public class FilterSystemQueryITCase extends AbstractBaseTestITCase {
ODataEntity oDataEntity = result.getBody().getEntities().get(0);
assertEquals("32767", ((ODataValuable) oDataEntity.getProperty("PropertyInt16")).getValue().toString());
}
-
+
+ @Test
+ public void testBooleanLiteral() {
+ ODataRetrieveResponse<ODataEntitySet> response = sendRequest(ES_ALL_PRIM, "PropertyBoolean eq false");
+ assertEquals(2, 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());
+
+ response = sendRequest(ES_ALL_PRIM, "PropertyBoolean eq true");
+ assertEquals(1, response.getBody().getEntities().size());
+
+ oDataEntity = response.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");
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
new file mode 100644
index 0000000..193800d
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/SystemQueryOptionITCase.java
@@ -0,0 +1,309 @@
+/*
+ * 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 static org.junit.Assert.fail;
+
+import java.net.URI;
+
+import org.apache.olingo.client.api.CommonODataClient;
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.uri.QueryOption;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.domain.CommonODataEntity;
+import org.apache.olingo.commons.api.domain.CommonODataEntitySet;
+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.Test;
+
+public class SystemQueryOptionITCas extends AbstractBaseTestITCase {
+ private static final String PROPERTY_INT16 = "PropertyInt16";
+ private static final String ES_SERVER_SIDE_PAGING = "ESServerSidePaging";
+ private static final String ES_ALL_PRIM = "ESAllPrim";
+ private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+
+ @Test
+ public void testCountSimple() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_ALL_PRIM)
+ .addQueryOption(QueryOption.COUNT, "true")
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(Integer.valueOf(3), response.getBody().getCount());
+ assertEquals(3, response.getBody().getEntities().size());
+ }
+
+ @Test
+ public void testServerSidePagingCount() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .addQueryOption(QueryOption.COUNT, "true")
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(10, response.getBody().getEntities().size());
+ assertEquals(Integer.valueOf(503), response.getBody().getCount());
+ }
+
+ @Test
+ public void testTopSimple() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .addQueryOption(QueryOption.TOP, new Integer(5).toString())
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(5, response.getBody().getEntities().size());
+
+ for (int i = 0; i < 5; i++) {
+ CommonODataEntity entity = response.getBody().getEntities().get(i);
+ assertEquals(new Integer(i + 1).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString());
+ }
+ }
+
+ @Test
+ public void testSkipSimple() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .addQueryOption(QueryOption.SKIP, new Integer(5).toString())
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(10, response.getBody().getEntities().size());
+
+ for (int i = 0; i < 10; i++) {
+ CommonODataEntity entity = response.getBody().getEntities().get(i);
+ assertEquals(new Integer(i + 6).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString());
+ }
+ }
+
+ @Test
+ public void testTopNothing() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .addQueryOption(QueryOption.TOP, new Integer(20).toString())
+ .addQueryOption(QueryOption.SKIP, new Integer(503).toString())
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(0, response.getBody().getEntities().size());
+ }
+
+ @Test
+ public void testSkipNothing() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .addQueryOption(QueryOption.SKIP, new Integer(10000).toString())
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(0, response.getBody().getEntities().size());
+ }
+
+ @Test
+ public void testFilterWithTopSkipOrderByAndServerSidePaging() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .filter("PropertyInt16 le 105") // 1, 2, ... , 105
+ .orderBy("PropertyInt16 desc") // 105, 104, ..., 2, 1
+ .addQueryOption(QueryOption.COUNT, Boolean.TRUE.toString()) // 105
+ .addQueryOption(QueryOption.SKIP, new Integer(3).toString()) // 102, 101, ..., 2, 1
+ .addQueryOption(QueryOption.TOP, new Integer(43).toString()) // 102, 101, ...., 59
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ assertEquals(Integer.valueOf(105), response.getBody().getCount());
+ assertEquals(10, response.getBody().getEntities().size());
+
+ int id = 102;
+
+ // Check first 10 entities
+ for (int i = 0; i < 10; i++) {
+ CommonODataEntity entity = response.getBody().getEntities().get(i);
+ assertEquals(new Integer(id).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString());
+ id--;
+ }
+
+ // Get 3 * 10 = 30 Entities and check the key
+ for (int j = 0; j < 3; j++) {
+ response = client.getRetrieveRequestFactory().getEntitySetRequest(response.getBody().getNext()).execute();
+ assertEquals(Integer.valueOf(105), response.getBody().getCount());
+ assertEquals(10, response.getBody().getEntities().size());
+ for (int i = 0; i < 10; i++) {
+ CommonODataEntity entity = response.getBody().getEntities().get(i);
+ assertEquals(new Integer(id).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString());
+ id--;
+ }
+ }
+
+ // Get the last 3 items
+ response = client.getRetrieveRequestFactory().getEntitySetRequest(response.getBody().getNext()).execute();
+ assertEquals(Integer.valueOf(105), response.getBody().getCount());
+ assertEquals(3, response.getBody().getEntities().size());
+ for (int i = 0; i < 3; i++) {
+ CommonODataEntity entity = response.getBody().getEntities().get(i);
+ assertEquals(new Integer(id).toString(), entity.getProperty(PROPERTY_INT16).getValue().toString());
+ id--;
+ }
+
+ // Make sure that the body no not contain a next link
+ assertEquals(null, response.getBody().getNext());
+ }
+
+ @Test
+ public void testNextLinkFormat() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ // Check initial next link format
+ URI nextLink = response.getBody().getNext();
+ assertEquals("http://localhost:9080/odata-server-tecsvc/odata.svc/ESServerSidePaging?%24skiptoken=1", nextLink
+ .toASCIIString());
+
+ // Check subsequent next links
+ response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(nextLink)
+ .execute();
+
+ nextLink = response.getBody().getNext();
+ assertEquals("http://localhost:9080/odata-server-tecsvc/odata.svc/ESServerSidePaging?%24skiptoken=2", nextLink
+ .toASCIIString());
+ }
+
+ @Test
+ public void testNextLinkFormatWithQueryOptions() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_SERVER_SIDE_PAGING)
+ .addQueryOption(QueryOption.COUNT, Boolean.TRUE.toString())
+ .build();
+
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+
+ // Check initial next link format
+ URI nextLink = response.getBody().getNext();
+ assertEquals("http://localhost:9080/odata-server-tecsvc/odata.svc/ESServerSidePaging?%24count=true&%24skiptoken=1",
+ nextLink.toASCIIString());
+
+ int token = 1;
+ while (nextLink != null) {
+ token++;
+
+ // Check subsequent next links
+ response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(nextLink)
+ .execute();
+
+ nextLink = response.getBody().getNext();
+ if(nextLink != null) {
+ assertEquals(
+ "http://localhost:9080/odata-server-tecsvc/odata.svc/ESServerSidePaging?%24count=true&%24skiptoken=" + token,
+ nextLink.toASCIIString());
+ }
+ }
+
+ assertEquals(50 + 1, token);
+ }
+
+ @Test
+ @SuppressWarnings("unused")
+ public void testNegativeSkip() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_ALL_PRIM)
+ .addQueryOption(QueryOption.SKIP, new Integer(-5).toString())
+ .build();
+
+ try {
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+ fail();
+ } catch (ODataClientErrorException e) {
+ assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), e.getStatusLine().getStatusCode());
+ }
+ }
+
+ @Test
+ @SuppressWarnings("unused")
+ public void testNegativeTop() {
+ CommonODataClient<?> client = getClient();
+ URI uri = client.newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment(ES_ALL_PRIM)
+ .addQueryOption(QueryOption.TOP, new Integer(-5).toString())
+ .build();
+ try {
+ ODataRetrieveResponse<CommonODataEntitySet> response = client.getRetrieveRequestFactory()
+ .getEntitySetRequest(uri)
+ .execute();
+ fail();
+ } catch (ODataClientErrorException e) {
+ assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), e.getStatusLine().getStatusCode());
+ }
+ }
+
+ @Override
+ protected CommonODataClient<?> getClient() {
+ ODataClient odata = ODataClientFactory.getV4();
+ odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON);
+ return odata;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/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 3113028..8fe5879 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
@@ -53,7 +53,8 @@ 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;
+import org.apache.olingo.server.tecsvc.processor.queryoptions.SystemQueryOptions;
+import org.apache.olingo.server.tecsvc.processor.queryoptions.options.ServerSidePagingHandler;
/**
* Technical Processor for entity-related functionality.
@@ -82,8 +83,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
entitySet.getEntities().addAll(entitySetInitial.getEntities());
// Apply system query options
- FilterSystemQueryHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, edmEntitySet);
- FilterSystemQueryHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, edmEntitySet);
+ SystemQueryOptions.applySystemQueryOptions(entitySet, edmEntitySet, uriInfo);
+ ServerSidePagingHandler.applyServerSidePaging(entitySet, request.getRawRequestUri(), uriInfo);
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
ODataSerializer serializer = odata.createSerializer(format);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/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 31257cb..c5853b1 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
@@ -149,18 +149,13 @@ public abstract class TechnicalProcessor implements Processor {
&& resourcePaths.get(navigationCount) instanceof UriResourceNavigation) {
navigationCount++;
}
-
+
return (UriResourceNavigation) resourcePaths.get(--navigationCount);
}
protected void validateOptions(final UriInfoResource uriInfo) throws ODataApplicationException {
- if (uriInfo.getCountOption() != null
- || !uriInfo.getCustomQueryOptions().isEmpty()
- || uriInfo.getIdOption() != null
- || uriInfo.getSearchOption() != null
- || uriInfo.getSkipOption() != null
- || uriInfo.getSkipTokenOption() != null
- || uriInfo.getTopOption() != null) {
+ if (uriInfo.getIdOption() != null
+ || uriInfo.getSearchOption() != null) {
throw new ODataApplicationException("Not all of the specified options are supported.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/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
deleted file mode 100644
index 12a4940..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/ExpressionVisitorImpl.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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/2ebdea80/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
deleted file mode 100644
index 21fc110..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterRuntimeException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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/2ebdea80/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
deleted file mode 100644
index 5b5b506..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/FilterSystemQueryHandler.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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;
- }
- });
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/TypedOperand.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/TypedOperand.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/TypedOperand.java
deleted file mode 100644
index 23037b6..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/TypedOperand.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.operand;
-
-import java.math.BigDecimal;
-import java.util.Locale;
-
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
-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.commons.core.edm.primitivetype.EdmByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDecimal;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt16;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt32;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt64;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSingle;
-import org.apache.olingo.server.api.ODataApplicationException;
-import org.apache.olingo.server.tecsvc.processor.expression.primitive.EdmNull;
-
-public class TypedOperand extends VisitorOperand {
-
- final private EdmType type;
- final private EdmProperty edmProperty;
-
- public TypedOperand(Object value, EdmType type) {
- super(value);
- this.type = type;
- this.edmProperty = null;
- }
-
- public TypedOperand(Object value, EdmType type, EdmProperty edmProperty) {
- super(value);
- this.type = type;
- this.edmProperty = edmProperty;
- }
-
- @Override
- public TypedOperand asTypedOperand() throws ODataApplicationException {
- if (!isNull() && value.getClass() != getDefaultType((EdmPrimitiveType) type)) {
- return asTypedOperand((EdmPrimitiveType) type);
- }
- return this;
- }
-
- @Override
- public TypedOperand asTypedOperand(EdmPrimitiveType... asTypes) throws ODataApplicationException {
- if (type.equals(EdmNull.getInstance())) {
- return this;
- } else if (isNull()) {
- return new TypedOperand(null, asTypes[0]);
- }
-
- Object newValue = null;
- for (EdmPrimitiveType asType : asTypes) {
- // Use BigDecimal for unlimited precision
- if (asType.equals(EdmDouble.getInstance())
- || asType.equals(EdmSingle.getInstance())
- || asType.equals(EdmDecimal.getInstance())) {
-
- try {
- newValue = new BigDecimal(value.toString());
- } catch(NumberFormatException e) {
- // Nothing to do
- }
- } else {
- // Use type conversion of EdmPrimitive types
- try {
- final String literal = getLiteral(value);
- newValue = tryCast(literal, (EdmPrimitiveType) type);
- } catch (EdmPrimitiveTypeException e) {
- // Nothing to do
- }
- }
-
- if (newValue != null) {
- return new TypedOperand(newValue, asType);
- }
- }
-
- throw new ODataApplicationException("Cast failed ", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
-
- public TypedOperand castToCommonType(VisitorOperand otherOperand) throws ODataApplicationException {
- final TypedOperand other = otherOperand.asTypedOperand();
- final EdmType oType = other.getType();
-
- // Make sure that the EDM type is equals, check also the java type.
- // So it is possible, that there is an conversation even if the same
- // EdmType is provided.
- // For example consider an Edm16 (internal Integer) and Edm16(internal
- // Short)
- // shortInstance.equals(intInstance) will always be false!
- if (type == oType && value != null && other.getValue() != null
- && value.getClass() == other.getValue().getClass()) {
- return this;
- } else if (isNullLiteral() || other.isNullLiteral()) {
- return this;
- }
-
- if (type.equals(EdmDouble.getInstance()) || oType.equals(EdmDouble.getInstance())) {
- return asTypedOperand(EdmDouble.getInstance());
- } else if (type.equals(EdmSingle.getInstance()) || oType.equals(EdmSingle.getInstance())) {
- return asTypedOperand(EdmSingle.getInstance());
- } else if (type.equals(EdmDecimal.getInstance()) || oType.equals(EdmDecimal.getInstance())) {
- return asTypedOperand(EdmDecimal.getInstance());
- } else if (type.equals(EdmInt64.getInstance()) || oType.equals(EdmInt64.getInstance())) {
- return asTypedOperand(EdmInt64.getInstance());
- } else if (type.equals(EdmInt32.getInstance()) || oType.equals(EdmInt32.getInstance())) {
- return asTypedOperand(EdmInt32.getInstance());
- } else if (type.equals(EdmInt16.getInstance()) || oType.equals(equals(EdmInt16.getInstance()))) {
- return asTypedOperand(EdmInt16.getInstance());
- } else {
- return asTypedOperand((EdmPrimitiveType) type);
- }
- }
-
- public EdmType getType() {
- return type;
- }
-
- public <T> T getTypedValue(Class<T> clazz) {
- return clazz.cast(value);
- }
-
- public boolean isNullLiteral() {
- return type.equals(EdmNull.getInstance());
- }
-
- public boolean isNull() {
- return isNullLiteral() || value == null;
- }
-
- public boolean isIntegerType() {
- return is(EdmByte.getInstance(),
- EdmSByte.getInstance(),
- EdmInt16.getInstance(),
- EdmInt32.getInstance(),
- EdmInt64.getInstance());
- }
-
- public boolean isDecimalType() {
- return is(EdmSingle.getInstance(),
- EdmDouble.getInstance(),
- EdmDecimal.getInstance());
- }
-
- public boolean is(EdmPrimitiveType... types) {
- if (isNullLiteral()) {
- return true;
- }
-
- for (EdmPrimitiveType type : types) {
- if (type.equals(this.type)) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public EdmProperty getEdmProperty() {
- return edmProperty;
- }
-
- private String getLiteral(Object value) throws EdmPrimitiveTypeException {
- final EdmProperty edmProperty = getEdmProperty();
- String uriLiteral = null;
-
- if (edmProperty != null) {
- uriLiteral = ((EdmPrimitiveType) type).valueToString(value, edmProperty.isNullable(), edmProperty.getMaxLength(),
- edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode());
- } else {
- uriLiteral = ((EdmPrimitiveType) type).valueToString(value, null, null, null, null, null);
- }
-
- return ((EdmPrimitiveType) type).toUriLiteral(uriLiteral);
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/UntypedOperand.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/UntypedOperand.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/UntypedOperand.java
deleted file mode 100644
index fa82c09..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/UntypedOperand.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.operand;
-
-import java.util.Locale;
-
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmProperty;
-import org.apache.olingo.commons.api.http.HttpStatusCode;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDecimal;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDuration;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt16;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt32;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt64;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSingle;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmTime;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmTimeOfDay;
-import org.apache.olingo.server.api.ODataApplicationException;
-import org.apache.olingo.server.tecsvc.processor.expression.primitive.EdmNull;
-
-public class UntypedOperand extends VisitorOperand {
-
- public UntypedOperand(final String literal) {
- super(literal);
- }
-
- @Override
- public TypedOperand asTypedOperand() throws ODataApplicationException {
- return determineType();
- }
-
- @Override
- public TypedOperand asTypedOperand(final EdmPrimitiveType... types) throws ODataApplicationException {
- final String literal = (String) value;
- Object newValue = null;
-
- // First try the null literal
- if ((newValue = tryCast(literal, EdmNull.getInstance())) != null) {
- return new TypedOperand(newValue, EdmNull.getInstance());
- }
-
- // Than try the given types
- for (EdmPrimitiveType type : types) {
- newValue = tryCast(literal, type);
-
- if (newValue != null) {
- return new TypedOperand(newValue, type);
- }
- }
-
- throw new ODataApplicationException("Cast failed", HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(),
- Locale.ROOT);
- }
-
- public TypedOperand determineType() throws ODataApplicationException {
- final String literal = (String) value;
- Object newValue = null;
-
- // Null literal
- if ((newValue = tryCast(literal, EdmNull.getInstance())) != null) {
- return new TypedOperand(newValue, EdmNull.getInstance());
- }
-
- // String
- if ((newValue = tryCast(literal, EdmString.getInstance())) != null) {
- return new TypedOperand(newValue, EdmString.getInstance());
- }
-
- // Date
- if ((newValue = tryCast(literal, EdmDateTimeOffset.getInstance())) != null) {
- return new TypedOperand(newValue, EdmDateTimeOffset.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmDate.getInstance())) != null) {
- return new TypedOperand(newValue, EdmDate.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmTimeOfDay.getInstance())) != null) {
- return new TypedOperand(newValue, EdmTimeOfDay.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmTime.getInstance())) != null) {
- return new TypedOperand(newValue, EdmTime.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmDuration.getInstance())) != null) {
- return new TypedOperand(newValue, EdmDuration.getInstance());
- }
-
- // Integer
- if ((newValue = tryCast(literal, EdmSByte.getInstance())) != null) {
- return new TypedOperand(newValue, EdmSByte.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmByte.getInstance())) != null) {
- return new TypedOperand(newValue, EdmByte.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmInt16.getInstance())) != null) {
- return new TypedOperand(newValue, EdmInt16.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmInt32.getInstance())) != null) {
- return new TypedOperand(newValue, EdmInt32.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmInt64.getInstance())) != null) {
- return new TypedOperand(newValue, EdmInt64.getInstance());
- }
-
- // Decimal
- if ((newValue = tryCast(literal, EdmDecimal.getInstance())) != null) {
- return new TypedOperand(newValue, EdmDecimal.getInstance());
- }
-
- // Float
- if ((newValue = tryCast(literal, EdmSingle.getInstance())) != null) {
- return new TypedOperand(newValue, EdmSingle.getInstance());
- }
-
- if ((newValue = tryCast(literal, EdmDouble.getInstance())) != null) {
- return new TypedOperand(newValue, EdmDouble.getInstance());
- }
-
- throw new ODataApplicationException("Could not determine type for literal " + literal,
- HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
- }
-
- @Override
- public EdmProperty getEdmProperty() {
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/VisitorOperand.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/VisitorOperand.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/VisitorOperand.java
deleted file mode 100644
index 02f6fb0..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operand/VisitorOperand.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.operand;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.HashMap;
-
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
-import org.apache.olingo.commons.api.edm.EdmProperty;
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDecimal;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt16;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt32;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt64;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSingle;
-import org.apache.olingo.server.api.ODataApplicationException;
-
-public abstract class VisitorOperand {
- final static private HashMap<EdmType, Class<?>> defaultTypeMapping = new HashMap<EdmType, Class<?>>();
- protected Object value;
-
- static {
- defaultTypeMapping.put(EdmByte.getInstance(), BigInteger.class);
- defaultTypeMapping.put(EdmSByte.getInstance(), BigInteger.class);
- defaultTypeMapping.put(EdmInt16.getInstance(), BigInteger.class);
- defaultTypeMapping.put(EdmInt32.getInstance(), BigInteger.class);
- defaultTypeMapping.put(EdmInt64.getInstance(), BigInteger.class);
-
- defaultTypeMapping.put(EdmSingle.getInstance(), BigDecimal.class);
- defaultTypeMapping.put(EdmDouble.getInstance(), BigDecimal.class);
- defaultTypeMapping.put(EdmDecimal.getInstance(), BigDecimal.class);
- }
-
- public VisitorOperand(Object value) {
- this.value = value;
- }
-
- public abstract TypedOperand asTypedOperand() throws ODataApplicationException;
-
- public abstract TypedOperand asTypedOperand(EdmPrimitiveType... types) throws ODataApplicationException;
-
- public abstract EdmProperty getEdmProperty();
-
- public Object getValue() {
- return value;
- }
-
- protected Object castTo(final String value, EdmPrimitiveType type) throws EdmPrimitiveTypeException {
- final EdmProperty edmProperty = getEdmProperty();
-
- if (edmProperty != null) {
- return type.valueOfString(value, edmProperty.isNullable(), edmProperty.getMaxLength(),
- edmProperty.getPrecision(), edmProperty.getScale(),
- edmProperty.isUnicode(), getDefaultType(type));
- } else {
- return type.valueOfString(value, null, null, null, null, null, getDefaultType(type));
- }
- }
-
- protected Class<?> getDefaultType(EdmPrimitiveType type) {
- return defaultTypeMapping.get(type) != null ? defaultTypeMapping.get(type) : type.getDefaultType();
- }
-
- protected Object tryCast(final String literal, final EdmPrimitiveType type) {
- try {
- return castTo(type.fromUriLiteral(literal), type);
- } catch (EdmPrimitiveTypeException e) {
- return null;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/BinaryOperator.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/BinaryOperator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/BinaryOperator.java
deleted file mode 100644
index f41e798..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/BinaryOperator.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * 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.operation;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.sql.Timestamp;
-import java.util.Calendar;
-import java.util.Locale;
-
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.commons.api.http.HttpStatusCode;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmBoolean;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDuration;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt16;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt32;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt64;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSByte;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmSingle;
-import org.apache.olingo.server.api.ODataApplicationException;
-import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind;
-import org.apache.olingo.server.tecsvc.processor.expression.operand.TypedOperand;
-import org.apache.olingo.server.tecsvc.processor.expression.operand.VisitorOperand;
-import org.apache.olingo.server.tecsvc.processor.expression.primitive.EdmNull;
-
-public class BinaryOperator {
- private static final int FACTOR_SECOND_INT = 1000;
- private static final BigDecimal FACTOR_SECOND = new BigDecimal(1000);
- private static final BigInteger EDM_SBYTE_MIN = BigInteger.valueOf(Byte.MIN_VALUE);
- private static final BigInteger EDN_SBYTE_MAX = BigInteger.valueOf(Byte.MAX_VALUE);
- private static final BigInteger EDM_BYTE_MIN = BigInteger.ZERO;
- private static final BigInteger EDM_BYTE_MAX = BigInteger.valueOf(((Byte.MAX_VALUE * 2) + 1));
- private static final BigInteger EDM_INT16_MIN = BigInteger.valueOf(Short.MIN_VALUE);
- private static final BigInteger EDM_INT16_MAX = BigInteger.valueOf(Short.MAX_VALUE);
- private static final BigInteger EDM_INT32_MIN = BigInteger.valueOf(Integer.MIN_VALUE);
- private static final BigInteger EDM_INT32_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
- private static final BigInteger EDM_INT64_MIN = BigInteger.valueOf(Long.MIN_VALUE);
- private static final BigInteger EDM_INT64_MAX = BigInteger.valueOf(Long.MAX_VALUE);
- private static final BigDecimal EDM_SINGLE_MIN = BigDecimal.valueOf(Float.MIN_VALUE);
- private static final BigDecimal EDM_SINGLE_MAX = BigDecimal.valueOf(Float.MAX_VALUE);
-
- private static final int EQUALS = 0;
- private static final int LESS_THAN = -1;
- private static final int GREATER_THAN = 1;
-
- private TypedOperand right;
- private TypedOperand left;
-
- public BinaryOperator(final VisitorOperand leftOperand, final VisitorOperand rightOperand)
- throws ODataApplicationException {
- left = leftOperand.asTypedOperand();
- right = rightOperand.asTypedOperand();
-
- left = left.castToCommonType(right);
- right = right.castToCommonType(left);
- }
-
- public VisitorOperand andOperator() throws ODataApplicationException {
- Boolean result = null;
- if (left.is(EdmBoolean.getInstance()) && right.is(EdmBoolean.getInstance())) {
- if (Boolean.TRUE.equals(left.getValue()) && Boolean.TRUE.equals(right.getValue())) {
- result = true;
- } else if (Boolean.FALSE.equals(left.getValue()) || Boolean.FALSE.equals(right.getValue())) {
- result = false;
- }
-
- return new TypedOperand(result, EdmBoolean.getInstance());
- } else {
- throw new ODataApplicationException("Add operator needs two binary operands",
- HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- public VisitorOperand orOperator() throws ODataApplicationException {
- Boolean result = null;
- if (left.is(EdmBoolean.getInstance()) && right.is(EdmBoolean.getInstance())) {
- if (Boolean.TRUE.equals(left.getValue()) || Boolean.TRUE.equals(right.getValue())) {
- result = true;
- } else if (Boolean.FALSE.equals(left.getValue()) && Boolean.FALSE.equals(right.getValue())) {
- result = false;
- }
-
- return new TypedOperand(result, EdmBoolean.getInstance());
- } else {
- throw new ODataApplicationException("Or operator needs two binary operands",
- HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- public VisitorOperand equalsOperator() {
- final boolean result = isBinaryComparisonNecessary() && binaryComparison(EQUALS);
- return new TypedOperand(result, EdmBoolean.getInstance());
- }
-
- public VisitorOperand notEqualsOperator() {
- final VisitorOperand equalsOperator = equalsOperator();
- return new TypedOperand(!(Boolean) equalsOperator.getValue(), EdmBoolean.getInstance());
- }
-
- private boolean isBinaryComparisonNecessary() {
- // binaryComparison() need to be called, if both operand are either null or not null
- return !(left.isNull() ^ right.isNull());
- }
-
- public VisitorOperand greaterEqualsOperator() {
- final boolean result = isBinaryComparisonNecessary() && binaryComparison(GREATER_THAN, EQUALS);
- return new TypedOperand(result, EdmBoolean.getInstance());
- }
-
- public VisitorOperand greaterThanOperator() {
- final boolean result = isBinaryComparisonNecessary() && binaryComparison(GREATER_THAN);
- return new TypedOperand(result, EdmBoolean.getInstance());
- }
-
- public VisitorOperand lessEqualsOperator() {
- final boolean result = isBinaryComparisonNecessary() && binaryComparison(LESS_THAN, EQUALS);
- return new TypedOperand(result, EdmBoolean.getInstance());
- }
-
- public VisitorOperand lessThanOperator() {
- final boolean result = isBinaryComparisonNecessary() && binaryComparison(LESS_THAN);
- return new TypedOperand(result, EdmBoolean.getInstance());
- }
-
- private boolean binaryComparison(int... expect) {
- int result;
-
- if (left.isNull() && right.isNull()) {
- result = 0; // null is equals to null
- } else {
- // left and right are not null!
- if (left.isIntegerType()) {
- result = left.getTypedValue(BigInteger.class).compareTo(right.getTypedValue(BigInteger.class));
- } else if (left.isDecimalType()) {
- result = left.getTypedValue(BigDecimal.class).compareTo(right.getTypedValue(BigDecimal.class));
- } else {
- result = left.getValue().equals(right.getValue()) ? 0 : 1;
- }
- }
- for (int expectedValue : expect) {
- if (expectedValue == result) {
- return true;
- }
- }
-
- return false;
- }
-
- public VisitorOperand arithmeticOperator(BinaryOperatorKind operator) throws ODataApplicationException {
- if (left.isNull() || right.isNull()) {
- return new TypedOperand(new Object(), EdmNull.getInstance());
- } else {
- if (left.isIntegerType()) {
- final BigInteger result = integerArithmeticOperation(operator);
- return new TypedOperand(result, determineResultType(result, left));
- } else if (left.isDecimalType()) {
- final BigDecimal result = decimalArithmeticOperation(operator);
- return new TypedOperand(result, determineResultType(result, left));
- } else if (left.is(EdmDate.getInstance(), EdmDuration.getInstance(), EdmDateTimeOffset.getInstance())) {
- return dateArithmeticOperation(operator);
- } else {
- throw new ODataApplicationException("Invalid type", HttpStatusCode.BAD_REQUEST.getStatusCode(),
- Locale.ROOT);
- }
- }
- }
-
- private EdmType determineResultType(final Number arithmeticResult, TypedOperand leftOperand) {
- // Left and right operand have the same typed, so it is enough to check the type of the left operand
- if (leftOperand.isDecimalType()) {
- final BigDecimal value = (BigDecimal) arithmeticResult;
- if (value.compareTo(EDM_SINGLE_MIN) >= 0 && value.compareTo(EDM_SINGLE_MAX) <= 0) {
- return EdmSingle.getInstance();
- } else {
- return EdmDouble.getInstance();
- }
- } else {
- final BigInteger value = (BigInteger) arithmeticResult;
-
- if (value.compareTo(EDN_SBYTE_MAX) <= 0 && value.compareTo(EDM_SBYTE_MIN) >= 0) {
- return EdmSByte.getInstance();
- }
- if (value.compareTo(EDM_BYTE_MAX) <= 0 && value.compareTo(EDM_BYTE_MIN) >= 0) {
- return EdmByte.getInstance();
- }
- if (value.compareTo(EDM_INT16_MAX) <= 0 && value.compareTo(EDM_INT16_MIN) >= 0) {
- return EdmInt16.getInstance();
- }
- if (value.compareTo(EDM_INT32_MAX) <= 0 && value.compareTo(EDM_INT32_MIN) >= 0) {
- return EdmInt32.getInstance();
- }
- if (value.compareTo(EDM_INT64_MAX) <= 0 && value.compareTo(EDM_INT64_MIN) >= 0) {
- return EdmInt64.getInstance();
- }
- // Choose double instead single because precision is higher (52 bits instead of 23)
- return EdmDouble.getInstance();
- }
- }
-
- private VisitorOperand dateArithmeticOperation(BinaryOperatorKind operator) throws ODataApplicationException {
- VisitorOperand result = null;
-
- if (left.is(EdmDate.getInstance())) {
- if (right.is(EdmDate.getInstance()) && operator == BinaryOperatorKind.SUB) {
- long millis = left.getTypedValue(Calendar.class).getTimeInMillis()
- - left.getTypedValue(Calendar.class).getTimeInMillis();
-
- result = new TypedOperand(new BigDecimal(millis).divide(FACTOR_SECOND), EdmDuration.getInstance());
- } else if (right.is(EdmDuration.getInstance()) && operator == BinaryOperatorKind.ADD) {
- long millis = left.getTypedValue(Calendar.class).getTimeInMillis()
- + (right.getTypedValue(BigDecimal.class).longValue() * FACTOR_SECOND_INT);
-
- result = new TypedOperand(new Timestamp(millis), EdmDateTimeOffset.getInstance());
- } else if (right.is(EdmDuration.getInstance()) && operator == BinaryOperatorKind.SUB) {
- long millis = left.getTypedValue(Calendar.class).getTimeInMillis()
- - (right.getTypedValue(BigDecimal.class).longValue() * FACTOR_SECOND_INT);
-
- result = new TypedOperand(new Timestamp(millis), EdmDateTimeOffset.getInstance());
- }
- } else if (left.is(EdmDuration.getInstance())) {
- if (right.is(EdmDuration.getInstance()) && operator == BinaryOperatorKind.ADD) {
- long seconds = left.getTypedValue(BigDecimal.class).longValue()
- + right.getTypedValue(BigDecimal.class).longValue();
-
- result = new TypedOperand(new BigDecimal(seconds), EdmDuration.getInstance());
- } else if (right.is(EdmDuration.getInstance()) && operator == BinaryOperatorKind.SUB) {
- long seconds = left.getTypedValue(BigDecimal.class).longValue()
- - right.getTypedValue(BigDecimal.class).longValue();
-
- result = new TypedOperand(new BigDecimal(seconds), EdmDuration.getInstance());
- }
- } else if (left.is(EdmDateTimeOffset.getInstance())) {
- if (right.is(EdmDuration.getInstance()) && operator == BinaryOperatorKind.ADD) {
- long millis = left.getTypedValue(Timestamp.class).getTime()
- + (right.getTypedValue(BigDecimal.class).longValue() * FACTOR_SECOND_INT);
-
- result = new TypedOperand(new Timestamp(millis), EdmDateTimeOffset.getInstance());
- } else if (right.is(EdmDuration.getInstance()) && operator == BinaryOperatorKind.SUB) {
- long millis = left.getTypedValue(Timestamp.class).getTime()
- - (right.getTypedValue(BigDecimal.class).longValue() * FACTOR_SECOND_INT);
-
- result = new TypedOperand(new Timestamp(millis), EdmDateTimeOffset.getInstance());
- } else if (right.is(EdmDateTimeOffset.getInstance()) && operator == BinaryOperatorKind.SUB) {
- long millis = left.getTypedValue(Timestamp.class).getTime()
- - right.getTypedValue(Timestamp.class).getTime();
-
- result = new TypedOperand(new BigDecimal(millis).divide(FACTOR_SECOND), EdmDuration.getInstance());
- }
- }
-
- if (result == null) {
- throw new ODataApplicationException("Invalid operation / operand", HttpStatusCode.BAD_REQUEST.getStatusCode(),
- Locale.ROOT);
- } else {
- return result;
- }
- }
-
- private BigDecimal decimalArithmeticOperation(BinaryOperatorKind operator) throws ODataApplicationException {
- final BigDecimal left = this.left.getTypedValue(BigDecimal.class);
- final BigDecimal right = this.right.getTypedValue(BigDecimal.class);
-
- switch (operator) {
- case ADD:
- return left.add(right);
- case DIV:
- return left.divide(left);
- case MUL:
- return left.multiply(right);
- case SUB:
- return left.subtract(right);
- default:
- throw new ODataApplicationException("Operator not valid", HttpStatusCode.BAD_REQUEST.getStatusCode(),
- Locale.ROOT);
- }
- }
-
- private BigInteger integerArithmeticOperation(BinaryOperatorKind operator) throws ODataApplicationException {
- final BigInteger left = this.left.getTypedValue(BigInteger.class);
- final BigInteger right = this.right.getTypedValue(BigInteger.class);
-
- switch (operator) {
- case ADD:
- return left.add(right);
- case DIV:
- return left.divide(right);
- case MUL:
- return left.multiply(right);
- case SUB:
- return left.subtract(right);
- case MOD:
- return left.mod(right);
- default:
- throw new ODataApplicationException("Operator not valid", HttpStatusCode.BAD_REQUEST.getStatusCode(),
- Locale.ROOT);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2ebdea80/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/MethodCallOperator.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/MethodCallOperator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/MethodCallOperator.java
deleted file mode 100644
index ece4df4..0000000
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/expression/operation/MethodCallOperator.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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.operation;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
-import org.apache.olingo.commons.api.edm.EdmType;
-import org.apache.olingo.commons.api.http.HttpStatusCode;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmBoolean;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmDecimal;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmInt32;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmTimeOfDay;
-import org.apache.olingo.server.api.ODataApplicationException;
-import org.apache.olingo.server.tecsvc.processor.expression.operand.TypedOperand;
-import org.apache.olingo.server.tecsvc.processor.expression.operand.VisitorOperand;
-
-public class MethodCallOperator {
-
- final private List<VisitorOperand> parameters;
-
- public MethodCallOperator(List<VisitorOperand> parameters) {
- this.parameters = parameters;
- }
-
- public VisitorOperand endsWith() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).endsWith(params.get(1));
- }
- }, EdmBoolean.getInstance());
- }
-
- public VisitorOperand indexOf() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).indexOf(params.get(1));
- }
- }, EdmInt32.getInstance());
- }
-
- public VisitorOperand startsWith() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).startsWith(params.get(1));
- }
- }, EdmBoolean.getInstance());
- }
-
- public VisitorOperand toLower() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).toLowerCase();
- }
- }, EdmString.getInstance());
- }
-
- public VisitorOperand toUpper() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).toUpperCase();
- }
- }, EdmString.getInstance());
- }
-
- public VisitorOperand trim() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).trim();
- }
- }, EdmString.getInstance());
- }
-
- public VisitorOperand substring() throws ODataApplicationException {
- final TypedOperand valueOperand = parameters.get(0).asTypedOperand();
- final TypedOperand startOperand = parameters.get(1).asTypedOperand();
-
- if (valueOperand.isNull() || startOperand.isNull()) {
- return new TypedOperand(null, EdmString.getInstance());
- } else if (valueOperand.is(EdmString.getInstance()) && startOperand.isIntegerType()) {
- final String value = valueOperand.getTypedValue(String.class);
- final BigInteger start = startOperand.getTypedValue(BigInteger.class);
- int end = value.length();
-
- if (parameters.size() == 3) {
- final TypedOperand lengthOperand = parameters.get(2).asTypedOperand();
-
- if (lengthOperand.isNull()) {
- return new TypedOperand(null, EdmString.getInstance());
- } else if (lengthOperand.isIntegerType()) {
- end = Math.min(start.add(lengthOperand.getTypedValue(BigInteger.class)).intValue(), value.length());
- } else {
- throw new ODataApplicationException("Third substring parameter should be Edm.Int32",
- HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- return new TypedOperand(value.substring(Math.min(start.intValue(), value.length()), end),
- EdmString.getInstance());
- } else {
- throw new ODataApplicationException("Substring has invalid parameters. First parameter should be Edm.String,"
- + " second parameter should be Edm.Int32", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- public VisitorOperand contains() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).contains(params.get(1));
- }
- }, EdmBoolean.getInstance());
- }
-
- public VisitorOperand concat() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0) + params.get(1);
- }
- }, EdmString.getInstance());
- }
-
- public VisitorOperand length() throws ODataApplicationException {
- return stringFunction(new StringFunction() {
- @Override
- public Object perform(List<String> params) {
- return params.get(0).length();
- }
- }, EdmInt32.getInstance());
- }
-
- public VisitorOperand year() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- return calendar.get(Calendar.YEAR);
- }
- }, EdmInt32.getInstance(), EdmDateTimeOffset.getInstance(), EdmDate.getInstance());
- }
-
- public VisitorOperand month() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- // Month is 0-based!
- return calendar.get(Calendar.MONTH) + 1;
- }
- }, EdmInt32.getInstance(), EdmDateTimeOffset.getInstance(), EdmDate.getInstance());
- }
-
- public VisitorOperand day() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- return calendar.get(Calendar.DAY_OF_MONTH);
- }
- }, EdmInt32.getInstance(), EdmDateTimeOffset.getInstance(), EdmDate.getInstance());
- }
-
- public VisitorOperand hour() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- return calendar.get(Calendar.HOUR_OF_DAY);
- }
- }, EdmInt32.getInstance(), EdmDateTimeOffset.getInstance(), EdmTimeOfDay.getInstance());
- }
-
- public VisitorOperand minute() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- return calendar.get(Calendar.MINUTE);
- }
- }, EdmInt32.getInstance(), EdmDateTimeOffset.getInstance(), EdmTimeOfDay.getInstance());
- }
-
- public VisitorOperand second() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- return calendar.get(Calendar.SECOND);
- }
- }, EdmInt32.getInstance(), EdmDateTimeOffset.getInstance(), EdmTimeOfDay.getInstance());
- }
-
- public VisitorOperand fractionalseconds() throws ODataApplicationException {
- return dateFunction(new DateFunction() {
- @Override
- public Object perform(Calendar calendar, TypedOperand operand) {
- if (operand.getValue() instanceof Timestamp) {
- return new BigDecimal(operand.getTypedValue(Timestamp.class).getNanos()).divide(BigDecimal
- .valueOf(1000 * 1000 * 1000));
- } else {
- return new BigDecimal(calendar.get(Calendar.MILLISECOND)).divide(BigDecimal.valueOf(1000));
- }
- }
- }, EdmDecimal.getInstance(), EdmDateTimeOffset.getInstance(), EdmTimeOfDay.getInstance());
- }
-
- public VisitorOperand round() throws ODataApplicationException {
- final TypedOperand operand = parameters.get(0).asTypedOperand();
- if (operand.isNull()) {
- return operand;
- } else if (operand.isDecimalType()) {
- return new TypedOperand(operand.getTypedValue(BigDecimal.class).round(new MathContext(1, RoundingMode.HALF_UP)),
- operand.getType());
- } else {
- throw new ODataApplicationException("Invalid type", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- public VisitorOperand floor() throws ODataApplicationException {
- final TypedOperand operand = parameters.get(0).asTypedOperand();
- if (operand.isNull()) {
- return operand;
- } else if (operand.isDecimalType()) {
- return new TypedOperand(operand.getTypedValue(BigDecimal.class).round(new MathContext(1, RoundingMode.FLOOR)),
- operand.getType());
- } else {
- throw new ODataApplicationException("Invalid type", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- public VisitorOperand ceiling() throws ODataApplicationException {
- final TypedOperand operand = parameters.get(0).asTypedOperand();
- if (operand.isNull()) {
- return operand;
- } else if (operand.isDecimalType()) {
- return new TypedOperand(operand.getTypedValue(BigDecimal.class).round(new MathContext(1, RoundingMode.CEILING)),
- operand.getType());
- } else {
- throw new ODataApplicationException("Invalid type", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- private interface StringFunction {
- Object perform(List<String> params);
- }
-
- private interface DateFunction {
- Object perform(Calendar calendar, TypedOperand operand);
- }
-
- private VisitorOperand dateFunction(DateFunction f, EdmType returnType, EdmPrimitiveType... expectedTypes)
- throws ODataApplicationException {
- final TypedOperand operand = parameters.get(0).asTypedOperand();
-
- if (operand.is(expectedTypes)) {
- if (!operand.isNull()) {
- Calendar calendar = null;
- if (operand.is(EdmDate.getInstance())) {
- calendar = operand.getTypedValue(Calendar.class);
- } else if (operand.is(EdmDateTimeOffset.getInstance())) {
- final Timestamp timestamp = operand.getTypedValue(Timestamp.class);
- calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
- calendar.setTimeInMillis(timestamp.getTime());
- } else if (operand.is(EdmTimeOfDay.getInstance())) {
- calendar = operand.getTypedValue(Calendar.class);
- } else {
- throw new ODataApplicationException("Invalid type", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
-
- return new TypedOperand(f.perform(calendar, operand), returnType);
- } else {
- return new TypedOperand(null, returnType);
- }
- } else {
- throw new ODataApplicationException("Invalid type", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
- private VisitorOperand stringFunction(StringFunction f, EdmType returnValue) throws ODataApplicationException {
- List<String> stringParameters = getParametersAsString();
- if (stringParameters.contains(null)) {
- return new TypedOperand(null, returnValue);
- } else {
- return new TypedOperand(f.perform(stringParameters), returnValue);
- }
- }
-
- private List<String> getParametersAsString() throws ODataApplicationException {
- List<String> result = new ArrayList<String>();
-
- for (VisitorOperand param : parameters) {
- TypedOperand operand = param.asTypedOperand();
- if (operand.isNull()) {
- result.add(null);
- } else if (operand.is(EdmString.getInstance())) {
- result.add(operand.getTypedValue(String.class));
- } else {
- throw new ODataApplicationException("Invalid parameter. Expected Edm.String", HttpStatusCode.BAD_REQUEST
- .getStatusCode(), Locale.ROOT);
- }
- }
-
- return result;
- }
-}