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

Signed-off-by: Christian Amend <chrisam@apache.org>
This commit is contained in:
Christian Holzer 2015-02-19 17:11:45 +01:00 committed by Christian Amend
parent cfb72decd1
commit 0e6c9a1183
17 changed files with 2812 additions and 26 deletions

View File

@ -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 {
/**

View File

@ -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 =

View File

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

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,199 @@
/*
* 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);
}
}

View File

@ -0,0 +1,155 @@
/*
* 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;
}
}

View File

@ -0,0 +1,93 @@
/*
* 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;
}
}
}

View File

@ -0,0 +1,318 @@
/*
* 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);
}
}
}

View File

@ -0,0 +1,334 @@
/*
* 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;
}
}

View File

@ -0,0 +1,63 @@
/*
* 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.util.Locale;
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.EdmDuration;
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 UnaryOperator {
final private TypedOperand operand;
public UnaryOperator(VisitorOperand operand) throws ODataApplicationException {
this.operand = operand.asTypedOperand();
}
public VisitorOperand minusOperation() throws ODataApplicationException {
if (operand.isNull()) {
return operand;
} else if (operand.isIntegerType()) {
return new TypedOperand(operand.getTypedValue(BigInteger.class).negate(), operand.getType());
} else if (operand.isDecimalType() || operand.is(EdmDuration.getInstance())) {
return new TypedOperand(operand.getTypedValue(BigDecimal.class).negate(), operand.getType());
} else {
throw new ODataApplicationException("Unsupported type", HttpStatusCode.BAD_REQUEST.getStatusCode(),
Locale.ROOT);
}
}
public VisitorOperand notOperation() throws ODataApplicationException {
if (operand.isNull()) {
return operand;
} else if (operand.is(EdmBoolean.getInstance())) {
return new TypedOperand(!operand.getTypedValue(Boolean.class), operand.getType());
} else {
throw new ODataApplicationException("Unsupported type", HttpStatusCode.BAD_REQUEST.getStatusCode(),
Locale.ROOT);
}
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.primitive;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.core.edm.primitivetype.SingletonPrimitiveType;
public final class EdmNull extends SingletonPrimitiveType {
private static final EdmNull instance = new EdmNull();
public static EdmNull getInstance() {
return instance;
}
@Override
public Class<?> getDefaultType() {
return Object.class;
}
@Override
protected <T> T internalValueOfString(String value, Boolean isNullable, Integer maxLength, Integer precision,
Integer scale, Boolean isUnicode, Class<T> returnType) throws EdmPrimitiveTypeException {
if (!value.equals("null")) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
if (returnType.isAssignableFrom(Object.class)) {
return returnType.cast(new Object());
} else {
throw new ClassCastException("unsupported return type " + returnType.getSimpleName());
}
}
@Override
protected <T> String internalValueToString(T value, Boolean isNullable, Integer maxLength, Integer precision,
Integer scale, Boolean isUnicode) throws EdmPrimitiveTypeException {
return "null";
}
}