[OLINGO-663] Set ETags in technical service

Change-Id: I92eccdbff85fb1afcd91e609cb232f723f81580e

Signed-off-by: Christian Amend <chrisam@apache.org>
This commit is contained in:
Klaus Straubinger 2015-05-19 10:18:10 +02:00 committed by Christian Amend
parent 1a9cff2f63
commit bec8cb3b2a
5 changed files with 60 additions and 28 deletions

View File

@ -20,6 +20,7 @@ package org.apache.olingo.fit.tecsvc.client;
import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -62,6 +63,7 @@ public final class MediaITCase extends AbstractBaseTestITCase {
final ODataRetrieveResponse<InputStream> response = request.execute(); final ODataRetrieveResponse<InputStream> response = request.execute();
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
assertEquals("image/svg+xml", response.getContentType()); assertEquals("image/svg+xml", response.getContentType());
assertEquals("W/\"1\"", response.getETag());
InputStream media = response.getBody(); InputStream media = response.getBody();
assertNotNull(media); assertNotNull(media);
@ -113,6 +115,8 @@ public final class MediaITCase extends AbstractBaseTestITCase {
assertEquals(HttpStatusCode.OK.getStatusCode(), mediaResponse.getStatusCode()); assertEquals(HttpStatusCode.OK.getStatusCode(), mediaResponse.getStatusCode());
assertEquals(ContentType.TEXT_PLAIN.toContentTypeString(), mediaResponse.getContentType()); assertEquals(ContentType.TEXT_PLAIN.toContentTypeString(), mediaResponse.getContentType());
assertEquals("just a test", IOUtils.toString(mediaResponse.getBody())); assertEquals("just a test", IOUtils.toString(mediaResponse.getBody()));
assertNotNull(mediaResponse.getETag());
assertNotEquals("W/\"4\"", mediaResponse.getETag());
} }
@Test @Test

View File

@ -298,6 +298,7 @@ public class DataCreator {
createPrimitive("PropertyGuid", GUID), createPrimitive("PropertyInt16", Short.MAX_VALUE), createPrimitive("PropertyGuid", GUID), createPrimitive("PropertyInt16", Short.MAX_VALUE),
createPrimitive("PropertyInt32", Integer.MAX_VALUE), createPrimitive("PropertyInt64", Long.MAX_VALUE), createPrimitive("PropertyInt32", Integer.MAX_VALUE), createPrimitive("PropertyInt64", Long.MAX_VALUE),
createPrimitive("PropertySByte", Byte.MAX_VALUE), createPrimitive("PropertyTimeOfDay", getTime(1, 0, 1)))); createPrimitive("PropertySByte", Byte.MAX_VALUE), createPrimitive("PropertyTimeOfDay", getTime(1, 0, 1))));
entity.setETag("W/\"" + Short.MAX_VALUE + '\"');
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
entity = new Entity(); entity = new Entity();
@ -314,6 +315,7 @@ public class DataCreator {
createPrimitive("PropertyInt32", Integer.MAX_VALUE), createPrimitive("PropertyInt64", Long.MAX_VALUE), createPrimitive("PropertyInt32", Integer.MAX_VALUE), createPrimitive("PropertyInt64", Long.MAX_VALUE),
createPrimitive("PropertySByte", Byte.MAX_VALUE), createPrimitive("PropertySByte", Byte.MAX_VALUE),
createPrimitive("PropertyTimeOfDay", getTimestamp(1, 1, 1, 7, 45, 12, 765432100)))); createPrimitive("PropertyTimeOfDay", getTimestamp(1, 1, 1, 7, 45, 12, 765432100))));
entity.setETag("W/\"7\"");
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
entity = new Entity(); entity = new Entity();
@ -329,6 +331,7 @@ public class DataCreator {
createPrimitive("PropertyGuid", GUID), createPrimitive("PropertyInt16", -25), createPrimitive("PropertyGuid", GUID), createPrimitive("PropertyInt16", -25),
createPrimitive("PropertyInt32", Integer.MAX_VALUE), createPrimitive("PropertyInt64", Long.MAX_VALUE), createPrimitive("PropertyInt32", Integer.MAX_VALUE), createPrimitive("PropertyInt64", Long.MAX_VALUE),
createPrimitive("PropertySByte", Byte.MAX_VALUE), createPrimitive("PropertyTimeOfDay", getTime(13, 27, 45)))); createPrimitive("PropertySByte", Byte.MAX_VALUE), createPrimitive("PropertyTimeOfDay", getTime(13, 27, 45))));
entity.setETag("W/\"0\"");
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
return entitySet; return entitySet;
@ -463,21 +466,25 @@ public class DataCreator {
Entity entity = new Entity().addProperty(createPrimitive("PropertyInt16", 1)) Entity entity = new Entity().addProperty(createPrimitive("PropertyInt16", 1))
.addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("darkturquoise"))); .addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("darkturquoise")));
entity.setMediaContentType("image/svg+xml"); entity.setMediaContentType("image/svg+xml");
entity.setMediaETag("W/\"1\"");
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
entity = new Entity().addProperty(createPrimitive("PropertyInt16", 2)) entity = new Entity().addProperty(createPrimitive("PropertyInt16", 2))
.addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("royalblue"))); .addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("royalblue")));
entity.setMediaContentType("image/svg+xml"); entity.setMediaContentType("image/svg+xml");
entity.setMediaETag("W/\"2\"");
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
entity = new Entity().addProperty(createPrimitive("PropertyInt16", 3)) entity = new Entity().addProperty(createPrimitive("PropertyInt16", 3))
.addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("crimson"))); .addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("crimson")));
entity.setMediaContentType("image/svg+xml"); entity.setMediaContentType("image/svg+xml");
entity.setMediaETag("W/\"3\"");
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
entity = new Entity().addProperty(createPrimitive("PropertyInt16", 4)) entity = new Entity().addProperty(createPrimitive("PropertyInt16", 4))
.addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("black"))); .addProperty(createPrimitive(DataProvider.MEDIA_PROPERTY_NAME, createImage("black")));
entity.setMediaContentType("image/svg+xml"); entity.setMediaContentType("image/svg+xml");
entity.setMediaETag("W/\"4\"");
entitySet.getEntities().add(entity); entitySet.getEntities().add(entity);
return entitySet; return entitySet;

