[OLINGO-564] Merge branch 'master' into OLINGO-564

This commit is contained in:
Michael Bolz 2015-04-28 12:56:08 +02:00
commit 3c0990910a
21 changed files with 771 additions and 121 deletions

View File

@ -0,0 +1,296 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.fit.tecsvc.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.net.URI;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
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.response.ODataInvokeResponse;
import org.apache.olingo.client.core.ODataClientFactory;
import org.apache.olingo.commons.api.domain.ODataCollectionValue;
import org.apache.olingo.commons.api.domain.ODataComplexValue;
import org.apache.olingo.commons.api.domain.ODataEntity;
import org.apache.olingo.commons.api.domain.ODataEntitySet;
import org.apache.olingo.commons.api.domain.ODataProperty;
import org.apache.olingo.commons.api.domain.ODataValue;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.fit.AbstractBaseTestITCase;
import org.apache.olingo.fit.tecsvc.TecSvcConst;
import org.junit.Test;
public class ActionImportITCase extends AbstractBaseTestITCase {
@Test
public void primitveAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTString").build();
ODataInvokeResponse<ODataProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class).execute();
assertEquals(200, response.getStatusCode());
assertEquals("UARTString string value", response.getBody().getPrimitiveValue().toValue());
}
@Test
public void primitveActionInvalidParameters() throws Exception {
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters.put("Invalid", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(1));
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTString").build();
try {
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class, parameters)
.execute();
fail("Expected an ODataClientErrorException");
} catch (ODataClientErrorException e) {
assertEquals(400, e.getStatusLine().getStatusCode());
}
}
@Test
public void primitveCollectionAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollStringTwoParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
parameters.put("ParameterDuration", getClient().getObjectFactory().newPrimitiveValueBuilder().setType(
EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal(1)).build());
ODataInvokeResponse<ODataProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataCollectionValue<ODataValue> valueArray = response.getBody().getCollectionValue();
assertEquals(3, valueArray.size());
Iterator<ODataValue> iterator = valueArray.iterator();
assertEquals("PT1S", iterator.next().asPrimitive().toValue());
assertEquals("PT2S", iterator.next().asPrimitive().toValue());
assertEquals("PT3S", iterator.next().asPrimitive().toValue());
}
@Test
public void complexAction() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCTTwoPrimParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
ODataInvokeResponse<ODataProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataComplexValue complexValue = response.getBody().getComplexValue();
ODataProperty propInt16 = complexValue.get("PropertyInt16");
assertNotNull(propInt16);
assertEquals(3, propInt16.getPrimitiveValue().toValue());
ODataProperty propString = complexValue.get("PropertyString");
assertNotNull(propString);
assertEquals("UARTCTTwoPrimParam string value", propString.getPrimitiveValue().toValue());
}
@Test
public void complexCollectionActionNoContent() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 0));
ODataInvokeResponse<ODataProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataCollectionValue<ODataValue> 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, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 1));
ODataInvokeResponse<ODataProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataCollectionValue<ODataValue> complexValueCollection = response.getBody().getCollectionValue();
assertEquals(1, complexValueCollection.size());
Iterator<ODataValue> iterator = complexValueCollection.iterator();
ODataComplexValue next = iterator.next().asComplex();
assertEquals(16, next.get("PropertyInt16").getPrimitiveValue().toValue());
assertEquals("Test123", next.get("PropertyString").getPrimitiveValue().toValue());
}
@Test
public void complexCollectionActionAllContent() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollCTTwoPrimParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
ODataInvokeResponse<ODataProperty> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataProperty.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataCollectionValue<ODataValue> complexValueCollection = response.getBody().getCollectionValue();
assertEquals(3, complexValueCollection.size());
Iterator<ODataValue> iterator = complexValueCollection.iterator();
ODataComplexValue next = iterator.next().asComplex();
assertEquals(16, next.get("PropertyInt16").getPrimitiveValue().toValue());
assertEquals("Test123", next.get("PropertyString").getPrimitiveValue().toValue());
next = iterator.next().asComplex();
assertEquals(17, next.get("PropertyInt16").getPrimitiveValue().toValue());
assertEquals("Test456", next.get("PropertyString").getPrimitiveValue().toValue());
next = iterator.next().asComplex();
assertEquals(18, next.get("PropertyInt16").getPrimitiveValue().toValue());
assertEquals("Test678", next.get("PropertyString").getPrimitiveValue().toValue());
}
@Test
public void entityActionETTwoKeyTwoPrim() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTETTwoKeyTwoPrimParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) -365));
ODataInvokeResponse<ODataEntity> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataEntity.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataEntity entity = response.getBody();
ODataProperty propInt16 = entity.getProperty("PropertyInt16");
assertNotNull(propInt16);
assertEquals(-365, propInt16.getPrimitiveValue().toValue());
ODataProperty propString = entity.getProperty("PropertyString");
assertNotNull(propString);
assertEquals("Test String2", propString.getPrimitiveValue().toValue());
}
@Test
public void entityCollectionActionETKeyNav() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 3));
ODataInvokeResponse<ODataEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataEntitySet entitySet = response.getBody();
assertEquals(3, entitySet.getEntities().size());
Integer key = 1;
for (ODataEntity entity : entitySet.getEntities()) {
assertEquals(key, entity.getProperty("PropertyInt16").getPrimitiveValue().toValue());
key++;
}
}
@Test
public void entityCollectionActionETKeyNavEmptyCollection() throws Exception {
URI actionURI =
getClient().newURIBuilder(TecSvcConst.BASE_URI).appendActionCallSegment("AIRTCollETKeyNavParam").build();
Map<String, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) 0));
ODataInvokeResponse<ODataEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataEntitySet 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, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters
.put("ParameterInt16", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short) -10));
ODataInvokeResponse<ODataEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataEntitySet entitySet = response.getBody();
assertEquals(0, entitySet.getEntities().size());
}
@Test
public void entityCollectionActionETAllPrim() throws Exception {
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, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters
.put("ParameterTimeOfDay", getClient().getObjectFactory().newPrimitiveValueBuilder().setType(
EdmPrimitiveTypeKind.TimeOfDay).setValue(time).build());
ODataInvokeResponse<ODataEntitySet> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataEntitySet.class, parameters)
.execute();
assertEquals(200, response.getStatusCode());
ODataEntitySet entitySet = response.getBody();
assertEquals(3, entitySet.getEntities().size());
Integer key = 1;
for (ODataEntity entity : entitySet.getEntities()) {
assertEquals(key, entity.getProperty("PropertyInt16").getPrimitiveValue().toValue());
key++;
}
}
@Test
public void entityActionETAllPrim() throws Exception {
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, ODataValue> parameters = new HashMap<String, ODataValue>();
parameters
.put("ParameterDate", getClient().getObjectFactory().newPrimitiveValueBuilder().setType(
EdmPrimitiveTypeKind.Date).setValue(dateTime).build());
ODataInvokeResponse<ODataEntity> response =
getClient().getInvokeRequestFactory().getActionInvokeRequest(actionURI, ODataEntity.class, parameters)
.execute();
// Check 201
assertEquals(201, response.getStatusCode());
}
@Override
protected ODataClient getClient() {
ODataClient odata = ODataClientFactory.getClient();
odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON_NO_METADATA);
return odata;
}
}

