[OLINGO-698] technical service supports preferences, part 1

Signed-off-by: Christian Amend <christian.amend@sap.com>
This commit is contained in:
Klaus Straubinger 2015-06-16 16:47:39 +02:00 committed by Christian Amend
parent a298e1fb7c
commit e5fe04aeeb
9 changed files with 486 additions and 299 deletions

View File

@ -25,6 +25,7 @@ import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.net.URI;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@ -32,6 +33,8 @@ import java.util.TimeZone;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.header.HeaderName;
import org.apache.olingo.client.api.communication.request.invoke.ODataInvokeRequest;
import org.apache.olingo.client.api.communication.response.ODataInvokeResponse;
import org.apache.olingo.client.api.domain.ClientCollectionValue;
import org.apache.olingo.client.api.domain.ClientComplexValue;
@ -42,6 +45,7 @@ import org.apache.olingo.client.api.domain.ClientValue;
import org.apache.olingo.client.core.ODataClientFactory;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.fit.AbstractBaseTestITCase;
import org.apache.olingo.fit.tecsvc.TecSvcConst;
import org.junit.Test;
@ -50,50 +54,62 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void noReturnTypeAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRT").build();
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class).execute();
assertEquals(204, response.getStatusCode());
}
@Test
public void primitveAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTString").build();
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRT").build();
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class).execute();
assertEquals(200, response.getStatusCode());
assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
}
@Test
public void primitiveAction() throws Exception {
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTString").build();
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class).execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
assertEquals("UARTString string value", response.getBody().getPrimitiveValue().toValue());
}
@Test
public void primitveActionInvalidParameters() throws Exception {
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters.put("Invalid", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(1));
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTString").build();
public void primitiveActionMinimalResponse() throws Exception {
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTString").build();
ODataInvokeRequest<ClientProperty> request = getClient().getInvokeRequestFactory()
.getActionInvokeRequest(actionURI, ClientProperty.class);
request.setPrefer(getClient().newPreferences().returnMinimal());
final ODataInvokeResponse<ClientProperty> response = request.execute();
assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
assertEquals("return=\"minimal\"", response.getHeader(HeaderName.preferenceApplied).iterator().next());
}
@Test
public void primitiveActionInvalidParameters() throws Exception {
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTString").build();
Map<String, ClientValue> parameters = Collections.singletonMap("Invalid",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(1));
try {
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters)
.execute();
.execute();
fail("Expected an ODataClientErrorException");
} catch (ODataClientErrorException e) {
assertEquals(400, e.getStatusLine().getStatusCode());
assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), e.getStatusLine().getStatusCode());
}
}
@Test
public void primitveCollectionAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollStringTwoParam").build();
public void primitiveCollectionAction() throws Exception {
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollStringTwoParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
parameters.put("ParameterDuration", getClient().getObjectFactory().newPrimitiveValueBuilder().setType(
EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal(1)).build());
parameters.put("ParameterDuration", getClient().getObjectFactory().newPrimitiveValueBuilder()
.setType(EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal(1)).build());
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientCollectionValue<ClientValue> valueArray = response.getBody().getCollectionValue();
assertEquals(3, valueArray.size());
Iterator<ClientValue> iterator = valueArray.iterator();
@ -104,14 +120,14 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void complexAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCTTwoPrimParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCTTwoPrimParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientComplexValue complexValue = response.getBody().getComplexValue();
ClientProperty propInt16 = complexValue.get("PropertyInt16");
assertNotNull(propInt16);
@ -123,28 +139,28 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void complexCollectionActionNoContent() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 0));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 0));
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientCollectionValue<ClientValue> complexValueCollection = response.getBody().getCollectionValue();
assertEquals(0, complexValueCollection.size());
}
@Test
public void complexCollectionActionSubContent() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 1));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 1));
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientCollectionValue<ClientValue> complexValueCollection = response.getBody().getCollectionValue();
assertEquals(1, complexValueCollection.size());
Iterator<ClientValue> iterator = complexValueCollection.iterator();
@ -156,14 +172,14 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void complexCollectionActionAllContent() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
ODataInvokeResponse<ClientProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientCollectionValue<ClientValue> complexValueCollection = response.getBody().getCollectionValue();
assertEquals(3, complexValueCollection.size());
Iterator<ClientValue> iterator = complexValueCollection.iterator();
@ -183,15 +199,14 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void entityActionETTwoKeyTwoPrim() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTETTwoKeyTwoPrimParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) -365));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTETTwoKeyTwoPrimParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) -365));
ODataInvokeResponse<ClientEntity> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientEntity.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientEntity entity = response.getBody();
ClientProperty propInt16 = entity.getProperty("PropertyInt16");
assertNotNull(propInt16);
@ -203,15 +218,14 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void entityCollectionActionETKeyNav() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
ODataInvokeResponse<ClientEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientEntitySet entitySet = response.getBody();
assertEquals(3, entitySet.getEntities().size());
Integer key = 1;
@ -223,51 +237,49 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void entityCollectionActionETKeyNavEmptyCollection() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 0));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 0));
ODataInvokeResponse<ClientEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientEntitySet entitySet = response.getBody();
assertEquals(0, entitySet.getEntities().size());
}
@Test
public void entityCollectionActionETKeyNavNegativeParam() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) -10));
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ClientValue> parameters = Collections.singletonMap("ParameterInt16",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) -10));
ODataInvokeResponse<ClientEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientEntitySet entitySet = response.getBody();
assertEquals(0, entitySet.getEntities().size());
}
@Test
public void entityCollectionActionETAllPrim() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollESAllPrimParam").build();
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTCollESAllPrimParam").build();
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
time.clear();
time.set(Calendar.HOUR_OF_DAY, 3);
time.set(Calendar.MINUTE, 0);
time.set(Calendar.SECOND, 0);
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters
.put("ParameterTimeOfDay", getClient().getObjectFactory().newPrimitiveValueBuilder().setType(
EdmPrimitiveTypeKind.TimeOfDay).setValue(time).build());
Map<String, ClientValue> parameters = Collections.singletonMap(
"ParameterTimeOfDay",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder()
.setType(EdmPrimitiveTypeKind.TimeOfDay).setValue(time).build());
ODataInvokeResponse<ClientEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ClientEntitySet entitySet = response.getBody();
assertEquals(3, entitySet.getEntities().size());
Integer key = 1;
@ -279,20 +291,19 @@ public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void entityActionETAllPrim() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTESAllPrimParam").build();
final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI)
.appendActionCallSegment("AIRTESAllPrimParam").build();
Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
dateTime.clear();
dateTime.set(1012, 2, 0, 0, 0, 0);
Map<String, ClientValue> parameters = new HashMap<String, ClientValue>();
parameters
.put("ParameterDate", getClient().getObjectFactory().newPrimitiveValueBuilder().setType(
EdmPrimitiveTypeKind.Date).setValue(dateTime).build());
Map<String, ClientValue> parameters = Collections.singletonMap(
"ParameterDate",
(ClientValue) getClient().getObjectFactory().newPrimitiveValueBuilder()
.setType(EdmPrimitiveTypeKind.Date).setValue(dateTime).build());
ODataInvokeResponse<ClientEntity> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientEntity.class, parameters)
.execute();
// Check 201
assertEquals(201, response.getStatusCode());
.execute();
assertEquals(HttpStatusCode.CREATED.getStatusCode(), response.getStatusCode());
}
@Override