View File

@ -56,7 +56,7 @@ public class DataProvider {
protected static final String MEDIA_PROPERTY_NAME = "$value"; protected static final String MEDIA_PROPERTY_NAME = "$value";
final private Map<String, EntityCollection> data; private Map<String, EntityCollection> data;
private Edm edm; private Edm edm;
private OData odata; private OData odata;
@ -64,6 +64,14 @@ public class DataProvider {
data = new DataCreator().getData(); data = new DataCreator().getData();
} }
public void setEdm(final Edm edm) {
this.edm = edm;
}
public void setOData(final OData odata) {
this.odata = odata;
}
public EntityCollection readAll(final EdmEntitySet edmEntitySet) throws DataProviderException { public EntityCollection readAll(final EdmEntitySet edmEntitySet) throws DataProviderException {
return data.get(edmEntitySet.getName()); return data.get(edmEntitySet.getName());
} }
@ -73,9 +81,8 @@ public class DataProvider {
return entitySet == null ? null : read(edmEntitySet.getEntityType(), entitySet, keys); return entitySet == null ? null : read(edmEntitySet.getEntityType(), entitySet, keys);
} }
public Entity public Entity read(final EdmEntityType edmEntityType, final EntityCollection entitySet,
read(final EdmEntityType edmEntityType, final EntityCollection entitySet, final List<UriParameter> keys) final List<UriParameter> keys) throws DataProviderException {
throws DataProviderException {
try { try {
for (final Entity entity : entitySet.getEntities()) { for (final Entity entity : entitySet.getEntities()) {
boolean found = true; boolean found = true;
@ -134,7 +141,7 @@ public class DataProvider {
final EntityCollection entitySet = readAll(edmEntitySet); final EntityCollection entitySet = readAll(edmEntitySet);
final List<Entity> entities = entitySet.getEntities(); final List<Entity> entities = entitySet.getEntities();
final Map<String, Object> newKey = findFreeComposedKey(entities, edmEntitySet.getEntityType()); final Map<String, Object> newKey = findFreeComposedKey(entities, edmEntitySet.getEntityType());
final Entity newEntity = new Entity(); Entity newEntity = new Entity();
newEntity.setType(edmEntityType.getFullQualifiedName().getFullQualifiedNameAsString()); newEntity.setType(edmEntityType.getFullQualifiedName().getFullQualifiedNameAsString());
for (final String keyName : edmEntityType.getKeyPredicateNames()) { for (final String keyName : edmEntityType.getKeyPredicateNames()) {
newEntity.addProperty(DataCreator.createPrimitive(keyName, newKey.get(keyName))); newEntity.addProperty(DataCreator.createPrimitive(keyName, newKey.get(keyName)));
@ -226,7 +233,7 @@ public class DataProvider {
return newProperty; return newProperty;
} }
public void update(final String rawBaseUri, final EdmEntitySet edmEntitySet, final Entity entity, public void update(final String rawBaseUri, final EdmEntitySet edmEntitySet, Entity entity,
final Entity changedEntity, final boolean patch, final boolean isInsert) throws DataProviderException { final Entity changedEntity, final boolean patch, final boolean isInsert) throws DataProviderException {
final EdmEntityType entityType = edmEntitySet.getEntityType(); final EdmEntityType entityType = edmEntitySet.getEntityType();
@ -256,11 +263,15 @@ public class DataProvider {
} else { } else {
handleDeleteSingleNavigationProperties(edmEntitySet, entity, changedEntity); handleDeleteSingleNavigationProperties(edmEntitySet, entity, changedEntity);
} }
// Update the ETag if present.
if (entity.getETag() != null) {
entity.setETag("W/\"" + System.nanoTime() + "\"");
}
} }
private void handleDeleteSingleNavigationProperties(final EdmEntitySet edmEntitySet, final Entity entity, private void handleDeleteSingleNavigationProperties(final EdmEntitySet edmEntitySet, final Entity entity,
final Entity changedEntity) final Entity changedEntity) throws DataProviderException {
throws DataProviderException {
final EdmEntityType entityType = edmEntitySet.getEntityType(); final EdmEntityType entityType = edmEntitySet.getEntityType();
final List<String> navigationPropertyNames = entityType.getNavigationPropertyNames(); final List<String> navigationPropertyNames = entityType.getNavigationPropertyNames();
@ -381,8 +392,8 @@ public class DataProvider {
} }
} }
private void private void setLink(final EdmNavigationProperty navigationProperty, final Entity srcEntity,
setLink(final EdmNavigationProperty navigationProperty, final Entity srcEntity, final Entity targetEntity) { final Entity targetEntity) {
if (navigationProperty.isCollection()) { if (navigationProperty.isCollection()) {
DataCreator.setLinks(srcEntity, navigationProperty.getName(), targetEntity); DataCreator.setLinks(srcEntity, navigationProperty.getName(), targetEntity);
} else { } else {
@ -475,6 +486,7 @@ public class DataProvider {
entity.getProperties().remove(entity.getProperty(MEDIA_PROPERTY_NAME)); entity.getProperties().remove(entity.getProperty(MEDIA_PROPERTY_NAME));
entity.addProperty(DataCreator.createPrimitive(MEDIA_PROPERTY_NAME, media)); entity.addProperty(DataCreator.createPrimitive(MEDIA_PROPERTY_NAME, media));
entity.setMediaContentType(type); entity.setMediaContentType(type);
entity.setMediaETag("W/\"" + System.nanoTime() + "\"");
} }
public EntityCollection readFunctionEntitySet(final EdmFunction function, final List<UriParameter> parameters) public EntityCollection readFunctionEntitySet(final EdmFunction function, final List<UriParameter> parameters)
@ -517,20 +529,11 @@ public class DataProvider {
return ActionData.entityAction(name, actionParameters); return ActionData.entityAction(name, actionParameters);
} }
public EntityCollection public EntityCollection processActionEntityCollection(final String name,
processActionEntityCollection(final String name, final Map<String, Parameter> actionParameters) final Map<String, Parameter> actionParameters) throws DataProviderException {
throws DataProviderException {
return ActionData.entityCollectionAction(name, actionParameters); return ActionData.entityCollectionAction(name, actionParameters);
} }
public void setEdm(final Edm edm) {
this.edm = edm;
}
public void setOData(final OData odata) {
this.odata = odata;
}
public static class DataProviderException extends ODataApplicationException { public static class DataProviderException extends ODataApplicationException {
private static final long serialVersionUID = 5098059649321796156L; private static final long serialVersionUID = 5098059649321796156L;

View File

@ -220,6 +220,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
.getContent()); .getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
} }
@Override @Override
@ -230,6 +233,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
response.setContent(odata.createFixedFormatSerializer().binary(dataProvider.readMedia(entity))); response.setContent(odata.createFixedFormatSerializer().binary(dataProvider.readMedia(entity)));
response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, entity.getMediaContentType()); response.setHeader(HttpHeader.CONTENT_TYPE, entity.getMediaContentType());
if (entity.getMediaETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getMediaETag());
}
} }
@Override @Override
@ -279,6 +285,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
response.setHeader(HttpHeader.LOCATION, response.setHeader(HttpHeader.LOCATION,
request.getRawBaseUri() + '/' + odata.createUriHelper().buildCanonicalURL(edmEntitySet, entity)); request.getRawBaseUri() + '/' + odata.createUriHelper().buildCanonicalURL(edmEntitySet, entity));
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
} }
@Override @Override
@ -319,6 +328,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
.getContent()); .getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
} }
@Override @Override
@ -338,6 +350,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
.getContent()); .getContent());
response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
if (entity.getETag() != null) {
response.setHeader(HttpHeader.ETAG, entity.getETag());
}
} }
@Override @Override
@ -377,6 +392,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
.getContent()); .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()); response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
if (entityResult.getEntity().getETag() != null) {
response.setHeader(HttpHeader.ETAG, entityResult.getEntity().getETag());
}
} }
} }

