Merge branch 'olingojava8' of https://git-wip-us.apache.org/repos/asf/olingo-odata4
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ApplyOption.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ApplyOption.java
index e5b10b5..90f89e4 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ApplyOption.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/queryoption/ApplyOption.java
@@ -20,6 +20,8 @@
import java.util.List;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+
/**
* Represents the system query option $apply, defined in the data aggregation extension.
*/
@@ -29,4 +31,9 @@
* @return a list of transformations
*/
List<ApplyItem> getApplyItems();
+
+ /**
+ * @return the structured type associated with this apply option
+ */
+ EdmStructuredType getEdmStructuredType();
}
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java
index 96be8a4..9b053f1 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java
@@ -46,6 +46,7 @@
import org.apache.olingo.server.api.uri.UriResourceRoot;
import org.apache.olingo.server.api.uri.UriResourceSingleton;
import org.apache.olingo.server.api.uri.UriResourceValue;
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.DeltaTokenOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@@ -219,6 +220,11 @@
break;
}
}
+
+ if (info.getApplyOption() != null) {
+ //per the docs, apply is first
+ visit(info.getApplyOption());
+ }
// http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793682
if (info.getSearchOption() != null) {
@@ -265,6 +271,10 @@
visit(info.getDeltaTokenOption());
}
}
+
+ @Override
+ public void visit(ApplyOption option) {
+ }
@Override
public void visit(ExpandOption option) {
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java
index 5fda0e4..9fa2802 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java
@@ -42,6 +42,7 @@
import org.apache.olingo.server.api.uri.UriResourceRoot;
import org.apache.olingo.server.api.uri.UriResourceSingleton;
import org.apache.olingo.server.api.uri.UriResourceValue;
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.DeltaTokenOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@@ -127,4 +128,6 @@
void visit(UriResourceComplexProperty info);
void visit(UriResourcePrimitiveProperty info);
+
+ void visit(ApplyOption option);
}
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
index 7f06e95..bb311d3 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceDispatcher.java
@@ -51,6 +51,7 @@
import org.apache.olingo.server.api.uri.UriResourceRef;
import org.apache.olingo.server.api.uri.UriResourceSingleton;
import org.apache.olingo.server.api.uri.UriResourceValue;
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
import org.apache.olingo.server.api.uri.queryoption.FormatOption;
import org.apache.olingo.server.core.requests.ActionRequest;
import org.apache.olingo.server.core.requests.BatchRequest;
@@ -272,6 +273,11 @@
this.request = dataRequest;
}
+ @Override
+ public void visit(ApplyOption option) {
+ ((DataRequest)this.request).setApply(option);
+ }
+
private void executeIdOption(String query, ODataRequest odRequest,
ODataResponse odResponse) throws ODataLibraryException,
ODataApplicationException {
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
index 77e1cfe..836334b 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ServiceHandler.java
@@ -279,7 +279,7 @@
void rollback(String txnId) throws ODataLibraryException, ODataApplicationException;;
/**
- * This is not complete, more URL parsing changes required. Cross join between two entities.
+ * Cross join between two entities.
* @param dataRequest
* @param entitySetNames
* @param response
@@ -311,4 +311,14 @@
* @param response
*/
void processError(ODataServerError error, ErrorResponse response);
+
+ /**
+ * Apply request
+ *
+ * @param dataRequest
+ * @param response
+ * @throws ODataLibraryException
+ * @throws ODataApplicationException
+ */
+ void apply(DataRequest dataRequest, ODataResponse response) throws ODataLibraryException, ODataApplicationException;
}
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
index de5843c..bd4a55e 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/legacy/ProcessorServiceHandler.java
@@ -439,6 +439,12 @@
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
+
+ @Override
+ public void apply(DataRequest dataRequest, ODataResponse response)
+ throws ODataLibraryException, ODataApplicationException {
+ throw new ODataHandlerException("not implemented", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
+ }
@Override
public boolean supportsDataIsolation() {
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
index 5f39f9b..4572c3e 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/BatchRequest.java
@@ -80,7 +80,7 @@
try {
txnId = handler.startTransaction();
partResponse = processChangeSet(part, handler);
- if (partResponse.getResponses().get(0).getStatusCode() > 400) {
+ if (partResponse.getResponses().get(0).getStatusCode() >= 400) {
handler.rollback(txnId);
} else {
handler.commit(txnId);
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
index 11a092f..69603df 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
@@ -71,6 +71,7 @@
import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
import org.apache.olingo.server.api.uri.UriResourceProperty;
import org.apache.olingo.server.api.uri.UriResourceSingleton;
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
import org.apache.olingo.server.core.ContentNegotiator;
import org.apache.olingo.server.core.ContentNegotiatorException;
import org.apache.olingo.server.core.ODataHandlerException;
@@ -277,10 +278,20 @@
public boolean assertHttpMethod(ODataResponse response) throws ODataHandlerException {
// the create/update/delete to navigation property is done through references
// see # 11.4.6
- if (!getNavigations().isEmpty() && !isGET()) {
- return methodNotAllowed(response, httpMethod(),
- "create/update/delete to navigation property is done through references",
- allowedMethods());
+ if (!getNavigations().isEmpty()) {
+ if (isPOST()) {
+ UriResourceNavigation last = getNavigations().getLast();
+ if (!(getEntitySet().getRelatedBindingTarget(last.getProperty().getName())
+ instanceof EdmEntitySet)) {
+ return methodNotAllowed(response, httpMethod(),
+ "navigation updates must be to an entity contained in an entity set",
+ allowedMethods());
+ }
+ } else if (!isGET()) {
+ return methodNotAllowed(response, httpMethod(),
+ "update/delete to navigation property is done through references",
+ allowedMethods());
+ }
}
if ((isGET() || isDELETE()) && getReturnRepresentation() != ReturnRepresentation.NONE) {
@@ -315,13 +326,14 @@
public void execute(ServiceHandler handler, ODataResponse response)
throws ODataLibraryException, ODataApplicationException {
+ ContextURL contextURL = getContextURL(odata);
EntityResponse entityResponse = EntityResponse.getInstance(DataRequest.this,
- getContextURL(odata), false, response);
+ contextURL, false, response);
if (isGET()) {
if (isCollection()) {
handler.read(DataRequest.this,
- EntitySetResponse.getInstance(DataRequest.this, getContextURL(odata), false, response));
+ EntitySetResponse.getInstance(DataRequest.this, contextURL, false, response));
} else {
handler.read(DataRequest.this,entityResponse);
}
@@ -338,24 +350,37 @@
} else if (ifNoneMatch) {
// 11.4.4
entityResponse = EntityResponse.getInstance(DataRequest.this,
- getContextURL(odata), false, response, getReturnRepresentation());
+ contextURL, false, response, getReturnRepresentation());
handler.createEntity(DataRequest.this, getEntityFromClient(), entityResponse);
} else {
handler.upsertEntity(DataRequest.this, getEntityFromClient(), isPATCH(), getETag(),
entityResponse);
}
} else if (isPOST()) {
- entityResponse = EntityResponse.getInstance(DataRequest.this,
- getContextURL(odata), false, response, getReturnRepresentation());
- handler.createEntity(DataRequest.this, getEntityFromClient(),entityResponse);
+ if (!getNavigations().isEmpty()) {
+ entityResponse = EntityResponse.getInstance(DataRequest.this,
+ contextURL, false, response, getReturnRepresentation());
+ UriResourceNavigation last = getNavigations().getLast();
+ EdmEntityType navigationType = last.getProperty().getType();
+ Entity entity = getEntityFromClient(navigationType);
+ handler.createEntity(DataRequest.this, entity,entityResponse);
+ } else {
+ entityResponse = EntityResponse.getInstance(DataRequest.this,
+ contextURL, false, response, getReturnRepresentation());
+ handler.createEntity(DataRequest.this, getEntityFromClient(),entityResponse);
+ }
} else if (isDELETE()) {
handler.deleteEntity(DataRequest.this, getETag(), entityResponse);
}
}
private Entity getEntityFromClient() throws DeserializerException {
+ return getEntityFromClient(getEntitySet().getEntityType());
+ }
+
+ private Entity getEntityFromClient(EdmEntityType entityType) throws DeserializerException {
ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType(), getServiceMetaData());
- return deserializer.entity(getODataRequest().getBody(), getEntitySet().getEntityType()).getEntity();
+ return deserializer.entity(getODataRequest().getBody(), entityType).getEntity();
}
@Override
@@ -763,7 +788,39 @@
return builder.build();
}
}
+
+ class ApplyRequest implements RequestType {
+ @Override
+ public boolean assertHttpMethod(ODataResponse response)
+ throws ODataHandlerException {
+ return ServiceRequest.assertHttpMethod(httpMethod(), allowedMethods(), response);
+ }
+
+ @Override
+ public HttpMethod[] allowedMethods() {
+ return new HttpMethod[] {HttpMethod.GET};
+ }
+
+ @Override
+ public ContentType getResponseContentType() throws ContentNegotiatorException {
+ return ContentNegotiator.doContentNegotiation(getUriInfo().getFormatOption(),
+ getODataRequest(), getCustomContentTypeSupport(), RepresentationType.COLLECTION_COMPLEX);
+ }
+
+ @Override
+ public void execute(ServiceHandler handler, ODataResponse response)
+ throws ODataLibraryException, ODataApplicationException {
+ handler.apply(DataRequest.this, response);
+ }
+
+ @Override
+ public ContextURL getContextURL(OData odata) throws SerializerException {
+ ContextURL.Builder builder = ContextURL.with().asCollection();
+ return builder.build();
+ }
+ }
+
private org.apache.olingo.commons.api.data.Property getPropertyValueFromClient(
EdmProperty edmProperty) throws DeserializerException {
ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType(), getServiceMetaData());
@@ -930,4 +987,8 @@
}
return sb.toString();
}
+
+ public void setApply(ApplyOption apply) {
+ this.type = new ApplyRequest();
+ }
}
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
index 562eac0..cde9b74 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
@@ -493,7 +493,7 @@
map = new HashMap<String, Object>();
this.peopleLinks.put((String) parentEntity.getProperty(key).getValue(), map);
}
- map.put("Photo", childEntity.getProperty(key).getValue());
+ map.put("Photo", ((Long)childEntity.getProperty("Id").getValue()).intValue());
setLink(parentEntity, navigation, childEntity);
} else if (type.getName().equals("Trip") && navigation.equals("PlanItems")) {
Map<String, Object> map = this.tripLinks.get(parentEntity.getProperty(key).getValue());
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
index 4a92198..f594a64 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
@@ -37,6 +37,7 @@
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.EdmSingleton;
+import org.apache.olingo.commons.api.ex.ODataNotSupportedException;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.server.api.OData;
@@ -238,7 +239,12 @@
public void createEntity(DataRequest request, Entity entity, EntityResponse response)
throws ODataLibraryException, ODataApplicationException {
EdmEntitySet edmEntitySet = request.getEntitySet();
-
+
+ if (!request.getNavigations().isEmpty()) {
+ UriResourceNavigation lastNavigation = request.getNavigations().getLast();
+ edmEntitySet = (EdmEntitySet)edmEntitySet.getRelatedBindingTarget(lastNavigation.getProperty().getName());
+ }
+
Entity created = this.dataModel.createEntity(edmEntitySet, entity, request.getODataRequest().getRawBaseUri());
try {
@@ -271,6 +277,25 @@
} catch (URISyntaxException e) {
throw new ODataApplicationException(e.getMessage(), 500, Locale.getDefault());
}
+
+ if (!request.getNavigations().isEmpty()) {
+ UriResourceNavigation lastNavigation = request.getNavigations().getLast();
+
+ String parentRequest = request.getODataRequest().getRawRequestUri();
+ parentRequest = parentRequest.substring(0, parentRequest.lastIndexOf('/'));
+
+ DataRequest bindingRequest;
+ try {
+ bindingRequest = request.parseLink(new URI(parentRequest));
+ } catch (URISyntaxException e) {
+ throw new ODataApplicationException(e.getMessage(), 500, Locale.getDefault());
+ }
+
+ Entity reference = this.dataModel.getEntity(bindingRequest.getEntitySet().getName(),
+ bindingRequest.getKeyPredicates());
+
+ this.dataModel.addNavigationLink(lastNavigation.getProperty().getName(), reference, created);
+ }
response.writeCreatedEntity(edmEntitySet, created);
}
@@ -539,7 +564,13 @@
@Override
public void crossJoin(DataRequest dataRequest, List<String> entitySetNames, ODataResponse response) {
- response.setStatusCode(200);
+ response.setStatusCode(501);
+ }
+
+ @Override
+ public void apply(DataRequest dataRequest, ODataResponse response)
+ throws ODataLibraryException, ODataApplicationException {
+ response.setStatusCode(501);
}
@Override
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
index fa32eef..5d2a13d 100644
--- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
@@ -552,6 +552,46 @@
assertTrue(node.get("value").isArray());
assertEquals("scottketchum", ((ArrayNode)node.get("value")).get(1).get("UserName").asText());
}
+
+ @Ignore("4.01 style binding not supported")
+ @Test
+ public void testCreateEntityWithLinkToRelatedEntitiesIds() throws Exception {
+ String payload = "{\n" +
+ " \"UserName\":\"olingo\",\n" +
+ " \"FirstName\":\"Olingo\",\n" +
+ " \"LastName\":\"Apache\",\n" +
+ " \"Emails\":[\n" +
+ " \"olingo@apache.org\"\n" +
+ " ],\n" +
+ " \"AddressInfo\":[\n" +
+ " {\n" +
+ " \"Address\":\"100 apache Ln.\",\n" +
+ " \"City\":{\n" +
+ " \"CountryRegion\":\"United States\",\n" +
+ " \"Name\":\"Boise\",\n" +
+ " \"Region\":\"ID\"\n" +
+ " }\n" +
+ " }\n" +
+ " ],\n" +
+ " \"Gender\":\"0\",\n" +
+ " \"Concurrency\":635585295719432047,\n" +
+ "\"Friends\":[" +
+ "{\"@id\": \"People('russellwhyte')\"},\n" +
+ "{\"@id\": \"People('scottketchum')\"}\n" +
+ "]"+
+ "}";
+ HttpPost postRequest = new HttpPost(baseURL + "/People");
+ postRequest.setEntity(new StringEntity(payload, ContentType.APPLICATION_JSON));
+ postRequest.setHeader("Prefer", "return=minimal");
+ HttpResponse response = httpSend(postRequest, 204);
+ EntityUtils.consumeQuietly(response.getEntity());
+
+ response = httpGET(baseURL+"/People('olingo')/Friends", 200);
+ JsonNode node = getJSONNode(response);
+ assertEquals(baseURL+"/$metadata#People", node.get("@odata.context").asText());
+ assertTrue(node.get("value").isArray());
+ assertEquals("scottketchum", ((ArrayNode)node.get("value")).get(1).get("UserName").asText());
+ }
@Test
public void testUpdatePrimitiveProperty() throws Exception {
@@ -779,6 +819,80 @@
node = getJSONNode(response);
assertNull("/People('russellwhyte')", ((ArrayNode) node.get("value")).get(2));
}
+
+ @Test
+ public void testAddEntityToNavigationFailsNotEntitySet() throws Exception {
+ // adding to an entity that is not part of an entity set
+ // goes against a few assumptions in downstream code, so
+ // not handling for now
+ String msg = "{\n" +
+ "\"TripId\": 1010,\n" +
+ "\"Description\": \"The trip of a lifetime.\",\n" +
+ "\"Name\": \"Grand Prize\",\n" +
+ "\"Budget\": 100000\n" +
+ "}";
+ String editUrl = baseURL + "/People('vincentcalabrese')/Trips";
+ HttpPost postRequest = new HttpPost(editUrl);
+ postRequest.setEntity(new StringEntity(msg, ContentType.APPLICATION_JSON));
+ postRequest.addHeader("Content-Type", "application/json;odata.metadata=minimal");
+ HttpResponse response = httpSend(postRequest, 405);
+ EntityUtils.consumeQuietly(response.getEntity());
+ }
+
+ @Test
+ public void testAddEntityToNavigation() throws Exception {
+ String msg = "{\n" +
+ "\"Id\": 1010,\n" +
+ "\"Name\": \"Grand Prize\"\n" +
+ "}";
+ String editUrl = baseURL + "/People('vincentcalabrese')/Photo";
+ HttpPost postRequest = new HttpPost(editUrl);
+ postRequest.setEntity(new StringEntity(msg, ContentType.APPLICATION_JSON));
+ postRequest.addHeader("Content-Type", "application/json;odata.metadata=minimal");
+ HttpResponse response = httpSend(postRequest, 201);
+ EntityUtils.consumeQuietly(response.getEntity());
+
+ response = httpGET(baseURL+"/People('vincentcalabrese')/Photo", 200);
+ JsonNode node = getJSONNode(response);
+ assertEquals(baseURL+"/$metadata#Photos/$entity", node.get("@odata.context").asText());
+ assertEquals("Grand Prize", node.get("Name").asText());
+ }
+
+ @Test
+ public void testAddEntityToNavigationSelf() throws Exception {
+ String payload = "{\n" +
+ " \"UserName\":\"olingo\",\n" +
+ " \"FirstName\":\"Olingo\",\n" +
+ " \"LastName\":\"Apache\",\n" +
+ " \"Emails\":[\n" +
+ " \"olingo@apache.org\"\n" +
+ " ],\n" +
+ " \"AddressInfo\":[\n" +
+ " {\n" +
+ " \"Address\":\"100 apache Ln.\",\n" +
+ " \"City\":{\n" +
+ " \"CountryRegion\":\"United States\",\n" +
+ " \"Name\":\"Boise\",\n" +
+ " \"Region\":\"ID\"\n" +
+ " }\n" +
+ " }\n" +
+ " ],\n" +
+ " \"Gender\":\"0\",\n" +
+ " \"Concurrency\":635585295719432047\n" +
+ "}";
+ String editUrl = baseURL + "/People('vincentcalabrese')/Friends";
+ HttpPost postRequest = new HttpPost(editUrl);
+ postRequest.setEntity(new StringEntity(payload, ContentType.APPLICATION_JSON));
+ postRequest.addHeader("Content-Type", "application/json;odata.metadata=minimal");
+ HttpResponse response = httpSend(postRequest, 201);
+ EntityUtils.consumeQuietly(response.getEntity());
+
+ response = httpGET(baseURL+"/People('vincentcalabrese')/Friends", 200);
+ JsonNode node = getJSONNode(response);
+ assertEquals(baseURL+"/$metadata#People", node.get("@odata.context").asText());
+ assertTrue(node.get("value").isArray());
+ assertEquals("olingo", ((ArrayNode)node.get("value")).get(2).get("UserName").asText());
+ }
@Test
public void testDeleteReference() throws Exception {
@@ -798,7 +912,7 @@
public void crossJoin() throws Exception {
String editUrl = baseURL + "/$crossjoin(People,Airlines)?$filter="
+ "People/UserName%20eq%20Airlines/AirlineCode";
- HttpResponse response = httpGET(editUrl, 200);
+ HttpResponse response = httpGET(editUrl, 501);
EntityUtils.consumeQuietly(response.getEntity());
}
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
index bbd94e5..7a632b1 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java
@@ -267,11 +267,13 @@
static void fillUriInformation(final ODataRequest odRequest,
final HttpServletRequest httpRequest, final int split) {
String rawRequestUri = httpRequest.getRequestURL().toString();
-
+
+ String rawServiceResolutionUri = null;
String rawODataPath;
//Application need to set the request mapping attribute if the request is coming from a spring based application
if(httpRequest.getAttribute(REQUESTMAPPING)!=null){
String requestMapping = httpRequest.getAttribute(REQUESTMAPPING).toString();
+ rawServiceResolutionUri = requestMapping;
int beginIndex = rawRequestUri.indexOf(requestMapping) + requestMapping.length();
rawODataPath = rawRequestUri.substring(beginIndex);
}else if(!"".equals(httpRequest.getServletPath())) {
@@ -286,7 +288,6 @@
rawODataPath = httpRequest.getRequestURI();
}
- String rawServiceResolutionUri = null;
if (split > 0) {
rawServiceResolutionUri = rawODataPath;
for (int i = 0; i < split; i++) {
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ApplyParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ApplyParser.java
index 66beb49..27f64fc 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ApplyParser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ApplyParser.java
@@ -135,6 +135,7 @@
private ApplyOption parseApply(EdmStructuredType referencedType)
throws UriParserException, UriValidationException {
ApplyOptionImpl option = new ApplyOptionImpl();
+ option.setEdmStructuredType(referencedType);
do {
option.add(parseTrafo(referencedType));
} while (tokenizer.next(TokenKind.SLASH));
@@ -253,11 +254,18 @@
}
final String alias = parseAsAlias(referencedType, true);
aggregateExpression.setAlias(alias);
+ DynamicProperty dynamicProperty = createDynamicProperty(alias,
+ // Determine the type for standard methods; there is no way to do this for custom methods.
+ getTypeForAggregateMethod(aggregateExpression.getStandardMethod(),
+ ExpressionParser.getType(expression)));
+ if (aggregateExpression.getStandardMethod() == StandardMethod.SUM
+ || aggregateExpression.getStandardMethod() == StandardMethod.AVERAGE) {
+ //by default a property with no precision/scale defaults to a 0 scale
+ //this does not work for sum/average in general
+ dynamicProperty.setScale(Integer.MAX_VALUE);
+ }
((DynamicStructuredType) referencedType).addProperty(
- createDynamicProperty(alias,
- // Determine the type for standard methods; there is no way to do this for custom methods.
- getTypeForAggregateMethod(aggregateExpression.getStandardMethod(),
- ExpressionParser.getType(expression))));
+ dynamicProperty);
parseAggregateFrom(aggregateExpression, referencedType);
}
@@ -319,7 +327,7 @@
}
}
- private EdmProperty createDynamicProperty(final String name, final EdmType type) {
+ private DynamicProperty createDynamicProperty(final String name, final EdmType type) {
return name == null ? null : new DynamicProperty(name, type);
}
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 470b9f8..3c78152 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -481,6 +481,7 @@
for (final ApplyItem item : option.getApplyItems()) {
((ApplyOptionImpl) applyOption).add(item);
}
+ ((ApplyOptionImpl) applyOption).setEdmStructuredType(option.getEdmStructuredType());
}
}
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java
index 066352d..8aa83bf 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java
@@ -22,6 +22,7 @@
import java.util.Collections;
import java.util.List;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.server.api.uri.queryoption.ApplyItem;
import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
@@ -29,6 +30,7 @@
public class ApplyOptionImpl extends SystemQueryOptionImpl implements ApplyOption {
private List<ApplyItem> transformations = new ArrayList<ApplyItem>();
+ private EdmStructuredType edmStructuredType;
public ApplyOptionImpl() {
setKind(SystemQueryOptionKind.APPLY);
@@ -43,4 +45,13 @@
transformations.add(transformation);
return this;
}
+
+ public void setEdmStructuredType(EdmStructuredType referencedType) {
+ this.edmStructuredType = referencedType;
+ }
+
+ @Override
+ public EdmStructuredType getEdmStructuredType() {
+ return edmStructuredType;
+ }
}
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java
index 2cfe063..7cfde33 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java
@@ -34,6 +34,8 @@
private final String name;
private final EdmType propertyType;
+ private Integer precision;
+ private Integer scale;
/** Creates a dynamic property with a mandatory name and an optional type. */
public DynamicProperty(final String name, final EdmType type) {
@@ -78,12 +80,12 @@
@Override
public Integer getPrecision() {
- return null;
+ return precision;
}
@Override
public Integer getScale() {
- return null;
+ return scale;
}
@Override
@@ -120,4 +122,14 @@
public EdmType getTypeWithAnnotations() {
return propertyType;
}
+
+ public DynamicProperty setPrecision(Integer precision) {
+ this.precision = precision;
+ return this;
+ }
+
+ public DynamicProperty setScale(Integer scale) {
+ this.scale = scale;
+ return this;
+ }
}
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
index 0645423..158cae6 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java
@@ -212,7 +212,7 @@
String rawODataPath = p[4];
String rawQueryPath = "".equals(p[5]) ? null : p[5];
String rawRequestUri = requestUrl + (queryString == null ? "" : "?" + queryString);
- String rawServiceResolutionUri = "".equals(p[3]) ? null : p[3];
+ String rawServiceResolutionUri = ("0".equals(p[6])) ? p[2] : p[3];
when(hr.getAttribute("requestMapping")).thenReturn(p[2]);
ODataHttpHandlerImpl.fillUriInformation(odr, hr, Integer.parseInt(p[6]));