View File

@ -37,6 +37,7 @@ import java.util.List;
import org.apache.olingo.client.api.EdmEnabledODataClient;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.header.HeaderName;
import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
@ -400,6 +401,24 @@ public class BasicITCase extends AbstractBaseTestITCase {
assertNull(property2.getPrimitiveValue());
}
@Test
public void createEntityMinimalResponse() throws Exception {
final ODataClient client = getClient();
final ClientObjectFactory factory = client.getObjectFactory();
ClientEntity newEntity = factory.newEntity(new FullQualifiedName("olingo.odata.test1", "ETTwoPrim"));
newEntity.getProperties().add(factory.newPrimitiveProperty("PropertyString",
factory.newPrimitiveValueBuilder().buildString("new")));
ODataEntityCreateRequest<ClientEntity> request = client.getCUDRequestFactory().getEntityCreateRequest(
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESTwoPrim").build(),
newEntity);
request.setPrefer(getClient().newPreferences().returnMinimal());
final ODataEntityCreateResponse<ClientEntity> response = request.execute();
assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
assertEquals("return=\"minimal\"", response.getHeader(HeaderName.preferenceApplied).iterator().next());
assertEquals(SERVICE_URI + "/ESTwoPrim(1)", response.getHeader(HttpHeader.LOCATION).iterator().next());
}
@Test
public void readEntityWithExpandedNavigationProperty() {
final ODataClient client = ODataClientFactory.getEdmEnabledClient(SERVICE_URI);
@ -459,30 +478,20 @@ public class BasicITCase extends AbstractBaseTestITCase {
entity.getProperties().add(
of.newCollectionProperty("CollPropertyComp",
of.newCollectionValue("CTPrimComp")
.add(
of.newComplexValue("CTPrimComp")
.add(
of.newPrimitiveProperty("PropertyInt16", of.newPrimitiveValueBuilder()
.buildInt16(
(short) 42)))
.add(
of.newComplexProperty("PropertyComp", of.newComplexValue("CTAllPrim")
.add(
of.newPrimitiveProperty("PropertyString", of
.newPrimitiveValueBuilder()
.buildString("42"))))))
.add(
of.newComplexValue("CTPrimComp")
.add(
of.newPrimitiveProperty("PropertyInt16", of.newPrimitiveValueBuilder()
.buildInt16(
(short) 43)))
.add(
of.newComplexProperty("PropertyComp", of.newComplexValue("CTAllPrim")
.add(
of.newPrimitiveProperty("PropertyString", of
.newPrimitiveValueBuilder()
.buildString("43"))))))));
.add(of.newComplexValue("CTPrimComp")
.add(of.newPrimitiveProperty("PropertyInt16",
of.newPrimitiveValueBuilder().buildInt16((short) 42)))
.add(of.newComplexProperty("PropertyComp",
of.newComplexValue("CTAllPrim")
.add(of.newPrimitiveProperty("PropertyString",
of.newPrimitiveValueBuilder().buildString("42"))))))
.add(of.newComplexValue("CTPrimComp")
.add(of.newPrimitiveProperty("PropertyInt16",
of.newPrimitiveValueBuilder().buildInt16((short) 43)))
.add(of.newComplexProperty("PropertyComp",
of.newComplexValue("CTAllPrim")
.add(of.newPrimitiveProperty("PropertyString",
of.newPrimitiveValueBuilder().buildString("43"))))))));
final URI uri = getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESKeyNav")
@ -681,13 +690,15 @@ public class BasicITCase extends AbstractBaseTestITCase {
entity.getProperties().add(of.newPrimitiveProperty("PropertyString", of.newPrimitiveValueBuilder()
.buildString(null)));
final ODataEntityUpdateResponse<ClientEntity> updateResponse = client.getCUDRequestFactory()
.getEntityUpdateRequest(targetURI, UpdateType.PATCH, entity)
.execute();
ODataEntityUpdateRequest<ClientEntity> request = client.getCUDRequestFactory()
.getEntityUpdateRequest(targetURI, UpdateType.PATCH, entity);
request.setPrefer(getClient().newPreferences().returnRepresentation());
final ODataEntityUpdateResponse<ClientEntity> response = request.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), updateResponse.getStatusCode());
assertTrue(updateResponse.getBody().getProperty("PropertyString").hasNullValue());
assertEquals(34, updateResponse.getBody().getProperty("PropertyDecimal").getPrimitiveValue().toValue());
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
assertEquals("return=\"representation\"", response.getHeader(HeaderName.preferenceApplied).iterator().next());
assertTrue(response.getBody().getProperty("PropertyString").hasNullValue());
assertEquals(34, response.getBody().getProperty("PropertyDecimal").getPrimitiveValue().toValue());
}
@Test(expected = ODataClientErrorException.class)
@ -743,23 +754,23 @@ public class BasicITCase extends AbstractBaseTestITCase {
.expand("NavPropertyETKeyNavOne", "NavPropertyETKeyNavMany")
.build());
entityRequest.addCustomHeader(HttpHeader.COOKIE, cookie);
final ODataRetrieveResponse<ClientEntity> entitytResponse = entityRequest.execute();
final ODataRetrieveResponse<ClientEntity> entityResponse = entityRequest.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), entitytResponse.getStatusCode());
assertEquals(1, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavOne")
assertEquals(HttpStatusCode.OK.getStatusCode(), entityResponse.getStatusCode());
assertEquals(1, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavOne")
.asInlineEntity()
.getEntity()
.getProperty("PropertyInt16")
.getPrimitiveValue()
.toValue());
assertEquals(3, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(3, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
.size());
assertEquals(1, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(1, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
@ -768,7 +779,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
.getPrimitiveValue()
.toValue());
assertEquals(2, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(2, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
@ -777,7 +788,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
.getPrimitiveValue()
.toValue());
assertEquals(3, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(3, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
@ -786,7 +797,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
.getPrimitiveValue()
.toValue());
final Iterator<ClientValue> collectionIterator = entitytResponse.getBody()
final Iterator<ClientValue> collectionIterator = entityResponse.getBody()
.getProperty("CollPropertyString")
.getCollectionValue()
.iterator();
@ -794,7 +805,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
assertEquals("Single entry!", collectionIterator.next().asPrimitive().toValue());
assertFalse(collectionIterator.hasNext());
final ClientComplexValue complexValue = entitytResponse.getBody()
final ClientComplexValue complexValue = entityResponse.getBody()
.getProperty("PropertyCompAllPrim")
.getComplexValue();
@ -825,14 +836,14 @@ public class BasicITCase extends AbstractBaseTestITCase {
.add(of.newPrimitiveValueBuilder().buildString("Single entry!"))));
entity.getProperties().add(of.newComplexProperty("PropertyCompAllPrim",
of.newComplexValue("CTAllPrim")
.add(of.newPrimitiveProperty("PropertyString",
of.newPrimitiveValueBuilder().buildString("Changed")))));
.add(of.newPrimitiveProperty("PropertyString", of.newPrimitiveValueBuilder().buildString("Changed")))));
final ODataEntityUpdateResponse<ClientEntity> response = client.getCUDRequestFactory()
.getEntityUpdateRequest(targetURI, UpdateType.REPLACE, entity)
.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
ODataEntityUpdateRequest<ClientEntity> request = client.getCUDRequestFactory()
.getEntityUpdateRequest(targetURI, UpdateType.REPLACE, entity);
request.setPrefer(getClient().newPreferences().returnMinimal());
final ODataEntityUpdateResponse<ClientEntity> response = request.execute();
assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
assertEquals("return=\"minimal\"", response.getHeader(HeaderName.preferenceApplied).iterator().next());
final String cookie = response.getHeader(HttpHeader.SET_COOKIE).iterator().next();
final ODataEntityRequest<ClientEntity> entityRequest = client.getRetrieveRequestFactory()
@ -843,23 +854,23 @@ public class BasicITCase extends AbstractBaseTestITCase {
.expand("NavPropertyETKeyNavOne", "NavPropertyETKeyNavMany")
.build());
entityRequest.addCustomHeader(HttpHeader.COOKIE, cookie);
final ODataRetrieveResponse<ClientEntity> entitytResponse = entityRequest.execute();
final ODataRetrieveResponse<ClientEntity> entityResponse = entityRequest.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), entitytResponse.getStatusCode());
assertEquals(1, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavOne")
assertEquals(HttpStatusCode.OK.getStatusCode(), entityResponse.getStatusCode());
assertEquals(1, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavOne")
.asInlineEntity()
.getEntity()
.getProperty("PropertyInt16")
.getPrimitiveValue()
.toValue());
assertEquals(3, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(3, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
.size());
assertEquals(1, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(1, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
@ -868,7 +879,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
.getPrimitiveValue()
.toValue());
assertEquals(2, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(2, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
@ -877,7 +888,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
.getPrimitiveValue()
.toValue());
assertEquals(3, entitytResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
assertEquals(3, entityResponse.getBody().getNavigationLink("NavPropertyETKeyNavMany")
.asInlineEntitySet()
.getEntitySet()
.getEntities()
@ -886,7 +897,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
.getPrimitiveValue()
.toValue());
final Iterator<ClientValue> collectionIterator = entitytResponse.getBody()
final Iterator<ClientValue> collectionIterator = entityResponse.getBody()
.getProperty("CollPropertyString")
.getCollectionValue()
.iterator();
@ -894,7 +905,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
assertEquals("Single entry!", collectionIterator.next().asPrimitive().toValue());
assertFalse(collectionIterator.hasNext());
final ClientComplexValue propCompAllPrim = entitytResponse.getBody()
final ClientComplexValue propCompAllPrim = entityResponse.getBody()
.getProperty("PropertyCompAllPrim")
.getComplexValue();
@ -902,15 +913,15 @@ public class BasicITCase extends AbstractBaseTestITCase {
assertTrue(propCompAllPrim.get("PropertyInt16").hasNullValue());
assertTrue(propCompAllPrim.get("PropertyDate").hasNullValue());
final ClientComplexValue propCompTwoPrim = entitytResponse.getBody()
final ClientComplexValue propCompTwoPrim = entityResponse.getBody()
.getProperty("PropertyCompTwoPrim")
.getComplexValue();
assertEquals("Must not be null", propCompTwoPrim.get("PropertyString").getPrimitiveValue().toValue());
assertEquals(42, propCompTwoPrim.get("PropertyInt16").getPrimitiveValue().toValue());
assertNotNull(entitytResponse.getBody().getProperty("PropertyCompNav").getComplexValue());
assertTrue(entitytResponse.getBody()
assertNotNull(entityResponse.getBody().getProperty("PropertyCompNav").getComplexValue());
assertTrue(entityResponse.getBody()
.getProperty("PropertyCompNav")
.getComplexValue()
.get("PropertyInt16")

View File

@ -33,6 +33,7 @@ import java.util.Iterator;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.header.HeaderName;
import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataPropertyUpdateRequest;
import org.apache.olingo.client.api.communication.request.cud.ODataValueUpdateRequest;
@ -367,6 +368,21 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
assertEquals("Test String1", IOUtils.toString((InputStream) value.toValue(), "UTF-8"));
}
@Test
public void updatePropertyValueMinimalResponse() throws Exception {
ODataValueUpdateRequest request = getClient().getCUDRequestFactory().getValueUpdateRequest(
getClient().newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESTwoPrim").appendKeySegment(32766)
.appendPropertySegment("PropertyString")
.build(),
UpdateType.REPLACE,
getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Test String1"));
request.setPrefer(getClient().newPreferences().returnMinimal());
final ODataValueUpdateResponse response = request.execute();
assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
assertEquals("return=\"minimal\"", response.getHeader(HeaderName.preferenceApplied).iterator().next());
}
@Test
public void readPrimitiveCollectionCount() {
final ODataValueRequest request = getClient().getRetrieveRequestFactory()

View File

@ -25,6 +25,8 @@ 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.header.HeaderName;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntity;
import org.apache.olingo.client.api.domain.ClientEntitySet;
@ -211,7 +213,7 @@ public class SystemQueryOptionITCase extends AbstractBaseTestITCase {
// Check initial next link format
URI nextLink = response.getBody().getNext();
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24skiptoken=1", nextLink.toASCIIString());
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24skiptoken=1%2A10", nextLink.toASCIIString());
// Check subsequent next links
response = client.getRetrieveRequestFactory()
@ -219,7 +221,7 @@ public class SystemQueryOptionITCase extends AbstractBaseTestITCase {
.execute();
nextLink = response.getBody().getNext();
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24skiptoken=2", nextLink.toASCIIString());
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24skiptoken=2%2A10", nextLink.toASCIIString());
}
@Test
@ -236,7 +238,7 @@ public class SystemQueryOptionITCase extends AbstractBaseTestITCase {
// Check initial next link format
URI nextLink = response.getBody().getNext();
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24count=true&%24skiptoken=1",
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24count=true&%24skiptoken=1%2A10",
nextLink.toASCIIString());
int token = 1;
@ -250,7 +252,7 @@ public class SystemQueryOptionITCase extends AbstractBaseTestITCase {
nextLink = response.getBody().getNext();
if (nextLink != null) {
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24count=true&%24skiptoken=" + token,
assertEquals(SERVICE_URI + "/ESServerSidePaging?%24count=true&%24skiptoken=" + token + "%2A10",
nextLink.toASCIIString());
}
}
@ -258,6 +260,19 @@ public class SystemQueryOptionITCase extends AbstractBaseTestITCase {
assertEquals(50 + 1, token);
}
@Test
public void nextLinkFormatWithClientPageSize() {
final ODataClient client = getClient();
final URI uri = client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_SERVER_SIDE_PAGING).build();
ODataEntitySetRequest<ClientEntitySet> request = client.getRetrieveRequestFactory().getEntitySetRequest(uri);
request.setPrefer(getClient().newPreferences().maxPageSize(7));
final ODataRetrieveResponse<ClientEntitySet> response = request.execute();
assertEquals("odata.maxpagesize=\"7\"", response.getHeader(HeaderName.preferenceApplied).iterator().next());
assertEquals(SERVICE_URI + '/' + ES_SERVER_SIDE_PAGING + "?%24skiptoken=1%2A" + 7,
response.getBody().getNext().toASCIIString());
}
@Test
public void testNegativeSkip() {
ODataClient client = getClient();

View File

@ -162,12 +162,17 @@ public interface HttpHeader {
*/
public static final String ODATA_MAX_VERSION = "OData-MaxVersion";
// CHECKSTYLE:OFF
/**
* OData Prefer Header
* See
* {@link <a href="http://docs.oasis-open.org/odata/odata/v4.0/errata01/os/complete/part1-protocol/odata-v4.0-errata01-os-part1-protocol-complete.html#_Toc399426728"> OData Version 4.0 Part 1: Protocol Plus Errata 01</a>}
* OData Prefer Header.
* See <a href="http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part1-protocol.html#_Toc406398233">
* OData Version 4.0 Part 1: Protocol</a> and <a href="https://www.ietf.org/rfc/rfc7240.txt">RFC 7240</a>.
*/
public static final String PREFER = "Prefer";
// CHECKSTYLE:ON
/**
* OData Preference-Applied Header.
* See <a href="http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part1-protocol.html#_Toc406398247">
* OData Version 4.0 Part 1: Protocol</a> and <a href="https://www.ietf.org/rfc/rfc7240.txt">RFC 7240</a>.
*/
public static final String PREFERENCE_APPLIED = "Preference-Applied";
}

View File

@ -40,6 +40,8 @@ import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.deserializer.DeserializerResult;
import org.apache.olingo.server.api.prefer.Preferences.Return;
import org.apache.olingo.server.api.prefer.PreferencesApplied;
import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ActionComplexProcessor;
import org.apache.olingo.server.api.processor.ActionEntityCollectionProcessor;
@ -58,7 +60,7 @@ import org.apache.olingo.server.tecsvc.data.DataProvider;
import org.apache.olingo.server.tecsvc.data.EntityActionResult;
/**
* Technical Processor for entity-related functionality.
* Technical Processor for action-related functionality.
*/
public class TechnicalActionProcessor extends TechnicalProcessor
implements ActionEntityCollectionProcessor, ActionEntityProcessor,
@ -92,16 +94,26 @@ public class TechnicalActionProcessor extends TechnicalProcessor
throw new ODataApplicationException("The action could not be executed.",
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final EdmEntityType type = (EdmEntityType) action.getReturnType().getType();
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null : getContextUrl(edmEntitySet, type, false))
.build();
response.setContent(odata.createSerializer(format)
.entityCollection(serviceMetadata, type, collection, options).getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final EdmEntityType type = (EdmEntityType) action.getReturnType().getType();
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
final EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null : getContextUrl(edmEntitySet, type, false))
.build();
response.setContent(odata.createSerializer(format)
.entityCollection(serviceMetadata, type, collection, options).getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
}
@Override
@ -129,18 +141,32 @@ public class TechnicalActionProcessor extends TechnicalProcessor
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
} else {
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(odata.createSerializer(format).entity(
serviceMetadata,
type,
entityResult.getEntity(),
EntitySerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null : getContextUrl(edmEntitySet, type, true))
.build())
.getContent());
response.setStatusCode((entityResult.isCreated() ? HttpStatusCode.CREATED : HttpStatusCode.OK)
.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(odata.createSerializer(format).entity(
serviceMetadata,
type,
entityResult.getEntity(),
EntitySerializerOptions.with()
.contextURL(format == ODataFormat.JSON_NO_METADATA ? null : getContextUrl(edmEntitySet, type, true))
.build())
.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode((entityResult.isCreated() ? HttpStatusCode.CREATED : HttpStatusCode.OK)
.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
if (entityResult.isCreated()) {
response.setHeader(HttpHeader.LOCATION,
request.getRawBaseUri() + '/'
+ odata.createUriHelper().buildCanonicalURL(edmEntitySet, entityResult.getEntity()));
}
if (entityResult.getEntity().getETag() != null) {
response.setHeader(HttpHeader.ETAG, entityResult.getEntity().getETag());
}
@ -170,17 +196,25 @@ public class TechnicalActionProcessor extends TechnicalProcessor
throw new ODataApplicationException("The action could not be executed.",
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
EdmPrimitiveType type = (EdmPrimitiveType) action.getReturnType().getType();
ContextURL contextURL = ContextURL.with().type(type).asCollection().build();
PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextURL).build();
SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat))
.primitiveCollection(serviceMetadata, type, property, options);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final EdmPrimitiveType type = (EdmPrimitiveType) action.getReturnType().getType();
final ContextURL contextURL = ContextURL.with().type(type).asCollection().build();
final PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextURL).build();
final SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat))
.primitiveCollection(serviceMetadata, type, property, options);
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
}
@Override
@ -205,15 +239,22 @@ public class TechnicalActionProcessor extends TechnicalProcessor
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
} else {
ContextURL contextURL = ContextURL.with().type(type).build();
PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextURL).build();
SerializerResult result = odata.createSerializer(ODataFormat.fromContentType(responseFormat))
.primitive(serviceMetadata, type, property, options);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final ContextURL contextURL = ContextURL.with().type(type).build();
final PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextURL).build();
final SerializerResult result = odata.createSerializer(ODataFormat.fromContentType(responseFormat))
.primitive(serviceMetadata, type, property, options);
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
}
}
@ -240,17 +281,25 @@ public class TechnicalActionProcessor extends TechnicalProcessor
throw new ODataApplicationException("The action could not be executed.",
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
EdmComplexType type = (EdmComplexType) action.getReturnType().getType();
ContextURL contextURL = ContextURL.with().type(type).asCollection().build();
ComplexSerializerOptions options = ComplexSerializerOptions.with().contextURL(contextURL).build();
SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat)).complexCollection(serviceMetadata, type,
property, options);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final EdmComplexType type = (EdmComplexType) action.getReturnType().getType();
final ContextURL contextURL = ContextURL.with().type(type).asCollection().build();
final ComplexSerializerOptions options = ComplexSerializerOptions.with().contextURL(contextURL).build();
final SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat)).complexCollection(serviceMetadata, type,
property, options);
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
}
@Override
@ -275,16 +324,23 @@ public class TechnicalActionProcessor extends TechnicalProcessor
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
} else {
ContextURL contextURL = ContextURL.with().type(type).build();
ComplexSerializerOptions options = ComplexSerializerOptions.with().contextURL(contextURL).build();
SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat)).complex(serviceMetadata, type, property,
options);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final ContextURL contextURL = ContextURL.with().type(type).build();
final ComplexSerializerOptions options = ComplexSerializerOptions.with().contextURL(contextURL).build();
final SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat)).complex(serviceMetadata, type, property,
options);
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
}
}