View File

@ -232,6 +232,7 @@ public class ODataJsonSerializerTest {
final String resultString = IOUtils.toString(result); final String resultString = IOUtils.toString(result);
final String expectedResult = "{" final String expectedResult = "{"
+ "\"@odata.context\":\"$metadata#ESCompAllPrim/$entity\"," + "\"@odata.context\":\"$metadata#ESCompAllPrim/$entity\","
+ "\"@odata.etag\":\"W/\\\"32767\\\"\","
+ "\"PropertyInt16\":32767," + "\"PropertyInt16\":32767,"
+ "\"PropertyComp\":{" + "\"PropertyComp\":{"
+ "\"PropertyString\":\"First Resource - first\"," + "\"PropertyString\":\"First Resource - first\","
@ -322,15 +323,14 @@ public class ODataJsonSerializerTest {
@Test @Test
public void entityMedia() throws Exception { public void entityMedia() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia");
Entity entity = data.readAll(edmEntitySet).getEntities().get(0); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.setMediaETag("theMediaETag");
final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(),
entity, entity,
EntitySerializerOptions.with() EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()).getContent()); .build()).getContent());
final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia/$entity\"," final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia/$entity\","
+ "\"@odata.mediaEtag\":\"theMediaETag\",\"@odata.mediaContentType\":\"image/svg+xml\"," + "\"@odata.mediaEtag\":\"W/\\\"1\\\"\",\"@odata.mediaContentType\":\"image/svg+xml\","
+ "\"PropertyInt16\":1}"; + "\"PropertyInt16\":1}";
Assert.assertEquals(expectedResult, resultString); Assert.assertEquals(expectedResult, resultString);
} }
@ -344,10 +344,10 @@ public class ODataJsonSerializerTest {
EntityCollectionSerializerOptions.with() EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build()).build()).getContent()); .contextURL(ContextURL.with().entitySet(edmEntitySet).build()).build()).getContent());
final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia\",\"value\":[" final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia\",\"value\":["
+ "{\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":1}," + "{\"@odata.mediaEtag\":\"W/\\\"1\\\"\",\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":1},"
+ "{\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":2}," + "{\"@odata.mediaEtag\":\"W/\\\"2\\\"\",\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":2},"
+ "{\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":3}," + "{\"@odata.mediaEtag\":\"W/\\\"3\\\"\",\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":3},"
+ "{\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":4}]}"; + "{\"@odata.mediaEtag\":\"W/\\\"4\\\"\",\"@odata.mediaContentType\":\"image/svg+xml\",\"PropertyInt16\":4}]}";
Assert.assertEquals(expectedResult, resultString); Assert.assertEquals(expectedResult, resultString);
} }