You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/05/29 11:01:10 UTC
[3/4] olingo-odata4 git commit: [OLINGO-663] conditional handling in
technical service, part 2
[OLINGO-663] conditional handling in technical service, part 2
Signed-off-by: Christian Amend <ch...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/7ad5b0fb
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/7ad5b0fb
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/7ad5b0fb
Branch: refs/heads/OLINGO-632_OSGi-Support
Commit: 7ad5b0fb54dd3f52247716afb32b2e8192fe750c
Parents: ea89f72
Author: Klaus Straubinger <kl...@sap.com>
Authored: Thu May 28 12:35:41 2015 +0200
Committer: Christian Amend <ch...@apache.org>
Committed: Thu May 28 15:12:31 2015 +0200
----------------------------------------------------------------------
.../fit/tecsvc/client/ConditionalITCase.java | 156 ++++++++--
.../olingo/fit/tecsvc/client/MediaITCase.java | 6 +-
.../tecsvc/client/PrimitiveComplexITCase.java | 121 +++++++-
.../olingo/server/api/EtagInformation.java | 4 +-
.../olingo/server/tecsvc/ETagSupport.java | 34 +++
.../olingo/server/tecsvc/TechnicalServlet.java | 7 +-
.../olingo/server/tecsvc/data/DataProvider.java | 10 +-
.../processor/TechnicalEntityProcessor.java | 97 +++---
.../TechnicalPrimitiveComplexProcessor.java | 294 ++++++++++++-------
.../tecsvc/processor/TechnicalProcessor.java | 47 ++-
10 files changed, 584 insertions(+), 192 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ConditionalITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ConditionalITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ConditionalITCase.java
index 2dcbc26..796c2c4 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ConditionalITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ConditionalITCase.java
@@ -18,20 +18,35 @@
*/
package org.apache.olingo.fit.tecsvc.client;
+import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import java.net.URI;
+
+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.request.ODataBasicRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataPropertyUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.UpdateType;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataValueRequest;
+import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.response.ODataDeleteResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.client.api.http.HttpClientException;
import org.apache.olingo.client.core.ODataClientFactory;
-import org.apache.olingo.commons.api.ODataError;
import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.fit.AbstractBaseTestITCase;
import org.apache.olingo.fit.tecsvc.TecSvcConst;
@@ -39,31 +54,27 @@ import org.junit.Test;
public final class ConditionalITCase extends AbstractBaseTestITCase {
+ private final ODataClient client = getClient();
+
+ private final URI uriEntity = client.newURIBuilder(TecSvcConst.BASE_URI)
+ .appendEntitySetSegment("ESCompAllPrim").appendKeySegment(0).build();
+ private final URI uriProperty = client.newURIBuilder(uriEntity.toASCIIString())
+ .appendPropertySegment("PropertyComp").appendPropertySegment("PropertyDuration").build();
+ private final URI uriPropertyValue = client.newURIBuilder(uriProperty.toASCIIString()).appendValueSegment().build();
+ private final URI uriMedia = client.newURIBuilder(TecSvcConst.BASE_URI)
+ .appendEntitySetSegment("ESMedia").appendKeySegment(1).appendValueSegment().build();
+
@Test
public void readWithWrongIfMatch() throws Exception {
- final ODataClient client = getClient();
- ODataEntityRequest<ClientEntity> request = client.getRetrieveRequestFactory().getEntityRequest(
- client.newURIBuilder(TecSvcConst.BASE_URI)
- .appendEntitySetSegment("ESCompAllPrim").appendKeySegment(0).build());
+ ODataEntityRequest<ClientEntity> request = client.getRetrieveRequestFactory().getEntityRequest(uriEntity);
request.setIfMatch("W/\"1\"");
assertNotNull(request);
-
- try {
- request.execute();
- fail("Expected Exception not thrown!");
- } catch (final ODataClientErrorException e) {
- assertEquals(HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), e.getStatusLine().getStatusCode());
- final ODataError error = e.getODataError();
- assertThat(error.getMessage(), containsString("condition"));
- }
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
}
@Test
public void readNotModified() throws Exception {
- final ODataClient client = getClient();
- ODataEntityRequest<ClientEntity> request = client.getRetrieveRequestFactory().getEntityRequest(
- client.newURIBuilder(TecSvcConst.BASE_URI)
- .appendEntitySetSegment("ESCompAllPrim").appendKeySegment(0).build());
+ ODataEntityRequest<ClientEntity> request = client.getRetrieveRequestFactory().getEntityRequest(uriEntity);
request.setIfNoneMatch("W/\"0\"");
assertNotNull(request);
@@ -71,6 +82,115 @@ public final class ConditionalITCase extends AbstractBaseTestITCase {
assertEquals(HttpStatusCode.NOT_MODIFIED.getStatusCode(), response.getStatusCode());
}
+ @Test
+ public void updateWithoutIfMatch() throws Exception {
+ executeAndExpectError(
+ client.getCUDRequestFactory().getEntityUpdateRequest(
+ uriEntity, UpdateType.PATCH, client.getObjectFactory().newEntity(null)),
+ HttpStatusCode.PRECONDITION_REQUIRED);
+ }
+
+ @Test
+ public void updateWithWrongIfMatch() throws Exception {
+ ODataEntityUpdateRequest<ClientEntity> request = client.getCUDRequestFactory().getEntityUpdateRequest(
+ uriEntity, UpdateType.PATCH, client.getObjectFactory().newEntity(null));
+ request.setIfMatch("W/\"1\"");
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ @Test
+ public void updateMediaWithWrongIfMatch() throws Exception {
+ ODataMediaEntityUpdateRequest<ClientEntity> request = client.getCUDRequestFactory().getMediaEntityUpdateRequest(
+ uriMedia, IOUtils.toInputStream("ignored"));
+ request.setIfMatch("W/\"42\"");
+
+ try {
+ request.payloadManager().getResponse();
+ fail("Expected Exception not thrown!");
+ } catch (final HttpClientException e) {
+ final ODataClientErrorException ex = (ODataClientErrorException) e.getCause().getCause();
+ assertEquals(HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), ex.getStatusLine().getStatusCode());
+ assertThat(ex.getODataError().getMessage(), containsString("condition"));
+ }
+ }
+
+ @Test
+ public void deleteWithWrongIfMatch() throws Exception {
+ ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriEntity);
+ request.setIfMatch("W/\"1\"");
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ @Test
+ public void deleteMediaWithWrongIfMatch() throws Exception {
+ ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriMedia);
+ request.setIfMatch("W/\"42\"");
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ @Test
+ public void indirectEntityChange() throws Exception {
+ final String eTag = "W/\"0\"";
+ ODataDeleteRequest deleteRequest = client.getCUDRequestFactory().getDeleteRequest(uriProperty);
+ deleteRequest.setIfMatch(eTag);
+ final ODataDeleteResponse response = deleteRequest.execute();
+
+ ODataEntityUpdateRequest<ClientEntity> request = client.getCUDRequestFactory().getEntityUpdateRequest(
+ uriEntity, UpdateType.PATCH, client.getObjectFactory().newEntity(null));
+ request.setIfMatch(eTag);
+ // This request has to be in the same session as the first in order to access the same data provider.
+ request.addCustomHeader(HttpHeader.COOKIE, response.getHeader(HttpHeader.SET_COOKIE).iterator().next());
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ @Test
+ public void readPropertyNotModified() throws Exception {
+ ODataPropertyRequest<ClientProperty> request = client.getRetrieveRequestFactory().getPropertyRequest(uriProperty);
+ request.setIfNoneMatch("W/\"0\"");
+ assertEquals(HttpStatusCode.NOT_MODIFIED.getStatusCode(), request.execute().getStatusCode());
+ }
+
+ @Test
+ public void readPropertyValueNotModified() throws Exception {
+ ODataValueRequest request = client.getRetrieveRequestFactory().getPropertyValueRequest(uriPropertyValue);
+ request.setIfNoneMatch("W/\"0\"");
+ assertEquals(HttpStatusCode.NOT_MODIFIED.getStatusCode(), request.execute().getStatusCode());
+ }
+
+ @Test
+ public void updatePropertyWithWrongIfMatch() throws Exception {
+ ODataPropertyUpdateRequest request = client.getCUDRequestFactory().getPropertyPrimitiveValueUpdateRequest(
+ uriProperty,
+ client.getObjectFactory().newPrimitiveProperty("PropertyDuration",
+ client.getObjectFactory().newPrimitiveValueBuilder().buildString("PT42S")));
+ request.setIfMatch("W/\"1\"");
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ @Test
+ public void deletePropertyWithWrongIfMatch() throws Exception {
+ ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriProperty);
+ request.setIfMatch("W/\"1\"");
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ @Test
+ public void deletePropertyValueWithWrongIfMatch() throws Exception {
+ ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriPropertyValue);
+ request.setIfMatch("W/\"1\"");
+ executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
+ }
+
+ private void executeAndExpectError(ODataBasicRequest<?> request, final HttpStatusCode status) {
+ try {
+ request.execute();
+ fail("Expected Exception not thrown!");
+ } catch (final ODataClientErrorException e) {
+ assertEquals(status.getStatusCode(), e.getStatusLine().getStatusCode());
+ assertThat(e.getODataError().getMessage(), anyOf(containsString("condition"), containsString("match")));
+ }
+ }
+
@Override
protected ODataClient getClient() {
ODataClient odata = ODataClientFactory.getClient();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/MediaITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/MediaITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/MediaITCase.java
index e48f08c..3bd14c1 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/MediaITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/MediaITCase.java
@@ -75,7 +75,8 @@ public final class MediaITCase extends AbstractBaseTestITCase {
final ODataClient client = getClient();
final URI uri = client.newURIBuilder(TecSvcConst.BASE_URI)
.appendEntitySetSegment("ESMedia").appendKeySegment(4).appendValueSegment().build();
- final ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uri);
+ ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uri);
+ request.setIfMatch("W/\"4\"");
assertNotNull(request);
final ODataDeleteResponse response = request.execute();
@@ -102,6 +103,7 @@ public final class MediaITCase extends AbstractBaseTestITCase {
client.getCUDRequestFactory().getMediaEntityUpdateRequest(uri,
IOUtils.toInputStream("just a test"));
request.setContentType(ContentType.TEXT_PLAIN.toContentTypeString());
+ request.setIfMatch("W/\"4\"");
assertNotNull(request);
final ODataMediaEntityUpdateResponse<ClientEntity> response = request.payloadManager().getResponse();
@@ -143,7 +145,7 @@ public final class MediaITCase extends AbstractBaseTestITCase {
// This check has to be in the same session in order to access the same data provider.
ODataMediaRequest mediaRequest = client.getRetrieveRequestFactory().getMediaRequest(
client.newURIBuilder(TecSvcConst.BASE_URI).appendEntitySetSegment("ESMedia")
- .appendKeySegment(5).appendValueSegment().build());
+ .appendKeySegment(5).appendValueSegment().build());
mediaRequest.addCustomHeader(HttpHeader.COOKIE, response.getHeader(HttpHeader.SET_COOKIE).iterator().next());
ODataRetrieveResponse<InputStream> mediaResponse = mediaRequest.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), mediaResponse.getStatusCode());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/PrimitiveComplexITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/PrimitiveComplexITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/PrimitiveComplexITCase.java
index 50ab97b..d71e6a0 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/PrimitiveComplexITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/PrimitiveComplexITCase.java
@@ -20,23 +20,31 @@ package org.apache.olingo.fit.tecsvc.client;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.net.URI;
+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.request.cud.ODataDeleteRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataPropertyUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.UpdateType;
import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataValueRequest;
import org.apache.olingo.client.api.communication.response.ODataDeleteResponse;
+import org.apache.olingo.client.api.communication.response.ODataPropertyUpdateResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.domain.ClientCollectionValue;
+import org.apache.olingo.client.api.domain.ClientComplexValue;
import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.client.api.domain.ClientValue;
import org.apache.olingo.client.core.ODataClientFactory;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
@@ -52,13 +60,12 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
@Test
public void readSimpleProperty() throws Exception {
- ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
+ final ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
.getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESTwoPrim")
.appendKeySegment(32766)
.appendPropertySegment("PropertyString")
.build());
-
assertNotNull(request);
ODataRetrieveResponse<ClientProperty> response = request.execute();
@@ -135,7 +142,7 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
@Test
public void readComplexProperty() throws Exception {
- ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
+ final ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
.getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESMixPrimCollComp")
.appendKeySegment(7)
@@ -153,7 +160,7 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
@Test
public void readComplexPropertyContextURL() throws Exception {
- ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
+ final ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
.getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESMixPrimCollComp")
.appendKeySegment(7)
@@ -185,7 +192,7 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
@Test
public void readUnknownProperty() throws Exception {
- ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
+ final ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
.getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESTwoPrim")
.appendKeySegment(32766)
@@ -201,17 +208,115 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
@Test
public void readNoContentProperty() throws Exception {
- ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
+ final ODataPropertyRequest<ClientProperty> request = getClient().getRetrieveRequestFactory()
.getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
.appendEntitySetSegment("ESTwoPrim")
.appendKeySegment(-32766)
.appendPropertySegment("PropertyString")
.build());
- ODataRetrieveResponse<ClientProperty> response = request.execute();
+ final ODataRetrieveResponse<ClientProperty> response = request.execute();
assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode());
}
@Test
+ public void updatePrimitiveProperty() throws Exception {
+ final ODataPropertyUpdateRequest request =
+ getClient().getCUDRequestFactory().getPropertyPrimitiveValueUpdateRequest(
+ getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESTwoPrim").appendKeySegment(32766)
+ .appendPropertySegment("PropertyString")
+ .build(),
+ getClient().getObjectFactory().newPrimitiveProperty("PropertyString",
+ getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Test String1")));
+ assertNotNull(request);
+
+ final ODataPropertyUpdateResponse response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+ final ClientProperty property = response.getBody();
+ assertNotNull(property);
+ assertNotNull(property.getPrimitiveValue());
+ assertEquals("Test String1", property.getPrimitiveValue().toValue());
+ }
+
+ @Test
+ public void patchComplexProperty() throws Exception {
+ final ODataPropertyUpdateRequest request =
+ getClient().getCUDRequestFactory().getPropertyComplexValueUpdateRequest(
+ getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESMixPrimCollComp").appendKeySegment(7)
+ .appendPropertySegment("PropertyComp")
+ .build(),
+ UpdateType.PATCH,
+ getClient().getObjectFactory().newComplexProperty("PropertyComp",
+ getClient().getObjectFactory().newComplexValue(null).add(
+ getClient().getObjectFactory().newPrimitiveProperty("PropertyString",
+ getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Test String42")))));
+ assertNotNull(request);
+
+ final ODataPropertyUpdateResponse response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+ final ClientProperty property = response.getBody();
+ assertNotNull(property);
+ assertNotNull(property.getComplexValue());
+ final ClientComplexValue value = property.getComplexValue();
+ assertEquals("Test String42", value.get("PropertyString").getPrimitiveValue().toValue());
+ assertEquals(222, value.get("PropertyInt16").getPrimitiveValue().toValue());
+ }
+
+ @Test
+ public void updatePrimitiveCollection() throws Exception {
+ final ODataPropertyUpdateRequest request =
+ getClient().getCUDRequestFactory().getPropertyCollectionValueUpdateRequest(
+ getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESMixPrimCollComp").appendKeySegment(7)
+ .appendPropertySegment("CollPropertyString")
+ .build(),
+ getClient().getObjectFactory().newCollectionProperty("CollPropertyString",
+ getClient().getObjectFactory().newCollectionValue(null)
+ .add(getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Test String1"))
+ .add(getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Test String2"))));
+ assertNotNull(request);
+
+ final ODataPropertyUpdateResponse response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+ final ClientProperty property = response.getBody();
+ assertNotNull(property);
+ final ClientCollectionValue<ClientValue> value = property.getCollectionValue();
+ assertNotNull(value);
+ Iterator<ClientValue> iterator = value.iterator();
+ assertTrue(iterator.hasNext());
+ assertEquals("Test String1", iterator.next().asPrimitive().toValue());
+ assertEquals("Test String2", iterator.next().asPrimitive().toValue());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void updateComplexCollection() throws Exception {
+ final ODataPropertyUpdateRequest request =
+ getClient().getCUDRequestFactory().getPropertyCollectionValueUpdateRequest(
+ getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESMixPrimCollComp").appendKeySegment(7)
+ .appendPropertySegment("CollPropertyComp")
+ .build(),
+ getClient().getObjectFactory().newCollectionProperty("CollPropertyComp",
+ getClient().getObjectFactory().newCollectionValue(null)));
+ assertNotNull(request);
+
+ final ODataPropertyUpdateResponse response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+ final ClientProperty property = response.getBody();
+ assertNotNull(property);
+ final ClientCollectionValue<ClientValue> value = property.getCollectionValue();
+ assertNotNull(value);
+ assertFalse(value.iterator().hasNext());
+ }
+
+ @Test
public void readPropertyValue() throws Exception {
final ODataValueRequest request = getClient().getRetrieveRequestFactory()
.getPropertyValueRequest(getClient().newURIBuilder(SERVICE_URI)
@@ -220,7 +325,7 @@ public class PrimitiveComplexITCase extends AbstractBaseTestITCase {
.appendPropertySegment("PropertyString")
.appendValueSegment()
.build());
- ODataRetrieveResponse<ClientPrimitiveValue> response = request.execute();
+ final ODataRetrieveResponse<ClientPrimitiveValue> response = request.execute();
assertEquals("Test String1", response.getBody().toValue());
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-api/src/main/java/org/apache/olingo/server/api/EtagInformation.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/EtagInformation.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/EtagInformation.java
index d6be3fa..87c6a17 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/EtagInformation.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/EtagInformation.java
@@ -48,7 +48,9 @@ public class EtagInformation {
}
/**
- * <p>Checks whether a given ETag value is matched by this ETag information.</p>
+ * <p>Checks whether a given ETag value is matched by this ETag information,
+ * using weak comparison as described in
+ * <a href="https://www.ietf.org/rfc/rfc7232.txt">RFC 7232</a>, section 2.3.2.</p>
* <p>If the given value is <code>null</code>, or if this ETag information
* does not contain anything, the result is <code>false</code>.</p>
* @param etag the ETag value to match
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
new file mode 100644
index 0000000..825032d
--- /dev/null
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import org.apache.olingo.server.api.CustomETagSupport;
+
+public class ETagSupport implements CustomETagSupport {
+
+ @Override
+ public boolean hasETag(final String entitySetName) {
+ return entitySetName.equals("ESCompAllPrim");
+ }
+
+ @Override
+ public boolean hasMediaETag(final String entitySetName) {
+ return entitySetName.equals("ESMedia");
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
index 25c86c7..0412c80 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
@@ -48,7 +48,7 @@ public class TechnicalServlet extends HttpServlet {
private static final Logger LOG = LoggerFactory.getLogger(TechnicalServlet.class);
@Override
- protected void service(final HttpServletRequest req, final HttpServletResponse resp)
+ protected void service(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
try {
OData odata = OData.newInstance();
@@ -57,7 +57,7 @@ public class TechnicalServlet extends HttpServlet {
final List<EdmxReference> references = Arrays.asList(reference);
final ServiceMetadata serviceMetadata = odata.createServiceMetadata(new EdmTechProvider(references), references);
- HttpSession session = req.getSession(true);
+ HttpSession session = request.getSession(true);
DataProvider dataProvider = (DataProvider) session.getAttribute(DataProvider.class.getName());
if (dataProvider == null) {
dataProvider = new DataProvider();
@@ -69,7 +69,8 @@ public class TechnicalServlet extends HttpServlet {
handler.register(new TechnicalEntityProcessor(dataProvider, serviceMetadata));
handler.register(new TechnicalPrimitiveComplexProcessor(dataProvider, serviceMetadata));
handler.register(new TechnicalBatchProcessor(dataProvider));
- handler.process(req, resp);
+ handler.register(new ETagSupport());
+ handler.process(request, response);
} catch (RuntimeException e) {
LOG.error("Server Error", e);
throw new ServletException(e);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 9de9bea..732d43b 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -275,6 +275,10 @@ public class DataProvider {
}
// Update the ETag if present.
+ updateETag(entity);
+ }
+
+ public void updateETag(Entity entity) {
if (entity.getETag() != null) {
entity.setETag("W/\"" + System.nanoTime() + "\"");
}
@@ -411,8 +415,8 @@ public class DataProvider {
}
}
- @SuppressWarnings({ "unchecked" })
- public void updateProperty(final EdmProperty edmProperty, final Property property, final Property newProperty,
+ @SuppressWarnings("unchecked")
+ public void updateProperty(final EdmProperty edmProperty, Property property, final Property newProperty,
final boolean patch) throws DataProviderException {
if (edmProperty.isPrimitive()) {
if (newProperty != null || !patch) {
@@ -420,7 +424,7 @@ public class DataProvider {
property.setValue(property.getValueType(), value);
}
} else if (edmProperty.isCollection()) {
- // Updating collection properties mean replacing all entites with the given ones
+ // Updating collection properties means replacing all entries with the given ones.
property.asCollection().clear();
if (newProperty != null) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
index 0ad21bb..489055b 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
@@ -18,6 +18,7 @@
*/
package org.apache.olingo.server.tecsvc.processor;
+import java.util.List;
import java.util.Locale;
import org.apache.olingo.commons.api.data.ContextURL;
@@ -34,7 +35,6 @@ import org.apache.olingo.commons.api.http.HttpContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.commons.api.http.HttpStatusCode;
-import org.apache.olingo.server.api.EtagInformation;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
@@ -57,9 +57,11 @@ 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.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.UriResourceValue;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
@@ -98,7 +100,10 @@ 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 {
- EdmAction action = checkBoundAndExtractAction(uriInfo);
+ blockBoundActions(uriInfo);
+ final EdmAction action = ((UriResourceAction) uriInfo.asUriInfoResource().getUriResourceParts().get(0))
+ .getAction();
+
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
@@ -148,7 +153,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
validateOptions(uriInfo.asUriInfoResource());
- processEntity(request, response, uriInfo, requestedContentType, false);
+ readEntity(request, response, uriInfo, requestedContentType, false);
}
@Override
@@ -238,6 +243,10 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
throw e;
}
}
+
+ checkChangePreconditions(entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
checkRequestFormat(requestFormat);
final ODataDeserializer deserializer = odata.createDeserializer(ODataFormat.fromContentType(requestFormat));
final Entity changedEntity = deserializer.entity(request.getBody(), edmEntitySet.getEntityType()).getEntity();
@@ -252,10 +261,10 @@ 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.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
@@ -270,6 +279,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
Entity entity = readEntity(uriInfo);
+ checkChangePreconditions(entity.getMediaETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
checkRequestFormat(requestFormat);
dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()),
requestFormat.toContentTypeString());
@@ -285,10 +297,16 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
}
@Override
- public void deleteEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo)
+ public void deleteEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
throws ODataApplicationException {
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
final Entity entity = readEntity(uriInfo);
+ final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+ final boolean isValue = resourcePaths.get(resourcePaths.size() - 1) instanceof UriResourceValue;
+
+ checkChangePreconditions(isValue ? entity.getMediaETag() : entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
dataProvider.delete(edmEntitySet, entity);
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
@@ -297,7 +315,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
public void processActionEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
- final EdmAction action = checkBoundAndExtractAction(uriInfo);
+ blockBoundActions(uriInfo);
+ final EdmAction action = ((UriResourceAction) uriInfo.asUriInfoResource().getUriResourceParts().get(0))
+ .getAction();
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
final EdmEntityType type = (EdmEntityType) action.getReturnType().getType();
@@ -319,9 +339,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
final ODataFormat format = ODataFormat.fromContentType(responseFormat);
response.setContent(serializeEntity(entityResult.getEntity(), edmEntitySet, type, format, null, null)
.getContent());
- response.setStatusCode((entityResult.isCreated() ? HttpStatusCode.CREATED : HttpStatusCode.OK).getStatusCode
-
- ());
+ response.setStatusCode((entityResult.isCreated() ? HttpStatusCode.CREATED : HttpStatusCode.OK)
+ .getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
if (entityResult.getEntity().getETag() != null) {
response.setHeader(HttpHeader.ETAG, entityResult.getEntity().getETag());
@@ -343,17 +362,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
}
- private void checkRequestFormat(final ContentType requestFormat) throws ODataApplicationException {
- if (requestFormat == null) {
- throw new ODataApplicationException("The content type has not been set in the request.",
- HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
- }
- }
-
private ContextURL getContextUrl(final EdmEntitySet entitySet, final EdmEntityType entityType,
- final boolean isSingleEntity, final ExpandOption expand, final SelectOption select) throws
-
- SerializerException {
+ final boolean isSingleEntity, final ExpandOption expand, final SelectOption select) throws SerializerException {
Builder builder = ContextURL.with();
builder = entitySet == null ?
isSingleEntity ? builder.type(entityType) : builder.asCollection().type(entityType) :
@@ -365,30 +375,26 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
}
@Override
- public void readReference(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void readReference(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType) throws ODataApplicationException, SerializerException {
-
- processEntity(request, response, uriInfo, requestedContentType, true);
+ readEntity(request, response, uriInfo, requestedContentType, true);
}
@Override
- public void createReference(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void createReference(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestFormat) throws ODataApplicationException, DeserializerException {
-
throw new ODataApplicationException("Not implemented", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
@Override
- public void updateReference(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void updateReference(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestFormat) throws ODataApplicationException, DeserializerException {
-
throw new ODataApplicationException("Not implemented", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
@Override
- public void deleteReference(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo)
+ public void deleteReference(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
throws ODataApplicationException {
-
throw new ODataApplicationException("Not implemented", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
@@ -399,7 +405,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
processEntityCollection(request, response, uriInfo, requestedContentType, true);
}
- private void processEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ private void readEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
final ContentType requestedContentType, final boolean isReference)
throws ODataApplicationException, SerializerException {
final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo);
@@ -410,18 +416,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
final Entity entity = readEntity(uriInfo);
- if (entity.getETag() != null) {
- final EtagInformation ifMatch = odata.createEtagInformation(request.getHeaders(HttpHeader.IF_MATCH));
- if (!ifMatch.isMatchedBy(entity.getETag()) && !ifMatch.getEtags().isEmpty()) {
- throw new ODataApplicationException("The If-Match precondition is not fulfilled.",
- HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), Locale.ROOT);
- }
- if (odata.createEtagInformation(request.getHeaders(HttpHeader.IF_NONE_MATCH))
- .isMatchedBy(entity.getETag())) {
- throw new ODataApplicationException("The entity has not been modified.",
- HttpStatusCode.NOT_MODIFIED.getStatusCode(), Locale.ROOT);
- }
- }
+ checkReadPreconditions(entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
final ExpandOption expand = uriInfo.getExpandOption();
@@ -430,12 +427,11 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
final ExpandSystemQueryOptionHandler expandHandler = new ExpandSystemQueryOptionHandler();
final Entity entitySerialization = expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand);
expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, expand);
-
- final SerializerResult serializerResult = (isReference) ?
- serializeReference(entity, edmEntitySet, format)
- : serializeEntity(entitySerialization, edmEntitySet, edmEntityType, format, expand, select);
-
-
+
+ final SerializerResult serializerResult = isReference ?
+ serializeReference(entity, edmEntitySet, format) :
+ serializeEntity(entitySerialization, edmEntitySet, edmEntityType, format, expand, select);
+
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
@@ -495,15 +491,15 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
// Serialize
final SerializerResult serializerResult = (isReference) ?
serializeReferenceCollection(entitySetSerialization, edmEntitySet, format) :
- serializeEntiyCollection(entitySetSerialization, edmEntitySet, edmEntityType, format,
- expand, select, countOption);
+ serializeEntityCollection(entitySetSerialization, edmEntitySet, edmEntityType, format,
+ expand, select, countOption);
response.setContent(serializerResult.getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
}
- private SerializerResult serializeEntiyCollection(final EntityCollection entityCollection,
+ private SerializerResult serializeEntityCollection(final EntityCollection entityCollection,
final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, final ODataFormat format,
final ExpandOption expand, final SelectOption select, final CountOption countOption)
throws SerializerException {
@@ -541,7 +537,6 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
private SerializerResult serializeEntity(final Entity entity,
final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, final ODataFormat format,
final ExpandOption expand, final SelectOption select) throws SerializerException {
-
return odata.createSerializer(format).entity(
serviceMetadata,
edmEntityType,
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
index 0d911f0..4f1a4ba 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
@@ -40,6 +40,7 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataRequest;
@@ -68,6 +69,7 @@ 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;
@@ -90,30 +92,31 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
}
@Override
- public void readPrimitive(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void readPrimitive(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
- readProperty(response, uriInfo, contentType, RepresentationType.PRIMITIVE);
+ readProperty(request, response, uriInfo, contentType, RepresentationType.PRIMITIVE);
}
@Override
- public void updatePrimitive(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void updatePrimitive(final ODataRequest request, 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);
+ updateProperty(request, response, uriInfo, requestFormat, responseFormat, RepresentationType.PRIMITIVE);
}
@Override
- public void deletePrimitive(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo)
+ public void deletePrimitive(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
throws ODataApplicationException {
- deleteProperty(response, uriInfo);
+ deleteProperty(request, response, uriInfo);
}
@Override
- public void processActionPrimitive(final ODataRequest request, final ODataResponse response,
+ public void processActionPrimitive(final ODataRequest request, ODataResponse response,
final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
- EdmAction action = checkBoundAndExtractAction(uriInfo);
+ blockBoundActions(uriInfo);
+ final EdmAction action = ((UriResourceAction) uriInfo.asUriInfoResource().getUriResourceParts().get(0))
+ .getAction();
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
@@ -124,8 +127,9 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
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);
+ // Not nullable return type so we have to give back an Internal Server Error
+ throw new ODataApplicationException("The action could not be executed.",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
} else {
ContextURL contextURL = ContextURL.with().type(type).build();
@@ -141,31 +145,31 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
}
@Override
- public void readPrimitiveCollection(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void readPrimitiveCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
- readProperty(response, uriInfo, contentType, RepresentationType.COLLECTION_PRIMITIVE);
+ readProperty(request, response, uriInfo, contentType, RepresentationType.COLLECTION_PRIMITIVE);
}
@Override
- public void updatePrimitiveCollection(final ODataRequest request, final ODataResponse response,
+ public void updatePrimitiveCollection(final ODataRequest request, 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);
+ updateProperty(request, response, uriInfo, requestFormat, responseFormat, RepresentationType.COLLECTION_PRIMITIVE);
}
@Override
- public void
- deletePrimitiveCollection(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo)
- throws ODataApplicationException {
- deleteProperty(response, uriInfo);
+ public void deletePrimitiveCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
+ throws ODataApplicationException {
+ deleteProperty(request, response, uriInfo);
}
@Override
- public void processActionPrimitiveCollection(final ODataRequest request, final ODataResponse response,
+ public void processActionPrimitiveCollection(final ODataRequest request, ODataResponse response,
final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
- EdmAction action = checkBoundAndExtractAction(uriInfo);
+ blockBoundActions(uriInfo);
+ final EdmAction action = ((UriResourceAction) uriInfo.asUriInfoResource().getUriResourceParts().get(0))
+ .getAction();
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
@@ -175,10 +179,12 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
if (property == null || property.isNull()) {
// Collection Propertys must never be null
- throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
+ throw new ODataApplicationException("The action could not be executed.",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), 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);
+ 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();
@@ -194,24 +200,31 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
}
@Override
- public void readComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void readComplex(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
- readProperty(response, uriInfo, contentType, RepresentationType.COMPLEX);
+ readProperty(request, response, uriInfo, contentType, RepresentationType.COMPLEX);
}
@Override
- public void updateComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void updateComplex(final ODataRequest request, 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);
+ updateProperty(request, response, uriInfo, requestFormat, responseFormat, RepresentationType.COMPLEX);
+ }
+
+ @Override
+ public void deleteComplex(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
+ throws ODataApplicationException {
+ deleteProperty(request, response, uriInfo);
}
@Override
- public void processActionComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void processActionComplex(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
- EdmAction action = checkBoundAndExtractAction(uriInfo);
+ blockBoundActions(uriInfo);
+ final EdmAction action = ((UriResourceAction) uriInfo.asUriInfoResource().getUriResourceParts().get(0))
+ .getAction();
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
@@ -222,8 +235,9 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
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);
+ // Not nullable return type so we have to give back an Internal Server Error
+ throw new ODataApplicationException("The action could not be executed.",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
}
} else {
ContextURL contextURL = ContextURL.with().type(type).build();
@@ -240,30 +254,31 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
}
@Override
- public void deleteComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo)
- throws ODataApplicationException {
- deleteProperty(response, uriInfo);
- }
-
- @Override
- public void readComplexCollection(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void readComplexCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
- readProperty(response, uriInfo, contentType, RepresentationType.COLLECTION_COMPLEX);
+ readProperty(request, response, uriInfo, contentType, RepresentationType.COLLECTION_COMPLEX);
}
@Override
- public void updateComplexCollection(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void updateComplexCollection(final ODataRequest request, 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);
+ updateProperty(request, response, uriInfo, requestFormat, responseFormat, RepresentationType.COLLECTION_COMPLEX);
}
@Override
- public void processActionComplexCollection(final ODataRequest request, final ODataResponse response,
+ public void deleteComplexCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
+ throws ODataApplicationException {
+ deleteProperty(request, response, uriInfo);
+ }
+
+ @Override
+ public void processActionComplexCollection(final ODataRequest request, ODataResponse response,
final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException {
- EdmAction action = checkBoundAndExtractAction(uriInfo);
+ blockBoundActions(uriInfo);
+ final EdmAction action = ((UriResourceAction) uriInfo.asUriInfoResource().getUriResourceParts().get(0))
+ .getAction();
DeserializerResult deserializerResult =
odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
.actionParameters(request.getBody(), action);
@@ -273,10 +288,12 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
if (property == null || property.isNull()) {
// Collection Propertys must never be null
- throw new ODataApplicationException("The action could no be executed", 500, Locale.ROOT);
+ throw new ODataApplicationException("The action could not be executed.",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), 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);
+ 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();
@@ -291,14 +308,9 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
}
- @Override
- public void deleteComplexCollection(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo)
- throws ODataApplicationException {
- deleteProperty(response, uriInfo);
- }
-
- private void readProperty(final ODataResponse response, final UriInfo uriInfo, final ContentType contentType,
- final RepresentationType representationType) throws ODataApplicationException, SerializerException {
+ private void readProperty(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
+ final ContentType contentType, final RepresentationType representationType)
+ throws ODataApplicationException, SerializerException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
validateOptions(resource);
validatePath(resource);
@@ -308,9 +320,16 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
final List<String> path = getPropertyPath(resourceParts, 0);
final Entity entity = readEntity(uriInfo);
+
+ if (entity != null && entity.getETag() != null) {
+ checkReadPreconditions(entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
+ }
+
final Property property = entity == null ?
- getPropertyData(dataProvider.readFunctionPrimitiveComplex(((UriResourceFunction) resourceParts.get(0))
- .getFunction(),
+ getPropertyData(
+ dataProvider.readFunctionPrimitiveComplex(((UriResourceFunction) resourceParts.get(0)).getFunction(),
((UriResourceFunction) resourceParts.get(0)).getParameters()), path) :
getPropertyData(entity, path);
@@ -320,6 +339,7 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
if (property.getValue() == null) {
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
final EdmProperty edmProperty = path.isEmpty() ? null :
((UriResourceProperty) resourceParts.get(resourceParts.size() - 1)).getProperty();
final EdmType type = edmProperty == null ?
@@ -328,69 +348,82 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
final EdmReturnType returnType = resourceParts.get(0) instanceof UriResourceFunction ?
((UriResourceFunction) resourceParts.get(0)).getFunction().getReturnType() : null;
- final ODataFormat format = ODataFormat.fromContentType(contentType);
- ODataSerializer serializer = odata.createSerializer(format);
final ExpandOption expand = uriInfo.getExpandOption();
final SelectOption select = uriInfo.getSelectOption();
- final ContextURL contextURL = format == ODataFormat.JSON_NO_METADATA ? null :
- getContextUrl(edmEntitySet, entity, path, type, representationType, expand, select);
- switch (representationType) {
- case PRIMITIVE:
- response.setContent(serializer.primitive((EdmPrimitiveType) type, property,
- PrimitiveSerializerOptions.with().contextURL(contextURL)
- .nullable(edmProperty == null ? returnType.isNullable() : edmProperty.isNullable())
- .maxLength(edmProperty == null ? returnType.getMaxLength() : edmProperty.getMaxLength())
- .precision(edmProperty == null ? returnType.getPrecision() : edmProperty.getPrecision())
- .scale(edmProperty == null ? returnType.getScale() : edmProperty.getScale())
- .unicode(edmProperty == null ? null : edmProperty.isUnicode())
- .build()).getContent());
- break;
- case COMPLEX:
- response.setContent(serializer.complex(serviceMetadata, (EdmComplexType) type, property,
- ComplexSerializerOptions.with().contextURL(contextURL)
- .expand(expand).select(select)
- .build()).getContent());
- break;
- case COLLECTION_PRIMITIVE:
- response.setContent(serializer.primitiveCollection((EdmPrimitiveType) type, property,
- PrimitiveSerializerOptions.with().contextURL(contextURL)
- .nullable(edmProperty == null ? returnType.isNullable() : edmProperty.isNullable())
- .maxLength(edmProperty == null ? returnType.getMaxLength() : edmProperty.getMaxLength())
- .precision(edmProperty == null ? returnType.getPrecision() : edmProperty.getPrecision())
- .scale(edmProperty == null ? returnType.getScale() : edmProperty.getScale())
- .unicode(edmProperty == null ? null : edmProperty.isUnicode())
- .build()).getContent());
- break;
- case COLLECTION_COMPLEX:
- response.setContent(serializer.complexCollection(serviceMetadata, (EdmComplexType) type, property,
- ComplexSerializerOptions.with().contextURL(contextURL)
- .expand(expand).select(select)
- .build()).getContent());
- break;
- default:
- break;
- }
- response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ final ODataFormat format = ODataFormat.fromContentType(contentType);
+ final SerializerResult result = serializeProperty(entity, edmEntitySet, path, property, edmProperty,
+ type, returnType, representationType, format, expand, select);
+ response.setContent(result.getContent());
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
}
+ if (entity != null && entity.getETag() != null) {
+ response.setHeader(HttpHeader.ETAG, entity.getETag());
+ }
+ }
+ }
+
+ private void updateProperty(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
+ final ContentType requestFormat, final ContentType responseFormat, final RepresentationType representationType)
+ throws ODataApplicationException, DeserializerException, SerializerException {
+ final UriInfoResource resource = uriInfo.asUriInfoResource();
+ validatePath(resource);
+ final EdmEntitySet edmEntitySet = getEdmEntitySet(resource);
+
+ Entity entity = readEntity(uriInfo);
+ checkChangePreconditions(entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
+
+ final List<UriResource> resourceParts = resource.getUriResourceParts();
+ final List<String> path = getPropertyPath(resourceParts, 0);
+ final EdmProperty edmProperty = ((UriResourceProperty) resourceParts.get(resourceParts.size() - 1))
+ .getProperty();
+
+ checkRequestFormat(requestFormat);
+ final Property changedProperty = odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
+ .property(request.getBody(), edmProperty).getProperty();
+ if (changedProperty.isNull() && !edmProperty.isNullable()) {
+ throw new ODataApplicationException("Not nullable.", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
+ }
+
+ Property property = getPropertyData(entity, path);
+
+ dataProvider.updateProperty(edmProperty, property, changedProperty, request.getMethod() == HttpMethod.PATCH);
+ dataProvider.updateETag(entity);
+
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ 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());
+ if (entity.getETag() != null) {
+ response.setHeader(HttpHeader.ETAG, entity.getETag());
}
}
- private void deleteProperty(final ODataResponse response, final UriInfo uriInfo) throws ODataApplicationException {
+ private void deleteProperty(final ODataRequest request, ODataResponse response, final UriInfo uriInfo)
+ throws ODataApplicationException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
validatePath(resource);
getEdmEntitySet(uriInfo); // including checks
+ Entity entity = readEntity(uriInfo);
+ checkChangePreconditions(entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
+
final List<UriResource> resourceParts = resource.getUriResourceParts();
final List<String> path = getPropertyPath(resourceParts, 0);
- final Property property = getPropertyData(readEntity(uriInfo), path);
+ Property property = getPropertyData(entity, path);
final EdmProperty edmProperty = ((UriResourceProperty) resourceParts.get(resourceParts.size() - 1))
.getProperty();
if (edmProperty.isNullable()) {
property.setValue(property.getValueType(), edmProperty.isCollection() ? Collections.emptyList() : null);
+ dataProvider.updateETag(entity);
response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
} else {
throw new ODataApplicationException("Not nullable.", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
@@ -436,6 +469,54 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
return result.toString();
}
+ private SerializerResult serializeProperty(final Entity entity, final EdmEntitySet edmEntitySet,
+ final List<String> path, final Property property, final EdmProperty edmProperty,
+ final EdmType type, final EdmReturnType returnType,
+ final RepresentationType representationType, final ODataFormat format,
+ final ExpandOption expand, final SelectOption select) throws SerializerException {
+ ODataSerializer serializer = odata.createSerializer(format);
+ final ContextURL contextURL = format == ODataFormat.JSON_NO_METADATA ? null :
+ getContextUrl(edmEntitySet, entity, path, type, representationType, expand, select);
+ SerializerResult result = null;
+ switch (representationType) {
+ case PRIMITIVE:
+ result = serializer.primitive((EdmPrimitiveType) type, property,
+ PrimitiveSerializerOptions.with().contextURL(contextURL)
+ .nullable(edmProperty == null ? returnType.isNullable() : edmProperty.isNullable())
+ .maxLength(edmProperty == null ? returnType.getMaxLength() : edmProperty.getMaxLength())
+ .precision(edmProperty == null ? returnType.getPrecision() : edmProperty.getPrecision())
+ .scale(edmProperty == null ? returnType.getScale() : edmProperty.getScale())
+ .unicode(edmProperty == null ? null : edmProperty.isUnicode())
+ .build());
+ break;
+ case COMPLEX:
+ result = serializer.complex(serviceMetadata, (EdmComplexType) type, property,
+ ComplexSerializerOptions.with().contextURL(contextURL)
+ .expand(expand).select(select)
+ .build());
+ break;
+ case COLLECTION_PRIMITIVE:
+ result = serializer.primitiveCollection((EdmPrimitiveType) type, property,
+ PrimitiveSerializerOptions.with().contextURL(contextURL)
+ .nullable(edmProperty == null ? returnType.isNullable() : edmProperty.isNullable())
+ .maxLength(edmProperty == null ? returnType.getMaxLength() : edmProperty.getMaxLength())
+ .precision(edmProperty == null ? returnType.getPrecision() : edmProperty.getPrecision())
+ .scale(edmProperty == null ? returnType.getScale() : edmProperty.getScale())
+ .unicode(edmProperty == null ? null : edmProperty.isUnicode())
+ .build());
+ break;
+ case COLLECTION_COMPLEX:
+ result = serializer.complexCollection(serviceMetadata, (EdmComplexType) type, property,
+ ComplexSerializerOptions.with().contextURL(contextURL)
+ .expand(expand).select(select)
+ .build());
+ break;
+ default:
+ break;
+ }
+ return result;
+ }
+
private ContextURL getContextUrl(final EdmEntitySet entitySet, final Entity entity, final List<String> path,
final EdmType type, final RepresentationType representationType,
final ExpandOption expand, final SelectOption select) throws SerializerException {
@@ -455,7 +536,7 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
}
@Override
- public void readPrimitiveValue(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
+ public void readPrimitiveValue(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
final ContentType contentType) throws ODataApplicationException, SerializerException {
final UriInfoResource resource = uriInfo.asUriInfoResource();
validateOptions(resource);
@@ -466,6 +547,12 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
final List<String> path = getPropertyPath(resourceParts, 1);
final Entity entity = readEntity(uriInfo);
+ if (entity != null && entity.getETag() != null) {
+ checkReadPreconditions(entity.getETag(),
+ request.getHeaders(HttpHeader.IF_MATCH),
+ request.getHeaders(HttpHeader.IF_NONE_MATCH));
+ }
+
final Property property = entity == null ?
getPropertyData(dataProvider.readFunctionPrimitiveComplex(((UriResourceFunction) resourceParts.get(0))
.getFunction(),
@@ -496,6 +583,9 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor
response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
}
+ if (entity != null && entity.getETag() != null) {
+ response.setHeader(HttpHeader.ETAG, entity.getETag());
+ }
}
private void validatePath(final UriInfoResource uriInfo) throws ODataApplicationException {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/7ad5b0fb/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
index e5991bd..3f5c7bb 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
@@ -18,19 +18,21 @@
*/
package org.apache.olingo.server.tecsvc.processor;
+import java.util.Collection;
import java.util.List;
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;
import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.EtagInformation;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ServiceMetadata;
@@ -218,12 +220,49 @@ public abstract class TechnicalProcessor implements Processor {
}
}
- protected EdmAction checkBoundAndExtractAction(final UriInfo uriInfo) throws ODataApplicationException {
+ protected void blockBoundActions(final UriInfo uriInfo) throws ODataApplicationException {
final List<UriResource> uriResourceParts = uriInfo.asUriInfoResource().getUriResourceParts();
- if (uriResourceParts.size() > 1) {
+ if (uriResourceParts.size() > 1
+ && uriResourceParts.get(uriResourceParts.size() - 1) instanceof UriResourceAction) {
throw new ODataApplicationException("Bound actions are not supported yet.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}
- return ((UriResourceAction) uriResourceParts.get(0)).getAction();
+ }
+
+ protected void checkRequestFormat(final ContentType requestFormat) throws ODataApplicationException {
+ if (requestFormat == null) {
+ throw new ODataApplicationException("The content type has not been set in the request.",
+ HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
+ }
+ }
+
+ protected void checkReadPreconditions(final String eTag,
+ final Collection<String> ifMatchHeaders, final Collection<String> ifNoneMatchHeaders)
+ throws ODataApplicationException {
+ if (eTag != null) {
+ final EtagInformation ifMatch = odata.createEtagInformation(ifMatchHeaders);
+ if (!ifMatch.isMatchedBy(eTag) && !ifMatch.getEtags().isEmpty()) {
+ throw new ODataApplicationException("The If-Match precondition is not fulfilled.",
+ HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), Locale.ROOT);
+ }
+ if (odata.createEtagInformation(ifNoneMatchHeaders).isMatchedBy(eTag)) {
+ throw new ODataApplicationException("The entity has not been modified.",
+ HttpStatusCode.NOT_MODIFIED.getStatusCode(), Locale.ROOT);
+ }
+ }
+ }
+
+ protected void checkChangePreconditions(final String eTag,
+ final Collection<String> ifMatchHeaders, final Collection<String> ifNoneMatchHeaders)
+ throws ODataApplicationException {
+ if (eTag != null) {
+ final EtagInformation ifMatch = odata.createEtagInformation(ifMatchHeaders);
+ final EtagInformation ifNoneMatch = odata.createEtagInformation(ifNoneMatchHeaders);
+ if (!ifMatch.isMatchedBy(eTag) && !ifMatch.getEtags().isEmpty()
+ || ifNoneMatch.isMatchedBy(eTag)) {
+ throw new ODataApplicationException("The preconditions are not fulfilled.",
+ HttpStatusCode.PRECONDITION_FAILED.getStatusCode(), Locale.ROOT);
+ }
+ }
}
}