View File

@ -40,6 +40,8 @@ import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.deserializer.DeserializerResult;
import org.apache.olingo.server.api.deserializer.ODataDeserializer;
import org.apache.olingo.server.api.prefer.PreferencesApplied;
import org.apache.olingo.server.api.prefer.Preferences.Return;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
@ -162,11 +164,20 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
expand = deserializerResult.getExpandTree();
}
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entity, edmEntitySet, edmEntityType, format, expand, null)
.getContent());
response.setStatusCode(HttpStatusCode.CREATED.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entity, edmEntitySet, edmEntityType, format, expand, null)
.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setStatusCode(HttpStatusCode.CREATED.getStatusCode());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
response.setHeader(HttpHeader.LOCATION,
request.getRawBaseUri() + '/' + odata.createUriHelper().buildCanonicalURL(edmEntitySet, entity));
if (entity.getETag() != null) {
@ -209,11 +220,20 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, changedEntity,
request.getMethod() == HttpMethod.PATCH, false);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entity, edmEntitySet, edmEntityType, format, null, null)
.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entity, edmEntitySet, edmEntityType, format, null, null)
.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
@ -234,11 +254,20 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()),
requestFormat.toContentTypeString());
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entity, edmEntitySet, edmEntityType, format, null, null)
.getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entity, edmEntitySet, edmEntityType, format, null, null)
.getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
} else {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
@ -414,10 +443,12 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), entitySet);
TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet);
ServerSidePagingHandler.applyServerSidePaging(uriInfo.getSkipTokenOption(),
final Integer pageSize = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getMaxPageSize();
final Integer serverPageSize = ServerSidePagingHandler.applyServerSidePaging(uriInfo.getSkipTokenOption(),
entitySet,
edmEntitySet,
request.getRawRequestUri());
request.getRawRequestUri(),
pageSize);
// Apply expand system query option
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
@ -443,6 +474,10 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
response.setContent(serializerResult.getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
if (pageSize != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().maxPageSize(serverPageSize).build().toString());
}
}
private SerializerResult serializeEntityCollection(final EntityCollection entityCollection,

View File

@ -48,6 +48,8 @@ import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.deserializer.FixedFormatDeserializer;
import org.apache.olingo.server.api.prefer.PreferencesApplied;
import org.apache.olingo.server.api.prefer.Preferences.Return;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountComplexCollectionProcessor;
@ -305,17 +307,26 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
dataProvider.updateETag(entity);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
if (representationType == RepresentationType.VALUE) {
response.setContent(
serializePrimitiveValue(property, edmProperty, (EdmPrimitiveType) edmProperty.getType(), null));
final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn();
if (returnPreference == null || returnPreference == Return.REPRESENTATION) {
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
if (representationType == RepresentationType.VALUE) {
response.setContent(
serializePrimitiveValue(property, edmProperty, (EdmPrimitiveType) edmProperty.getType(), null));
} else {
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
final SerializerResult result = serializeProperty(entity, edmEntitySet, path, property, edmProperty,
edmProperty.getType(), null, representationType, format, null, null);
response.setContent(result.getContent());
}
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
} else {
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
final SerializerResult result = serializeProperty(entity, edmEntitySet, path, property, edmProperty,
edmProperty.getType(), null, representationType, format, null, null);
response.setContent(result.getContent());
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
if (returnPreference != null) {
response.setHeader(HttpHeader.PREFERENCE_APPLIED,
PreferencesApplied.with().returnRepresentation(returnPreference).build().toString());
}
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}

View File

@ -34,68 +34,63 @@ public class ServerSidePagingHandler {
private static final int MAX_PAGE_SIZE = 10;
private static final String ES_SERVER_SIDE_PAGING = "ESServerSidePaging";
public static void applyServerSidePaging(final SkipTokenOption skipTokenOption, final EntityCollection entitySet,
final EdmEntitySet edmEntitySet, final String rawRequestUri) throws ODataApplicationException {
/**
* <p>Applies server-side paging to the given entity collection.</p>
* <p>The next link is constructed and set in the data. It must support client-specified
* page sizes. Therefore, the format <code>page*pageSize</code> (with a literal asterisk)
* has been chosen for the skiptoken.</p>
* @param skipTokenOption the current skiptoken option (from a previous response's next link)
* @param entityCollection the data
* @param edmEntitySet the EDM entity set to decide whether paging must be done
* @param rawRequestUri the request URI (used to construct the next link)
* @param preferredPageSize the client's preference for page size
* @return the chosen page size (or <code>null</code> if no paging has been done);
* could be used in the Preference-Applied HTTP header
* @throws ODataApplicationException
*/
public static Integer applyServerSidePaging(final SkipTokenOption skipTokenOption, EntityCollection entityCollection,
final EdmEntitySet edmEntitySet, final String rawRequestUri, final Integer preferredPageSize)
throws ODataApplicationException {
if (edmEntitySet != null && shouldApplyServerSidePaging(edmEntitySet)) {
final int maxPageSize = getMaxPageSize();
final int pageSize = getPageSize(getPageSize(skipTokenOption), preferredPageSize);
final int page = getPage(skipTokenOption);
final int itemsToSkip = maxPageSize * page;
final int itemsToSkip = pageSize * page;
if (itemsToSkip <= entitySet.getEntities().size()) {
SkipHandler.popAtMost(entitySet, itemsToSkip);
final int remainingItems = entitySet.getEntities().size();
TopHandler.reduceToSize(entitySet, maxPageSize);
if (itemsToSkip <= entityCollection.getEntities().size()) {
SkipHandler.popAtMost(entityCollection, itemsToSkip);
final int remainingItems = entityCollection.getEntities().size();
TopHandler.reduceToSize(entityCollection, pageSize);
// Determine if a new next Link has to be provided
if (remainingItems > maxPageSize) {
entitySet.setNext(createNextLink(rawRequestUri, page + 1));
// Determine if a new next Link has to be provided.
if (remainingItems > pageSize) {
entityCollection.setNext(createNextLink(rawRequestUri, page + 1, pageSize));
}
} else {
throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
}
return pageSize;
}
return null;
}
private static URI createNextLink(final String rawRequestUri, final Integer page)
private static URI createNextLink(final String rawRequestUri, final Integer page, final int pageSize)
throws ODataApplicationException {
// Remove a maybe existing skiptoken, making sure that the query part is not empty.
String nextlink = rawRequestUri.contains("?") ?
rawRequestUri.replaceAll("(\\$|%24)skiptoken=.+&?", "").replaceAll("(\\?|&)$", "") :
rawRequestUri;
// Add a question mark or an ampersand, depending on the current query part.
nextlink += nextlink.contains("?") ? '&' : '?';
// Append the new skiptoken.
try {
// Remove skip token
String nextlink = rawRequestUri;
// Remove a may existing skiptoken, make sure that the query part is not empty
if (rawRequestUri.contains("?")) {
nextlink = rawRequestUri.replaceAll("(\\$|%24)skiptoken=.+&?", "").replaceAll("(\\?|&)$", "");
}
// Add a question mark or an ampersand, depending of the current query part
if (!nextlink.contains("?")) {
nextlink = nextlink + "?";
} else {
nextlink = nextlink + "&";
}
// Append the new nextlink
return new URI(nextlink + Encoder.encode(SystemQueryOptionKind.SKIPTOKEN.toString()) + "="
+ Encoder.encode(page.toString()));
} catch (URISyntaxException e) {
return new URI(nextlink + Encoder.encode(SystemQueryOptionKind.SKIPTOKEN.toString()) + '='
+ Encoder.encode(page.toString() + '*' + pageSize));
} catch (final URISyntaxException e) {
throw new ODataApplicationException("Exception while constructing next link",
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
}
private static int getPage(final SkipTokenOption skipTokenOption) throws ODataApplicationException {
if (skipTokenOption != null) {
try {
return Integer.parseInt(skipTokenOption.getValue());
} catch (NumberFormatException e) {
throw new ODataApplicationException("Invalid skip token", HttpStatusCode.BAD_REQUEST.getStatusCode(),
Locale.ROOT);
}
} else {
return 0;
HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT, e);
}
}
@ -103,8 +98,40 @@ public class ServerSidePagingHandler {
return ES_SERVER_SIDE_PAGING.equals(edmEntitySet.getName());
}
private static int getMaxPageSize() {
// TODO Consider odata.maxpagesize preference?
return MAX_PAGE_SIZE;
private static int getPageSize(final int skipTokenPageSize, final Integer preferredPageSize) {
return skipTokenPageSize > 0 ? skipTokenPageSize :
preferredPageSize == null || preferredPageSize >= MAX_PAGE_SIZE ?
MAX_PAGE_SIZE :
preferredPageSize;
}
private static int getPageSize(final SkipTokenOption skipTokenOption) throws ODataApplicationException {
if (skipTokenOption != null && skipTokenOption.getValue().length() >= 3
&& skipTokenOption.getValue().contains("*")) {
final String value = skipTokenOption.getValue();
try {
return Integer.parseInt(value.substring(value.indexOf('*') + 1));
} catch (final NumberFormatException e) {
throw new ODataApplicationException("Invalid skip token", HttpStatusCode.BAD_REQUEST.getStatusCode(),
Locale.ROOT, e);
}
} else {
return 0;
}
}
private static int getPage(final SkipTokenOption skipTokenOption) throws ODataApplicationException {
if (skipTokenOption != null && skipTokenOption.getValue().length() >= 3
&& skipTokenOption.getValue().contains("*")) {
final String value = skipTokenOption.getValue();
try {
return Integer.parseInt(value.substring(0, value.indexOf('*')));
} catch (final NumberFormatException e) {
throw new ODataApplicationException("Invalid skip token", HttpStatusCode.BAD_REQUEST.getStatusCode(),
Locale.ROOT, e);
}
} else {
return 0;
}
}
}