View File

@ -37,6 +37,8 @@ public enum SegmentType {
COUNT("$count"),
BOUND_OPERATION,
UNBOUND_OPERATION,
BOUND_ACTION,
UNBOUND_ACTION,
METADATA("$metadata"),
BATCH("$batch"),
LINKS("$links"),

View File

@ -355,4 +355,12 @@ public interface URIBuilder {
* @see org.apache.olingo.client.api.uri.QueryOption#SELECT
*/
URIBuilder expandWithSelect(String expandItem, String... selectItems);
/**
* Appends action segment to the URI.
*
* @param action Action name
* @return current URIBuilder instance
*/
URIBuilder appendActionCallSegment(String action);
}

View File

@ -179,6 +179,13 @@ public class URIBuilderImpl implements URIBuilder {
return this;
}
@Override
public URIBuilder appendActionCallSegment(final String action) {
segments.add(new Segment(
segments.size() == 1 ? SegmentType.UNBOUND_ACTION : SegmentType.BOUND_ACTION, action));
return this;
}
@Override
public URIBuilder appendOperationCallSegment(final String operation) {
segments.add(new Segment(
@ -266,7 +273,9 @@ public class URIBuilderImpl implements URIBuilder {
case BOUND_OPERATION:
segmentsBuilder.append(getBoundOperationSeparator());
break;
case BOUND_ACTION:
segmentsBuilder.append(getBoundOperationSeparator());
break;
default:
if (segmentsBuilder.length() > 0 && segmentsBuilder.charAt(segmentsBuilder.length() - 1) != '/') {
segmentsBuilder.append('/');

View File

@ -100,10 +100,10 @@ public class URIBuilderTest extends AbstractTest {
final URIBuilder uriBuilder = getClient().newURIBuilder(SERVICE_ROOT).
appendEntitySetSegment("Categories").appendKeySegment(1).
appendNavigationSegment("Products").appendNavigationSegment("Model").
appendOperationCallSegment("AllOrders");
appendActionCallSegment("AllOrders");
assertEquals(new org.apache.http.client.utils.URIBuilder(
SERVICE_ROOT + "/Categories(1)/Products/Model.AllOrders()").build(), uriBuilder.build());
SERVICE_ROOT + "/Categories(1)/Products/Model.AllOrders").build(), uriBuilder.build());
}
@Test

View File

@ -158,6 +158,7 @@ public class Entity extends Linked {
for (Property property : properties) {
if (name.equals(property.getName())) {
result = property;
break;
}
}

View File

@ -235,21 +235,27 @@ public interface ServiceHandler extends Processor {
* During a batch operation, this method starts the transaction (if any) before any operation is handled
* by the service. No nested transactions.
* @return must return a unique transaction id that references a atomic operation.
* @throws ODataTranslatedException
* @throws ODataApplicationException
*/
String startTransaction();
String startTransaction() throws ODataTranslatedException, ODataApplicationException;;
/**
* When a batch operation is complete and all the intermediate service requests are successful, then
* commit is called with transaction id returned in the startTransaction method.
* @param txnId
* @throws ODataTranslatedException
* @throws ODataApplicationException
*/
void commit(String txnId);
void commit(String txnId) throws ODataTranslatedException, ODataApplicationException;;
/**
* When a batch operation is in-complete due to an error in the middle of changeset, then rollback is
* called with transaction id, that returned from startTransaction method.
* @param txnId
* @throws ODataTranslatedException
* @throws ODataApplicationException
*/
void rollback(String txnId);
void rollback(String txnId) throws ODataTranslatedException, ODataApplicationException;;
/**
* This is not complete, more URL parsing changes required. Cross join between two entities.

View File

@ -77,12 +77,25 @@ public class BatchRequest extends ServiceRequest {
for (BatchRequestPart part : parts) {
if (part.isChangeSet()) {
String txnId = handler.startTransaction();
partResponse = processChangeSet(part, handler);
if (partResponse.getResponses().get(0).getStatusCode() > 400) {
handler.rollback(txnId);
String txnId = null;
try {
txnId = handler.startTransaction();
partResponse = processChangeSet(part, handler);
if (partResponse.getResponses().get(0).getStatusCode() > 400) {
handler.rollback(txnId);
}
handler.commit(txnId);
} catch(ODataTranslatedException e) {
if (txnId != null) {
handler.rollback(txnId);
}
throw e;
} catch (ODataApplicationException e) {
if (txnId != null) {
handler.rollback(txnId);
}
throw e;
}
handler.commit(txnId);
} else {
// single request, a static request
ODataRequest partRequest = part.getRequests().get(0);

View File

@ -273,6 +273,11 @@ public class DataRequest extends ServiceRequest {
return false;
}
// in update, delete entity cases, predicate must be there
if ((isPATCH() || isPUT() || isDELETE())
&& (getKeyPredicates() == null || getKeyPredicates().isEmpty())) {
return false;
}
return true;
}

View File

@ -630,6 +630,48 @@ public class TripPinDataModel {
return copy;
}
public boolean updateEntity(EdmEntitySet edmEntitySet, String eTag, String key, Object keyValue,
boolean merge, Entity changes, String baseURL) throws ODataApplicationException {
boolean updated = false;
if (merge) {
EntityCollection set = getEntitySet(edmEntitySet.getName());
Iterator<Entity> it = set.getEntities().iterator();
while (it.hasNext()) {
Entity entity = it.next();
if (entity.getProperty(key).getValue().equals(keyValue) && eTag.equals("*")
|| eTag.equals(entity.getETag())) {
for (Property p :changes.getProperties()) {
for (Property p1: entity.getProperties()) {
if (p.getName().equals(p1.getName())) {
p1.setValue(p1.getValueType(), p.getValue());
updated = true;
break;
}
}
}
break;
}
}
} else {
// this is delete, then insert
EntityCollection set = getEntitySet(edmEntitySet.getName());
Iterator<Entity> it = set.getEntities().iterator();
while (it.hasNext()) {
Entity entity = it.next();
if (entity.getProperty(key).getValue().equals(keyValue) && eTag.equals("*")
|| eTag.equals(entity.getETag())) {
Property p = entity.getProperty(key);
changes.addProperty(p);
createEntity(edmEntitySet, changes, baseURL);
updated = true;
}
}
}
return updated;
}
public boolean deleteEntity(String entitySetName, String eTag, String key, Object keyValue) {
EntityCollection set = getEntitySet(entitySetName);
Iterator<Entity> it = set.getEntities().iterator();

View File

@ -273,9 +273,25 @@ public class TripPinHandler implements ServiceHandler {
}
@Override
public void updateEntity(DataRequest request, Entity entity, boolean merge, String entityETag,
public void updateEntity(DataRequest request, Entity entity, boolean merge, String eTag,
EntityResponse response) throws ODataTranslatedException, ODataApplicationException {
response.writeServerError(true);
EdmEntitySet edmEntitySet = request.getEntitySet();
Entity currentEntity = this.dataModel.getEntity(edmEntitySet.getName(), request.getKeyPredicates());
if (currentEntity == null) {
response.writeNotFound(true);
return;
}
String key = edmEntitySet.getEntityType().getKeyPredicateNames().get(0);
String baseURL = request.getODataRequest().getRawBaseUri();
boolean updated = this.dataModel.updateEntity(edmEntitySet, eTag, key, currentEntity
.getProperty(key).getValue(), merge, entity, baseURL);
if (updated) {
response.writeUpdatedEntity();
} else {
response.writeNotModified();
}
}
@Override

View File

@ -34,6 +34,7 @@ import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
@ -418,6 +419,32 @@ public class TripPinServiceTest {
EntityUtils.consumeQuietly(response.getEntity());
}
@Test
public void testUpdateEntity() throws Exception {
String payload = "{" +
" \"Emails\":[" +
" \"Krista@example.com\"," +
" \"Krista@gmail.com\"" +
" ]" +
"}";
HttpPatch updateRequest = new HttpPatch(baseURL+"/People('kristakemp')");
updateRequest.setEntity(new StringEntity(payload, ContentType.APPLICATION_JSON));
httpSend(updateRequest, 204);
HttpResponse response = httpGET(baseURL + "/People('kristakemp')", 200);
JsonNode node = getJSONNode(response);
assertEquals("$metadata#People/$entity", node.get("@odata.context").asText());
assertEquals("Krista@example.com", node.get("Emails").get(0).asText());
assertEquals("Krista@gmail.com", node.get("Emails").get(1).asText());
}
@Test
public void testDeleteEntity() throws Exception{
// fail because no key predicates supplied
HttpDelete deleteRequest = new HttpDelete(baseURL+"/People");
HttpResponse response = httpSend(deleteRequest, 405);
EntityUtils.consumeQuietly(response.getEntity());
}
@Test
public void testCreateEntityWithLinkToRelatedEntities() throws Exception {

View File

@ -195,6 +195,22 @@ public class ODataJsonDeserializer implements ODataDeserializer {
Map<String, Parameter> parameters = new LinkedHashMap<String, Parameter>();
if (tree != null) {
consumeParameters(edmAction, tree, parameters);
final List<String> toRemove = new ArrayList<String>();
Iterator<Entry<String, JsonNode>> fieldsIterator = tree.fields();
while (fieldsIterator.hasNext()) {
Map.Entry<String, JsonNode> field = fieldsIterator.next();
if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
// Control Information is ignored for requests as per specification chapter "4.5 Control Information"
toRemove.add(field.getKey());
} else if (field.getKey().contains(ODATA_ANNOTATION_MARKER)) {
throw new DeserializerException("Custom annotation with field name: " + field.getKey() + " not supported",
DeserializerException.MessageKeys.NOT_IMPLEMENTED);
}
}
// remove here to avoid iterator issues.
tree.remove(toRemove);
assertJsonNodeIsEmpty(tree);
}
return DeserializerResultImpl.with().actionParameters(parameters).build();

View File

@ -24,6 +24,7 @@ import java.util.Calendar;
import java.util.List;
import java.util.Map;
import org.apache.olingo.commons.api.data.ComplexValue;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.data.Parameter;
@ -49,11 +50,17 @@ public class ActionData {
protected static Property primitiveCollectionAction(String name, Map<String, Parameter> parameters)
throws DataProviderException {
if ("UARTCollStringTwoParam".equals(name)) {
List<Object> collectionValues = new ArrayList<Object>();
int loopCount = (Integer) parameters.get("ParameterInt16").asPrimitive();
Parameter paramInt16 = parameters.get("ParameterInt16");
Parameter paramDuration = parameters.get("ParameterDuration");
if (paramInt16 == null || paramDuration == null) {
throw new DataProviderException("Missing parameters for action: UARTCollStringTwoParam",
HttpStatusCode.BAD_REQUEST);
}
short loopCount = (Short) paramInt16.asPrimitive();
BigDecimal duration = (BigDecimal) paramDuration.asPrimitive();
EdmPrimitiveType primDuration = OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration);
BigDecimal duration = (BigDecimal) parameters.get("ParameterDuration").asPrimitive();
BigDecimal addValue = new BigDecimal(1);
List<Object> collectionValues = new ArrayList<Object>();
for (int i = 0; i < loopCount; i++) {
try {
String value = primDuration.valueToString(duration, false, null, null, null, null);
@ -63,78 +70,92 @@ public class ActionData {
}
duration = duration.add(addValue);
}
return DataCreator.createPrimitiveCollection(null, collectionValues);
return new Property(null, name, ValueType.COLLECTION_PRIMITIVE, collectionValues);
}
throw new DataProviderException("Action " + name + " is not yet implemented.");
}
protected static Property complexAction(String name, Map<String, Parameter> parameters) throws DataProviderException {
if ("UARTCTTwoPrimParam".equals(name)) {
Integer number = (Integer) parameters.get("ParameterInt16").asPrimitive();
if (number == null) {
number = new Integer(32767);
Parameter paramInt16 = parameters.get("ParameterInt16");
Short number;
if (paramInt16 == null) {
number = new Short((short) 32767);
} else {
number = (Short) paramInt16.asPrimitive();
}
Property complexProp = createCTTwoPrimComplexProperty(number, "UARTCTTwoPrimParam string value");
return complexProp;
return createCTTwoPrimComplexProperty(number, "UARTCTTwoPrimParam string value");
}
throw new DataProviderException("Action " + name + " is not yet implemented.");
}
private static Property createCTTwoPrimComplexProperty(Integer number, String text) {
List<Property> props = new ArrayList<Property>();
private static Property createCTTwoPrimComplexProperty(Short number, String text) {
ComplexValue compValue = new ComplexValue();
Property propInt = new Property();
propInt.setName("PropertyInt16");
propInt.setValue(ValueType.PRIMITIVE, number);
props.add(propInt);
compValue.getValue().add(propInt);
Property propString = new Property();
propString.setName("PropertyString");
propString.setValue(ValueType.PRIMITIVE, text);
props.add(propString);
compValue.getValue().add(propString);
Property complexProp = new Property();
complexProp.setValue(ValueType.COMPLEX, props);
complexProp.setValue(ValueType.COMPLEX, compValue);
return complexProp;
}
protected static Property complexCollectionAction(String name, Map<String, Parameter> parameters)
throws DataProviderException {
if ("UARTCollCTTwoPrimParam".equals(name)) {
ArrayList<Property> complexCollection = new ArrayList<Property>();
complexCollection.add(createCTTwoPrimComplexProperty(16, "Test123"));
complexCollection.add(createCTTwoPrimComplexProperty(17, "Test456"));
complexCollection.add(createCTTwoPrimComplexProperty(18, "Test678"));
List<ComplexValue> complexCollection = new ArrayList<ComplexValue>();
complexCollection.add(createCTTwoPrimComplexProperty((short) 16, "Test123").asComplex());
complexCollection.add(createCTTwoPrimComplexProperty((short) 17, "Test456").asComplex());
complexCollection.add(createCTTwoPrimComplexProperty((short) 18, "Test678").asComplex());
Integer number = (Integer) parameters.get("ParameterInt16").asPrimitive();
if (number != null && number >= 0 && number < complexCollection.size()) {
complexCollection.subList(number, complexCollection.size() - 1).clear();
Parameter paramInt16 = parameters.get("ParameterInt16");
if (paramInt16 != null) {
Short number = (Short) paramInt16.asPrimitive();
if (number < 0) {
complexCollection.clear();
} else if (number >= 0 && number < complexCollection.size()) {
complexCollection = complexCollection.subList(0, number);
}
Property complexCollProperty = new Property();
complexCollProperty.setValue(ValueType.COLLECTION_COMPLEX, complexCollection);
return complexCollProperty;
}
Property complexCollProperty = new Property();
complexCollProperty.setValue(ValueType.COLLECTION_COMPLEX, complexCollection);
return complexCollProperty;
}
throw new DataProviderException("Action " + name + " is not yet implemented.");
}
protected static Entity entityAction(String name, Map<String, Parameter> parameters) throws DataProviderException {
protected static EntityActionResult entityAction(String name, Map<String, Parameter> parameters)
throws DataProviderException {
if ("UARTETTwoKeyTwoPrimParam".equals(name)) {
Integer number = (Integer) parameters.get("ParameterInt16").asPrimitive();
if (number == null) {
number = 0;
Parameter parameter = parameters.get("ParameterInt16");
Short number;
if (parameter != null) {
number = (Short) parameter.asPrimitive();
} else {
number = (short) 0;
}
EntityCollection entityCollection = new DataCreator().getData().get("ESTwoKeyTwoPrim");
for (Entity entity : entityCollection.getEntities()) {
if (number.equals(entity.getProperty("PropertyInt16").asPrimitive())) {
return entity;
Object asPrimitive = entity.getProperty("PropertyInt16").asPrimitive();
if (number.equals(asPrimitive)) {
return new EntityActionResult().setEntity(entity);
}
}
// Entity Not found
throw new DataProviderException("Entity not found with key: " + number, HttpStatusCode.NOT_FOUND);
} else if ("UARTETAllPrimParam".equals(name)) {
Calendar date = (Calendar) parameters.get("ParameterDate").asPrimitive();
Parameter paramDate = parameters.get("ParameterDate");
EntityCollection entityCollection = new DataCreator().getData().get("ESAllPrim");
if (date != null) {
if (paramDate != null) {
Calendar date = (Calendar) paramDate.asPrimitive();
boolean freeKey;
Short key = 0;
do {
@ -147,10 +168,10 @@ public class ActionData {
}
key++;
} while (!freeKey);
// TODO: Set create response code
return createAllPrimEntity(key, "UARTETAllPrimParam string value", date);
return new EntityActionResult().setEntity(createAllPrimEntity(key, "UARTETAllPrimParam string value", date))
.setCreated(true);
} else {
return entityCollection.getEntities().get(0);
return new EntityActionResult().setEntity(entityCollection.getEntities().get(0));
}
}
throw new DataProviderException("Action " + name + " is not yet implemented.");
@ -178,26 +199,31 @@ public class ActionData {
protected static EntityCollection entityCollectionAction(String name, Map<String, Parameter> parameters)
throws DataProviderException {
if ("UARTCollETKeyNavParam".equals(name)) {
Short number = (Short) parameters.get("ParameterInt16").asPrimitive();
EntityCollection collection = new EntityCollection();
if (number != null && number > 0) {
for (int i = 1; i <= number; i++) {
collection.getEntities().add(createETKeyNavEntity(number));
}
Parameter paramInt16 = parameters.get("ParameterInt16");
Short number;
if (paramInt16 == null) {
number = (short) 0;
} else {
return collection;
number = (Short) paramInt16.asPrimitive();
}
} else if ("UARTCollETAllPrimParam".equals(name)) {
Calendar timeOfDay = (Calendar) parameters.get("ParameterTimeOfDay").asPrimitive();
EntityCollection collection = new EntityCollection();
if (timeOfDay != null) {
if (number > 0) {
for (short i = 1; i <= number; i++) {
collection.getEntities().add(createETKeyNavEntity(i));
}
}
return collection;
} else if ("UARTCollETAllPrimParam".equals(name)) {
Parameter paramTimeOfDay = parameters.get("ParameterTimeOfDay");
EntityCollection collection = new EntityCollection();
if (paramTimeOfDay != null) {
Calendar timeOfDay = (Calendar) paramTimeOfDay.asPrimitive();
int count = timeOfDay.get(Calendar.HOUR_OF_DAY);
for (short i = 1; i <= count; i++) {
collection.getEntities().add(createAllPrimEntity(i, "UARTCollETAllPrimParam int16 value: " + i, null));
}
} else {
return collection;
}
}
return collection;
}
throw new DataProviderException("Action " + name + " is not yet implemented.");
}

View File

@ -85,13 +85,13 @@ public class DataCreator {
private EntityCollection createESTwoKeyTwoPrim() {
EntityCollection entitySet = new EntityCollection();
entitySet.getEntities().add(createETTwoKeyTwoPrimEntity(32767, "Test String1"));
entitySet.getEntities().add(createETKeyNavEntity(-365, "Test String2"));
entitySet.getEntities().add(createETKeyNavEntity(-32766, "Test String3"));
entitySet.getEntities().add(createETTwoKeyTwoPrimEntity((short) 32767, "Test String1"));
entitySet.getEntities().add(createETTwoKeyTwoPrimEntity((short) -365, "Test String2"));
entitySet.getEntities().add(createETTwoKeyTwoPrimEntity((short) -32766, "Test String3"));
return entitySet;
}
private Entity createETTwoKeyTwoPrimEntity(int propertyInt16, String propertyString) {
private Entity createETTwoKeyTwoPrimEntity(short propertyInt16, String propertyString) {
return new Entity().addProperty(createPrimitive("PropertyInt16", propertyInt16))
.addProperty(createPrimitive("PropertyString", propertyString));
}
@ -266,7 +266,7 @@ public class DataCreator {
.addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789dddfff")))
.addProperty(createPrimitive("PropertyTimeOfDay", getTime(23, 49, 14))));
entitySet.getEntities().add(new Entity().addProperty(createPrimitive("PropertyInt16", 0))
entitySet.getEntities().add(new Entity().addProperty(createPrimitive("PropertyInt16", (short) 0))
.addProperty(createPrimitive("PropertyString", "")).addProperty(createPrimitive("PropertyBoolean", false))
.addProperty(createPrimitive("PropertyByte", 0)).addProperty(createPrimitive("PropertySByte", 0))
.addProperty(createPrimitive("PropertyInt32", 0)).addProperty(createPrimitive("PropertyInt64", 0))
@ -600,7 +600,7 @@ public class DataCreator {
return new Property(null, name, ValueType.COLLECTION_COMPLEX, complexCollection);
}
private static Calendar getDateTime(final int year, final int month, final int day,
protected static Calendar getDateTime(final int year, final int month, final int day,
final int hour, final int minute, final int second) {
Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
dateTime.clear();
@ -608,7 +608,7 @@ public class DataCreator {
return dateTime;
}
private static Calendar getTime(final int hour, final int minute, final int second) {
protected static Calendar getTime(final int hour, final int minute, final int second) {
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
time.clear();
time.set(Calendar.HOUR_OF_DAY, hour);

View File

@ -495,11 +495,31 @@ public class DataProvider {
return ActionData.primitiveAction(name, actionParameters);
}
public Property processActionComplex(String name, Map<String, Parameter> actionParameters)
throws DataProviderException {
return ActionData.complexAction(name, actionParameters);
}
public Property processActionComplexCollection(String name, Map<String, Parameter> actionParameters)
throws DataProviderException {
return ActionData.complexCollectionAction(name, actionParameters);
}
public Property processActionPrimitiveCollection(String name, Map<String, Parameter> actionParameters)
throws DataProviderException {
return ActionData.primitiveCollectionAction(name, actionParameters);
}
public EntityActionResult processActionEntity(String name, Map<String, Parameter> actionParameters)
throws DataProviderException {
return ActionData.entityAction(name, actionParameters);
}
public EntityCollection processActionEntityCollection(String name, Map<String, Parameter> actionParameters)
throws DataProviderException {
return ActionData.entityCollectionAction(name, actionParameters);
}
public void setEdm(final Edm edm) {
this.edm = edm;
}

View File

@ -0,0 +1,43 @@
/*
* 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.data;
import org.apache.olingo.commons.api.data.Entity;
public class EntityActionResult {
private Entity entity;
private boolean created = false;
public Entity getEntity() {
return entity;
}
public EntityActionResult setEntity(Entity entity) {
this.entity = entity;
return this;
}
public boolean isCreated() {
return created;
}
public EntityActionResult setCreated(boolean created) {
this.created = created;
return this;
}
}

View File

@ -6,9 +6,9 @@
* 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
@ -52,6 +52,7 @@ import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
@ -59,6 +60,7 @@ import org.apache.olingo.server.api.uri.UriResourceFunction;
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.data.EntityActionResult;
import org.apache.olingo.server.tecsvc.data.RequestValidator;
import org.apache.olingo.server.tecsvc.processor.queryoptions.ExpandSystemQueryOptionHandler;
import org.apache.olingo.server.tecsvc.processor.queryoptions.options.CountHandler;
@ -117,14 +119,14 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
// Transform the entity graph to a tree. The construction is controlled by the expand tree.
// Apply all expand system query options to the tree.So the expanded navigation properties can be modified
// Apply all expand system query options to the tree.So the expanded navigation properties can be modified
// for serialization,without affecting the data stored in the database.
final ExpandSystemQueryOptionHandler expandHandler = new ExpandSystemQueryOptionHandler();
final EntityCollection entitySetSerialization = expandHandler.transformEntitySetGraphToTree(entitySet,
edmEntitySet,
expand);
final EntityCollection entitySetSerialization = expandHandler.transformEntitySetGraphToTree(entitySet,
edmEntitySet,
expand);
expandHandler.applyExpandQueryOptions(entitySetSerialization, edmEntitySet, expand);
// Serialize
@ -147,8 +149,32 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
public void processActionEntityCollection(final ODataRequest request, final ODataResponse response,
final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
throw new ODataApplicationException("Process entity collection is not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
EdmAction action = checkBoundAndExtractAction(uriInfo);
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
EntityCollection collection =
dataProvider.processActionEntityCollection(action.getName(), deserializerResult.getActionParameters());
if (collection == null) {
// Collection Propertys must never be null
throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
} else if (collection.getEntities().contains(null) && !action.getReturnType().isNullable()) {
// Not nullable return type but array contains a null value
throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
}
EdmEntityType type = (EdmEntityType) action.getReturnType().getType();
ContextURL contextURL = ContextURL.with().type(type).asCollection().build();
EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions.with().contextURL(contextURL).build();
SerializerResult result =
odata.createSerializer(ODataFormat.fromContentType(responseFormat))
.entityCollection(serviceMetadata, type, collection, options);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
}
@Override
@ -230,7 +256,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) uriInfo.getUriResourceParts().get(0);
final EdmEntitySet edmEntitySet = resourceEntitySet.getEntitySet();
final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
final Entity entity;
ExpandOption expand = null;
if (edmEntityType.hasStream()) { // called from createMediaEntity(...), not directly
@ -238,14 +264,14 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()),
requestFormat.toContentTypeString());
} else {
final DeserializerResult deserializerResult = odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.entity(request.getBody(), edmEntityType);
new RequestValidator(dataProvider,
odata.createUriHelper(),
serviceMetadata.getEdm(),
request.getRawBaseUri()
).validate(edmEntitySet, deserializerResult.getEntity());
final DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.entity(request.getBody(), edmEntityType);
new RequestValidator(dataProvider,
odata.createUriHelper(),
serviceMetadata.getEdm(),
request.getRawBaseUri()).validate(edmEntitySet, deserializerResult.getEntity());
entity = dataProvider.create(edmEntitySet);
dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, deserializerResult.getEntity(), false, true);
expand = deserializerResult.getExpandTree();
@ -271,11 +297,11 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
throws ODataApplicationException, DeserializerException, SerializerException {
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
Entity entity;
try {
entity = readEntity(uriInfo);
} catch(ODataApplicationException e) {
if(e.getStatusCode() == HttpStatusCode.NOT_FOUND.getStatusCode()) {
} catch (ODataApplicationException e) {
if (e.getStatusCode() == HttpStatusCode.NOT_FOUND.getStatusCode()) {
// Perform upsert
createEntity(request, response, uriInfo, requestFormat, responseFormat);
return;
@ -286,15 +312,14 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
checkRequestFormat(requestFormat);
final ODataDeserializer deserializer = odata.createDeserializer(ODataFormat.fromContentType(requestFormat));
final Entity changedEntity = deserializer.entity(request.getBody(), edmEntitySet.getEntityType()).getEntity();
new RequestValidator(dataProvider,
true, // Update
request.getMethod() == HttpMethod.PATCH,
odata.createUriHelper(),
serviceMetadata.getEdm(),
request.getRawBaseUri()
).validate(edmEntitySet, changedEntity);
new RequestValidator(dataProvider,
true, // Update
request.getMethod() == HttpMethod.PATCH,
odata.createUriHelper(),
serviceMetadata.getEdm(),
request.getRawBaseUri()).validate(edmEntitySet, changedEntity);
dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, changedEntity,
request.getMethod() == HttpMethod.PATCH, false);
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
@ -325,8 +350,36 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
public void processActionEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
throw new ODataApplicationException("Any action returning an entity is not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
EdmAction action = checkBoundAndExtractAction(uriInfo);
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
EntityActionResult entityResult =
dataProvider.processActionEntity(action.getName(), deserializerResult.getActionParameters());
EdmEntityType type = (EdmEntityType) action.getReturnType().getType();
if (entityResult == null || entityResult.getEntity() == null) {
if (action.getReturnType().isNullable()) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
// Not nullable return type so we have to give back a 500
throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
}
} else {
ContextURL contextURL = ContextURL.with().type(type).build();
EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextURL).build();
SerializerResult result = odata.createSerializer(ODataFormat.fromContentType(responseFormat))
.entity(serviceMetadata, type, entityResult.getEntity(), options);
if(entityResult.isCreated()){
response.setStatusCode(HttpStatusCode.CREATED.getStatusCode());
}else{
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
}
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
}
}
@Override

View File

@ -68,7 +68,6 @@ import org.apache.olingo.server.api.uri.UriHelper;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceFunction;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceProperty;
@ -121,7 +120,7 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
Property property = dataProvider.processActionPrimitive(action.getName(), deserializerResult.getActionParameters());
EdmPrimitiveType type = (EdmPrimitiveType) action.getReturnType().getType();
if (property.isNull()) {
if (property == null || property.isNull()) {
if (action.getReturnType().isNullable()) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
@ -141,18 +140,6 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
}
}
private EdmAction checkBoundAndExtractAction(final UriInfo uriInfo) throws ODataApplicationException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
List<UriResource> uriResourceParts = resource.getUriResourceParts();
if (uriResourceParts.size() > 1) {
throw new ODataApplicationException("Bound acctions not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
UriResourceAction uriResourceAction = (UriResourceAction) uriResourceParts.get(0);
EdmAction action = uriResourceAction.getAction();
return action;
}
@Override
public void readPrimitiveCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
@ -177,8 +164,32 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
public void processActionPrimitiveCollection(final ODataRequest request, final ODataResponse response,
final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
throw new ODataApplicationException("Not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
EdmAction action = checkBoundAndExtractAction(uriInfo);
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
Property property =
dataProvider.processActionPrimitiveCollection(action.getName(), deserializerResult.getActionParameters());
if (property == null || property.isNull()) {
// Collection Propertys must never be null
throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
} else if (property.asCollection().contains(null) && !action.getReturnType().isNullable()) {
// Not nullable return type but array contains a null value
throw new ODataApplicationException("The action could no be executed", 500, 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(type, property, options);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
}
@Override
@ -199,8 +210,32 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
public void processActionComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo,
ContentType requestFormat, ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
throw new ODataApplicationException("Not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
EdmAction action = checkBoundAndExtractAction(uriInfo);
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
Property property = dataProvider.processActionComplex(action.getName(), deserializerResult.getActionParameters());
EdmComplexType type = (EdmComplexType) action.getReturnType().getType();
if (property == null || property.isNull()) {
if (action.getReturnType().isNullable()) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
// Not nullable return type so we have to give back a 500
throw new ODataApplicationException("The action could no be executed", 500, 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());
}
}
@Override
@ -232,9 +267,10 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
Property property = dataProvider.processActionPrimitive(action.getName(), deserializerResult.getActionParameters());
Property property =
dataProvider.processActionComplexCollection(action.getName(), deserializerResult.getActionParameters());
if (property.isNull()) {
if (property == null || property.isNull()) {
// Collection Propertys must never be null
throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
} else if (property.asCollection().contains(null) && !action.getReturnType().isNullable()) {

View File

@ -24,6 +24,7 @@ import java.util.Locale;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
@ -34,9 +35,11 @@ import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceFunction;
import org.apache.olingo.server.api.uri.UriResourceNavigation;
@ -212,4 +215,16 @@ public abstract class TechnicalProcessor implements Processor {
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
}
protected EdmAction checkBoundAndExtractAction(final UriInfo uriInfo) throws ODataApplicationException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
List<UriResource> uriResourceParts = resource.getUriResourceParts();
if (uriResourceParts.size() > 1) {
throw new ODataApplicationException("Bound acctions not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
UriResourceAction uriResourceAction = (UriResourceAction) uriResourceParts.get(0);
EdmAction action = uriResourceAction.getAction();
return action;
}
}

View File

@ -65,6 +65,22 @@ public class ODataJsonDeserializerActionParametersTest extends AbstractODataDese
assertTrue(parameters.isEmpty());
}
@Test
public void ignoreODataAnnotations() throws Exception {
final String input =
"{\"ParameterDuration@odata.type\":\"Edm.Duration\","
+ "\"ParameterDuration\":\"P42DT11H22M33S\",\"ParameterInt16\":42}";
final Map<String, Parameter> parameters = deserialize(input, "UARTTwoParam");
assertNotNull(parameters);
assertEquals(2, parameters.size());
Parameter parameter = parameters.get("ParameterInt16");
assertNotNull(parameter);
assertEquals((short) 42, parameter.getValue());
parameter = parameters.get("ParameterDuration");
assertNotNull(parameter);
assertEquals(BigDecimal.valueOf(3669753), parameter.getValue());
}
@Test(expected = DeserializerException.class)
public void bindingParameter() throws Exception {
deserialize("{\"ParameterETAllPrim\":{\"PropertyInt16\":42}}", "BAETAllPrimRT", "ETAllPrim");