From afebbbbb679a9ee985180717106a7ace8f54b051 Mon Sep 17 00:00:00 2001 From: Ramesh Reddy Date: Fri, 26 Sep 2014 13:24:57 -0500 Subject: [PATCH 1/2] OLINGO-444, OLINGO-445: Adding support for addressing a individual property (primitive, complex) and aslo ability to retrive the bare value using Signed-off-by: Michael Bolz --- .../server/api/processor/EntityProcessor.java | 14 ++ .../api/processor/EntitySetProcessor.java | 2 +- .../api/serializer/ODataSerializer.java | 12 ++ .../olingo/server/core/ODataHandler.java | 26 ++- .../serializer/ODataXmlSerializerImpl.java | 10 + .../serializer/json/ODataJsonSerializer.java | 122 ++++++++--- .../serializer/utils/ContextURLBuilder.java | 11 +- .../tecsvc/processor/TechnicalProcessor.java | 71 ++++++- .../olingo/server/core/ODataHandlerTest.java | 75 ++++++- .../json/ODataJsonSerializerTest.java | 195 +++++++++++++----- 10 files changed, 441 insertions(+), 97 deletions(-) diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java index a277fa91f..daccae4ca 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java @@ -36,4 +36,18 @@ public interface EntityProcessor extends Processor { * @param requestedContentType - requested content type after content negotiation */ void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format); + + /** + * Reads primitive property from entity. + * If the property is single-valued and has the null value, the service responds with 204 No Content. + * If the property is not available, for example due to permissions, the service responds with 404 Not Found + * @param request - OData request object containing raw HTTP information + * @param response - OData response object for collecting response data + * @param uriInfo - information of a parsed OData URI + * @param format - requested content type after content negotiation + * @param value - true if only value of property requested through $value, + * false when individual property read with metadata + */ + void readEntityProperty(ODataRequest request, ODataResponse response, + UriInfo uriInfo, ContentType format, boolean value); } diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntitySetProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntitySetProcessor.java index e23823ca2..eb36ea4fe 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntitySetProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntitySetProcessor.java @@ -30,7 +30,7 @@ public interface EntitySetProcessor extends Processor { /** * Reads entities data from persistence and puts serialized content and status into the response. - * + * * @param request - OData request object containing raw HTTP information * @param response - OData response object for collecting response data * @param uriInfo - information of a parsed OData URI diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java index 8d11ee443..4fe93ec11 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java @@ -22,8 +22,10 @@ import java.io.InputStream; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; +import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; @@ -55,6 +57,16 @@ public interface ODataSerializer { */ InputStream entity(EdmEntitySet edmEntitySet, Entity entity, ODataSerializerOptions options) throws ODataSerializerException; + + /** + * Writes entity data into an InputStream. + * @param edmProperty property definition + * @param property property value + * @param value when true send bare value of property, false metadata is also included + * @param options options for the serializer + */ + InputStream entityProperty(EdmProperty edmProperty, Property property, + boolean value, ODataSerializerOptions options) throws ODataSerializerException; /** * Writes entity-set data into an InputStream. diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java index fed47a76f..7a5831fb9 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java @@ -44,6 +44,7 @@ import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourcePartTyped; +import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.core.uri.parser.Parser; import org.apache.olingo.server.core.uri.parser.UriParserException; import org.apache.olingo.server.core.uri.parser.UriParserSemanticException; @@ -230,7 +231,30 @@ public class ODataHandler { case count: if (request.getMethod().equals(HttpMethod.GET)) { EntitySetProcessor cp = selectProcessor(EntitySetProcessor.class); - cp.countEntitySet(request, response, uriInfo); + cp.countEntitySet(request, response, uriInfo); + } else { + throw new ODataHandlerException("not implemented", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + break; + case primitiveProperty: + case complexProperty: + if (request.getMethod().equals(HttpMethod.GET)) { + EntityProcessor ep = selectProcessor(EntityProcessor.class); + + requestedContentType = + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, ep, EntityProcessor.class); + + ep.readEntityProperty(request, response, uriInfo, requestedContentType, false); + } else { + throw new ODataHandlerException("not implemented", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + break; + case value: + if (request.getMethod().equals(HttpMethod.GET)) { + EntityProcessor ep = selectProcessor(EntityProcessor.class); + ep.readEntityProperty(request, response, uriInfo, requestedContentType, true); } else { throw new ODataHandlerException("not implemented", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java index 580833a7a..9588619e0 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java @@ -26,8 +26,10 @@ import javax.xml.stream.XMLStreamWriter; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; +import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.ODataSerializerException; @@ -106,4 +108,12 @@ public class ODataXmlSerializerImpl implements ODataSerializer { final ExpandOption expand, final SelectOption select) throws ODataSerializerException { return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select); } + + @Override + public InputStream entityProperty(EdmProperty edmProperty, Property property, + boolean value, ODataSerializerOptions options) + throws ODataSerializerException{ + throw new ODataSerializerException("error serialization not implemented for XML format", + ODataSerializerException.MessageKeys.NOT_IMPLEMENTED); + } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java index 1d5e54984..46cc6ff1d 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java @@ -133,15 +133,13 @@ public class ODataJsonSerializer implements ODataSerializer { try { JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); json.writeStartObject(); - if (format != ODataFormat.JSON_NO_METADATA) { - if (options == null || options.getContextURL() == null) { - throw new ODataSerializerException("ContextURL null!", - ODataSerializerException.MessageKeys.NO_CONTEXT_URL); - } else { - json.writeStringField(Constants.JSON_CONTEXT, - ContextURLBuilder.create(options.getContextURL()).toASCIIString()); - } + + final ContextURL contextURL = checkContextURL(options); + if (contextURL != null) { + json.writeStringField(Constants.JSON_CONTEXT, + ContextURLBuilder.create(contextURL).toASCIIString()); } + if (options != null && options.getCount() != null && options.getCount().getValue() && entitySet.getCount() != null) { json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount()); @@ -163,11 +161,7 @@ public class ODataJsonSerializer implements ODataSerializer { @Override public InputStream entity(final EdmEntitySet edmEntitySet, final Entity entity, final ODataSerializerOptions options) throws ODataSerializerException { - final ContextURL contextURL = options == null ? null : options.getContextURL(); - if (format != ODataFormat.JSON_NO_METADATA && contextURL == null) { - throw new ODataSerializerException("ContextURL null!", - ODataSerializerException.MessageKeys.NO_CONTEXT_URL); - } + final ContextURL contextURL = checkContextURL(options); CircleStreamBuffer buffer = new CircleStreamBuffer(); try { JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); @@ -181,6 +175,19 @@ public class ODataJsonSerializer implements ODataSerializer { return buffer.getInputStream(); } + private ContextURL checkContextURL(final ODataSerializerOptions options) + throws ODataSerializerException { + ContextURL contextURL = options == null ? null : options.getContextURL(); + if (format != ODataFormat.JSON_NO_METADATA && contextURL == null) { + throw new ODataSerializerException("ContextURL null!", + ODataSerializerException.MessageKeys.NO_CONTEXT_URL); + } + if (format == ODataFormat.JSON_NO_METADATA) { + contextURL = null; + } + return contextURL; + } + protected void writeEntitySet(final EdmEntityType entityType, final EntitySet entitySet, final ExpandOption expand, final SelectOption select, final JsonGenerator json) throws IOException, ODataSerializerException { @@ -288,24 +295,30 @@ public class ODataJsonSerializer implements ODataSerializer { json.writeNull(); } } else { - try { - if (edmProperty.isCollection()) { - writeCollection(edmProperty, property, selectedPaths, json); - } else if (edmProperty.isPrimitive()) { - writePrimitive(edmProperty, property, json); - } else if (property.isLinkedComplex()) { - writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json); - } else if (property.isComplex()) { - writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json); - } else { - throw new ODataSerializerException("Property type not yet supported!", - ODataSerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName()); - } - } catch (final EdmPrimitiveTypeException e) { - throw new ODataSerializerException("Wrong value for property!", e, - ODataSerializerException.MessageKeys.WRONG_PROPERTY_VALUE, - edmProperty.getName(), property.getValue().toString()); + writePropertyValue(edmProperty, property, selectedPaths, json); + } + } + + private void writePropertyValue(final EdmProperty edmProperty, + final Property property, final Set> selectedPaths, + final JsonGenerator json) throws IOException, ODataSerializerException { + try { + if (edmProperty.isCollection()) { + writeCollection(edmProperty, property, selectedPaths, json); + } else if (edmProperty.isPrimitive()) { + writePrimitive(edmProperty, property, json); + } else if (property.isLinkedComplex()) { + writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json); + } else if (property.isComplex()) { + writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json); + } else { + throw new ODataSerializerException("Property type not yet supported!", + ODataSerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName()); } + } catch (final EdmPrimitiveTypeException e) { + throw new ODataSerializerException("Wrong value for property!", e, + ODataSerializerException.MessageKeys.WRONG_PROPERTY_VALUE, + edmProperty.getName(), property.getValue().toString()); } } @@ -378,8 +391,15 @@ public class ODataJsonSerializer implements ODataSerializer { protected void writeComplexValue(final EdmProperty edmProperty, final List properties, final Set> selectedPaths, JsonGenerator json) throws IOException, EdmPrimitiveTypeException, ODataSerializerException { - final EdmComplexType type = (EdmComplexType) edmProperty.getType(); json.writeStartObject(); + writeProperyValues(edmProperty, properties, selectedPaths, json); + json.writeEndObject(); + } + + private void writeProperyValues(final EdmProperty edmProperty, + final List properties, final Set> selectedPaths, + JsonGenerator json) throws IOException, ODataSerializerException { + final EdmComplexType type = (EdmComplexType) edmProperty.getType(); for (final String propertyName : type.getPropertyNames()) { final Property property = findProperty(propertyName, properties); if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) { @@ -388,7 +408,6 @@ public class ODataJsonSerializer implements ODataSerializer { json); } } - json.writeEndObject(); } private Property findProperty(final String propertyName, final List properties) { @@ -405,4 +424,43 @@ public class ODataJsonSerializer implements ODataSerializer { final ExpandOption expand, final SelectOption select) throws ODataSerializerException { return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select); } + + @Override + public InputStream entityProperty(EdmProperty edmProperty, + Property property, boolean value, ODataSerializerOptions options) + throws ODataSerializerException { + final ContextURL contextURL = checkContextURL(options); + CircleStreamBuffer buffer = new CircleStreamBuffer(); + try { + JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); + if (value) { + // this is always primitive + writePropertyValue(edmProperty, property, null, json); + } else { + json.writeStartObject(); + if (format != ODataFormat.JSON_NO_METADATA) { + if (contextURL != null) { + json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString()); + } + } + if (property.isPrimitive() && property.isNull()) { + throw new ODataSerializerException("Property value can not be null", + ODataSerializerException.MessageKeys.NULL_INPUT); + } else if (property.isComplex() && !property.isNull()) { + writeProperyValues(edmProperty, property.asComplex(), null, json); + } else if (property.isLinkedComplex() && !property.isNull()) { + writeProperyValues(edmProperty, property.asLinkedComplex().getValue(), null, json); + } else { + json.writeFieldName(Constants.VALUE); + writePropertyValue(edmProperty, property, null, json); + } + json.writeEndObject(); + } + json.close(); + } catch (final IOException e) { + throw new ODataSerializerException("An I/O exception occurred.", e, + ODataSerializerException.MessageKeys.IO_EXCEPTION); + } + return buffer.getInputStream(); + } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java index a9c1315cc..86b29c620 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java @@ -19,13 +19,19 @@ package org.apache.olingo.server.core.serializer.utils; import java.net.URI; + import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.core.Encoder; +/** + * Builder to build a context URL (as defined in the + * protocol specification). + */ public final class ContextURLBuilder { - public static final URI create(final ContextURL contextURL) { + public static URI create(final ContextURL contextURL) { StringBuilder result = new StringBuilder(); if (contextURL.getServiceRoot() != null) { result.append(contextURL.getServiceRoot()); @@ -43,6 +49,9 @@ public final class ContextURLBuilder { if (contextURL.getSelectList() != null) { result.append('(').append(contextURL.getSelectList()).append(')'); } + if (contextURL.getNavOrPropertyPath() != null) { + result.append('/').append(contextURL.getNavOrPropertyPath()); + } if (contextURL.isReference()) { if (contextURL.getEntitySetOrSingletonOrType() != null) { throw new IllegalArgumentException("ContextURL: $ref with Entity Set"); 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 c8de54738..274b98801 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 @@ -22,8 +22,10 @@ import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.data.ContextURL.Suffix; +import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; @@ -41,6 +43,7 @@ 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.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind; @@ -50,6 +53,9 @@ import java.io.ByteArrayInputStream; import java.util.List; import java.util.Locale; +/** + * Technical Processor which provides current implemented processor functionality. + */ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { private OData odata; @@ -84,7 +90,7 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { response.setContent(serializer.entitySet(edmEntitySet, entitySet, ODataSerializerOptions.with() .contextURL(format == ODataFormat.JSON_NO_METADATA ? null : - getContextUrl(serializer, edmEntitySet, false, expand, select)) + getContextUrl(serializer, edmEntitySet, false, expand, select, null)) .count(uriInfo.getCountOption()) .expand(expand).select(select) .build())); @@ -120,7 +126,7 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { response.setContent(serializer.entity(edmEntitySet, entity, ODataSerializerOptions.with() .contextURL(format == ODataFormat.JSON_NO_METADATA ? null : - getContextUrl(serializer, edmEntitySet, true, expand, select)) + getContextUrl(serializer, edmEntitySet, true, expand, select, null)) .count(uriInfo.getCountOption()) .expand(expand).select(select) .build())); @@ -142,9 +148,9 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { EntitySet entitySet = null; final UriInfoResource uriResource = uriInfo.asUriInfoResource(); final List resourceParts = uriResource.getUriResourceParts(); - if(isCount(resourceParts)) { + if (isCount(resourceParts)) { int pos = resourceParts.size() - 2; - if(pos >= 0) { + if (pos >= 0) { final UriResourceEntitySet ur = (UriResourceEntitySet) uriResource.getUriResourceParts().get(pos); entitySet = readEntitySetInternal(ur.getEntitySet(), true); @@ -165,7 +171,7 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { } private boolean isCount(List resourceParts) { - if(resourceParts.isEmpty()) { + if (resourceParts.isEmpty()) { return false; } UriResource part = resourceParts.get(resourceParts.size() - 1); @@ -180,7 +186,7 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { boolean withCount) throws DataProvider.DataProviderException { EntitySet entitySet = dataProvider.readAll(edmEntitySet); // TODO: set count (correctly) and next link - if(withCount && entitySet.getCount() == null) { + if (withCount && entitySet.getCount() == null) { entitySet.setCount(entitySet.getEntities().size()); } // @@ -225,9 +231,58 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { private ContextURL getContextUrl(final ODataSerializer serializer, final EdmEntitySet entitySet, final boolean isSingleEntity, - final ExpandOption expand, final SelectOption select) throws ODataSerializerException { + final ExpandOption expand, final SelectOption select, final String navOrPropertyPath) + throws ODataSerializerException { + return ContextURL.with().entitySet(entitySet) .selectList(serializer.buildContextURLSelectList(entitySet, expand, select)) - .suffix(isSingleEntity ? Suffix.ENTITY : null).build(); + .suffix(isSingleEntity ? Suffix.ENTITY : null) + .navOrPropertyPath(navOrPropertyPath) + .build(); + } + + @Override + public void readEntityProperty(ODataRequest request, + ODataResponse response, UriInfo uriInfo, ContentType contentType, boolean value) { + + if (!validateOptions(uriInfo.asUriInfoResource())) { + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); + return; + } + try { + final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource()); + final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet); + if (entity == null) { + response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); + } else { + UriResourceProperty uriProperty = (UriResourceProperty) uriInfo + .getUriResourceParts().get(uriInfo.getUriResourceParts().size() - 1); + EdmProperty edmProperty = uriProperty.getProperty(); + Property property = entity.getProperty(edmProperty.getName()); + if (property == null) { + response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); + } else { + if (property.getValue() == null) { + response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode()); + } else { + final ODataFormat format = ODataFormat.fromContentType(contentType); + ODataSerializer serializer = odata.createSerializer(format); + response.setContent(serializer.entityProperty(edmProperty, property, value, + ODataSerializerOptions.with() + .contextURL(format == ODataFormat.JSON_NO_METADATA ? null : + getContextUrl(serializer, edmEntitySet, true, null, null, edmProperty.getName())) + .build())); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString()); + } + } + } + } catch (final DataProvider.DataProviderException e) { + response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode()); + } catch (final ODataSerializerException e) { + response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode()); + } catch (final ODataApplicationException e) { + response.setStatusCode(e.getStatusCode()); + } } } diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java index b30ec60f2..50113a046 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java @@ -28,6 +28,7 @@ import java.util.Arrays; import org.apache.commons.io.IOUtils; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; +import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.http.HttpContentType; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpMethod; @@ -39,6 +40,7 @@ import org.apache.olingo.server.api.processor.EntitySetProcessor; import org.apache.olingo.server.api.processor.MetadataProcessor; import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Before; import org.junit.Test; @@ -215,7 +217,7 @@ public class ODataHandlerTest { assertNotNull(response); assertEquals(HttpStatusCode.NOT_ACCEPTABLE.getStatusCode(), response.getStatusCode()); } - + @Test public void testContentNegotiationNotSupported2() { ODataRequest request = new ODataRequest(); @@ -252,14 +254,13 @@ public class ODataHandlerTest { handler.register(processor); ODataResponse response = handler.process(request); - assertNotNull(response); Mockito.verify(processor).countEntitySet( Mockito.eq(request), Mockito.any(ODataResponse.class), Mockito.any(UriInfo.class)); - } - + } + @Test public void testCountWithNavigation() throws Exception { ODataRequest request = new ODataRequest(); @@ -271,11 +272,73 @@ public class ODataHandlerTest { handler.register(processor); ODataResponse response = handler.process(request); - assertNotNull(response); Mockito.verify(processor).countEntitySet( Mockito.eq(request), Mockito.any(ODataResponse.class), Mockito.any(UriInfo.class)); - } + } + + @Test + public void testAddressPrimitiveProperty() throws Exception { + ODataRequest request = new ODataRequest(); + + request.setMethod(HttpMethod.GET); + request.setRawODataPath("ESAllPrim/PropertyInt16"); + + EntityProcessor processor = mock(EntityProcessor.class); + handler.register(processor); + + ODataResponse response = handler.process(request); + assertNotNull(response); + + Mockito.verify(processor).readEntityProperty( + Mockito.any(ODataRequest.class), + Mockito.any(ODataResponse.class), + Mockito.any(UriInfo.class), + Mockito.any(ContentType.class), + Mockito.eq(false)); + } + + @Test + public void testAddressPrimitivePropertyValue() throws Exception { + ODataRequest request = new ODataRequest(); + + request.setMethod(HttpMethod.GET); + request.setRawODataPath("ESAllPrim/PropertyInt16/$value"); + + EntityProcessor processor = mock(EntityProcessor.class); + handler.register(processor); + + ODataResponse response = handler.process(request); + assertNotNull(response); + + Mockito.verify(processor).readEntityProperty( + Mockito.any(ODataRequest.class), + Mockito.any(ODataResponse.class), + Mockito.any(UriInfo.class), + Mockito.any(ContentType.class), + Mockito.eq(true)); + } + + @Test + public void testAddressComplexProperty() throws Exception { + ODataRequest request = new ODataRequest(); + + request.setMethod(HttpMethod.GET); + request.setRawODataPath("ESMixPrimCollComp/PropertyComp"); + + EntityProcessor processor = mock(EntityProcessor.class); + handler.register(processor); + + ODataResponse response = handler.process(request); + assertNotNull(response); + + Mockito.verify(processor).readEntityProperty( + Mockito.any(ODataRequest.class), + Mockito.any(ODataResponse.class), + Mockito.any(UriInfo.class), + Mockito.any(ContentType.class), + Mockito.eq(false)); + } } diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java index 83e21734b..06504806d 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java @@ -29,10 +29,13 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmElement; import org.apache.olingo.commons.api.edm.EdmEntityContainer; import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.format.ODataFormat; +import org.apache.olingo.commons.core.data.PropertyImpl; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.ODataSerializerException; @@ -42,6 +45,7 @@ import org.apache.olingo.server.api.uri.queryoption.ExpandItem; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectItem; import org.apache.olingo.server.api.uri.queryoption.SelectOption; +import org.apache.olingo.server.core.edm.provider.EdmPropertyImpl; import org.apache.olingo.server.core.serializer.ExpandSelectMock; import org.apache.olingo.server.tecsvc.data.DataProvider; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; @@ -134,9 +138,9 @@ public class ODataJsonSerializerTest { Assert.fail("Expected exception not thrown!"); } catch (final ODataSerializerException e) { Assert.assertEquals(ODataSerializerException.MessageKeys.WRONG_PROPERTY_VALUE, e.getMessageKey()); - final String message = e.getLocalizedMessage(); - Assert.assertThat(message, CoreMatchers.containsString("PropertyInt16")); - Assert.assertThat(message, CoreMatchers.containsString("false")); + final String message = e.getLocalizedMessage(); + Assert.assertThat(message, CoreMatchers.containsString("PropertyInt16")); + Assert.assertThat(message, CoreMatchers.containsString("false")); } } @@ -391,10 +395,10 @@ public class ODataJsonSerializerTest { .build()); final String resultString = IOUtils.toString(result); Assert.assertEquals("{" - + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp/PropertyString)\"," - + "\"value\":[" - + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 1\"}}}," - + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 2\"}}}]}", + + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp/PropertyString)\"," + + "\"value\":[" + + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 1\"}}}," + + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 2\"}}}]}", resultString); } @@ -414,10 +418,10 @@ public class ODataJsonSerializerTest { .select(select) .build())); Assert.assertEquals("{" - + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp)\"," - + "\"value\":[" - + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":123,\"PropertyString\":\"String 1\"}}}," - + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":987,\"PropertyString\":\"String 2\"}}}]}", + + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp)\"," + + "\"value\":[" + + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":123,\"PropertyString\":\"String 1\"}}}," + + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":987,\"PropertyString\":\"String 2\"}}}]}", resultString); } @@ -434,24 +438,24 @@ public class ODataJsonSerializerTest { .build()); final String resultString = IOUtils.toString(result); Assert.assertEquals("{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\"," - + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," - + "\"NavPropertyETAllPrimOne\":{" - + "\"PropertyInt16\":32767," - + "\"PropertyString\":\"First Resource - positive values\"," - + "\"PropertyBoolean\":true," - + "\"PropertyByte\":255," - + "\"PropertySByte\":127," - + "\"PropertyInt32\":2147483647," - + "\"PropertyInt64\":9223372036854775807," - + "\"PropertySingle\":1.79E20," - + "\"PropertyDouble\":-1.79E19," - + "\"PropertyDecimal\":34," - + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," - + "\"PropertyDate\":\"2012-12-03\"," - + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," - + "\"PropertyDuration\":\"PT6S\"," - + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," - + "\"PropertyTimeOfDay\":\"03:26:05\"}}", + + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," + + "\"NavPropertyETAllPrimOne\":{" + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte\":255," + + "\"PropertySByte\":127," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"}}", resultString); } @@ -473,9 +477,9 @@ public class ODataJsonSerializerTest { .expand(expand) .build())); Assert.assertEquals("{" - + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimOne(PropertyDate))/$entity\"," - + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," - + "\"NavPropertyETAllPrimOne\":{\"PropertyDate\":\"2012-12-03\"}}", + + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimOne(PropertyDate))/$entity\"," + + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," + + "\"NavPropertyETAllPrimOne\":{\"PropertyDate\":\"2012-12-03\"}}", resultString); } @@ -500,10 +504,10 @@ public class ODataJsonSerializerTest { .select(select) .build())); Assert.assertEquals("{" - + "\"@odata.context\":\"$metadata#ESAllPrim(PropertySByte)/$entity\"," - + "\"PropertySByte\":127," - + "\"NavPropertyETTwoPrimOne\":{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}," - + "\"NavPropertyETTwoPrimMany\":[{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"}]}", + + "\"@odata.context\":\"$metadata#ESAllPrim(PropertySByte)/$entity\"," + + "\"PropertySByte\":127," + + "\"NavPropertyETTwoPrimOne\":{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}," + + "\"NavPropertyETTwoPrimMany\":[{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"}]}", resultString); } @@ -526,9 +530,9 @@ public class ODataJsonSerializerTest { .select(select) .build())); Assert.assertEquals("{" - + "\"@odata.context\":\"$metadata#ESAllPrim(PropertyTimeOfDay)/$entity\"," - + "\"PropertyTimeOfDay\":\"23:49:14\"," - + "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}", + + "\"@odata.context\":\"$metadata#ESAllPrim(PropertyTimeOfDay)/$entity\"," + + "\"PropertyTimeOfDay\":\"23:49:14\"," + + "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}", resultString); } @@ -555,15 +559,110 @@ public class ODataJsonSerializerTest { .expand(expand) .build())); Assert.assertEquals("{" - + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\"," - + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"," - + "\"NavPropertyETAllPrimMany\":[" - + "{\"PropertyInt32\":-2147483648,\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}," - + "{\"PropertyInt32\":0,\"NavPropertyETTwoPrimOne\":null," - + "\"NavPropertyETTwoPrimMany\":[" - + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}," - + "{\"PropertyInt16\":-32766,\"PropertyString\":\"Test String3\"}," - + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}", + + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\"," + + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"," + + "\"NavPropertyETAllPrimMany\":[" + + "{\"PropertyInt32\":-2147483648,\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}," + + "{\"PropertyInt32\":0,\"NavPropertyETTwoPrimOne\":null," + + "\"NavPropertyETTwoPrimMany\":[" + + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}," + + "{\"PropertyInt16\":-32766,\"PropertyString\":\"Test String3\"}," + + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}", + resultString); + } + + @Test + public void individualPrimitiveProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntitySet entitySet = data.readAll(edmEntitySet); + + EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString"); + Entity entity = entitySet.getEntities().get(0); + + InputStream result = serializer + .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"), false, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySetOrSingletonOrType("Edm.String") + .build()) + .build()); + final String resultString = IOUtils.toString(result); + Assert.assertEquals("{" + + "\"@odata.context\":\"$metadata#Edm.String\"," + + "\"value\":\"First Resource - positive values\"}", + resultString); + } + + @Test(expected = ODataSerializerException.class) + public void individualPrimitivePropertyNull() throws Exception { + PropertyImpl property = new PropertyImpl("Edm.String", "PropertyString", ValueType.PRIMITIVE, null); + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString"); + InputStream result = serializer + .entityProperty((EdmProperty) edmElement, property, false, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySetOrSingletonOrType("Edm.String") + .build()) + .build()); + } + + @Test + public void individualPrimitivePropertyArray() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final EntitySet entitySet = data.readAll(edmEntitySet); + + EdmElement edmElement = edmEntitySet.getEntityType().getProperty("CollPropertyString"); + Entity entity = entitySet.getEntities().get(0); + + InputStream result = serializer + .entityProperty((EdmProperty) edmElement, entity.getProperty("CollPropertyString"), false, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySetOrSingletonOrType("Collection(Edm.String)") + .build()) + .build()); + final String resultString = IOUtils.toString(result); + Assert.assertEquals("{" + + "\"@odata.context\":\"$metadata#Collection%28Edm.String%29\"," + + "\"value\":[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]}", + resultString); + } + + @Test + public void individualPrimitivePropertyValue() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntitySet entitySet = data.readAll(edmEntitySet); + + EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString"); + Entity entity = entitySet.getEntities().get(0); + + InputStream result = serializer + .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"), true, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESAllPrim(1)") + .navOrPropertyPath("PropertyString") + .build()) + .build()); + final String resultString = IOUtils.toString(result); + Assert.assertEquals("\"First Resource - positive values\"", resultString); + } + + @Test + public void individualComplexProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EntitySet entitySet = data.readAll(edmEntitySet); + + EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyComp"); + Entity entity = entitySet.getEntities().get(0); + + InputStream result = serializer + .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyComp"), false, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESMixPrimCollComp.PropertyComp") + .build()) + .build()); + final String resultString = IOUtils.toString(result); + Assert.assertEquals("{" + + "\"@odata.context\":\"$metadata#ESMixPrimCollComp.PropertyComp\"," + + "\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"}", resultString); } } From 1971a90c799aea076328d95612e2294666a278c6 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Thu, 2 Oct 2014 14:44:00 +0200 Subject: [PATCH 2/2] [OLINGO-444] Introduced PropertyProcessor and adapted related classes --- .../server/api/processor/EntityProcessor.java | 17 +--- .../api/processor/PropertyProcessor.java | 62 ++++++++++++++ .../api/serializer/ODataSerializer.java | 5 +- .../olingo/server/core/ODataHandler.java | 23 +++--- .../serializer/ODataXmlSerializerImpl.java | 3 +- .../serializer/json/ODataJsonSerializer.java | 47 +++++------ .../tecsvc/processor/TechnicalProcessor.java | 80 +++++++++++++++---- .../olingo/server/core/ODataHandlerTest.java | 54 ++++++------- .../json/ODataJsonSerializerTest.java | 15 ++-- 9 files changed, 192 insertions(+), 114 deletions(-) create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java index daccae4ca..7f2e3abe9 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java @@ -29,25 +29,10 @@ import org.apache.olingo.server.api.uri.UriInfo; public interface EntityProcessor extends Processor { /** - * Reads entity data from persistency and puts serialized content and status into the response. + * Reads entity data from persistence and puts serialized content and status into the response. * @param request - OData request object containing raw HTTP information * @param response - OData response object for collecting response data * @param uriInfo - information of a parsed OData URI - * @param requestedContentType - requested content type after content negotiation */ void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format); - - /** - * Reads primitive property from entity. - * If the property is single-valued and has the null value, the service responds with 204 No Content. - * If the property is not available, for example due to permissions, the service responds with 404 Not Found - * @param request - OData request object containing raw HTTP information - * @param response - OData response object for collecting response data - * @param uriInfo - information of a parsed OData URI - * @param format - requested content type after content negotiation - * @param value - true if only value of property requested through $value, - * false when individual property read with metadata - */ - void readEntityProperty(ODataRequest request, ODataResponse response, - UriInfo uriInfo, ContentType format, boolean value); } diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java new file mode 100644 index 000000000..31ff2b1a1 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java @@ -0,0 +1,62 @@ +/* + * 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.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.serializer.ODataSerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling a property of an entity. + */ +public interface PropertyProcessor extends Processor { + + /** + * Reads primitive or complex property from entity. + * If the property is single-valued and has the null value, the service responds with 204 No Content. + * If the property is not available, for example due to permissions, the service responds with 404 Not Found + * + * @param request - OData request object containing raw HTTP information + * @param response - OData response object for collecting response data + * @param uriInfo - information of a parsed OData URI + * @param format - requested content type after content negotiation + * @throws ODataApplicationException if service implementation encounters a failure + * @throws ODataSerializerException if serialization failed + */ + void readProperty(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format) + throws ODataApplicationException, ODataSerializerException; + + /** + * Reads value for primitive property from entity. + * If the property is single-valued and has the null value, the service responds with 204 No Content. + * If the property is not available, for example due to permissions, the service responds with 404 Not Found + * + * @param request - OData request object containing raw HTTP information + * @param response - OData response object for collecting response data + * @param uriInfo - information of a parsed OData URI + * @param format - requested content type after content negotiation + * @throws ODataApplicationException if service implementation encounters a failure + * @throws ODataSerializerException if serialization failed + */ + void readPropertyValue(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format) + throws ODataApplicationException, ODataSerializerException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java index 4fe93ec11..57e0014fa 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java @@ -62,11 +62,10 @@ public interface ODataSerializer { * Writes entity data into an InputStream. * @param edmProperty property definition * @param property property value - * @param value when true send bare value of property, false metadata is also included * @param options options for the serializer */ - InputStream entityProperty(EdmProperty edmProperty, Property property, - boolean value, ODataSerializerOptions options) throws ODataSerializerException; + InputStream entityProperty(EdmProperty edmProperty, Property property, ODataSerializerOptions options) + throws ODataSerializerException; /** * Writes entity-set data into an InputStream. diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java index 7a5831fb9..827dfd8f6 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java @@ -33,18 +33,11 @@ import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.ODataTranslatedException; -import org.apache.olingo.server.api.processor.DefaultProcessor; -import org.apache.olingo.server.api.processor.EntitySetProcessor; -import org.apache.olingo.server.api.processor.EntityProcessor; -import org.apache.olingo.server.api.processor.ExceptionProcessor; -import org.apache.olingo.server.api.processor.MetadataProcessor; -import org.apache.olingo.server.api.processor.Processor; -import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; +import org.apache.olingo.server.api.processor.*; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourcePartTyped; -import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.core.uri.parser.Parser; import org.apache.olingo.server.core.uri.parser.UriParserException; import org.apache.olingo.server.core.uri.parser.UriParserSemanticException; @@ -166,7 +159,7 @@ public class ODataHandler { } private void handleResourceDispatching(final ODataRequest request, final ODataResponse response, - final UriInfo uriInfo) throws ODataTranslatedException { + final UriInfo uriInfo) throws ODataTranslatedException, ODataApplicationException { int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1; UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex); ContentType requestedContentType = null; @@ -240,12 +233,12 @@ public class ODataHandler { case primitiveProperty: case complexProperty: if (request.getMethod().equals(HttpMethod.GET)) { - EntityProcessor ep = selectProcessor(EntityProcessor.class); + PropertyProcessor ep = selectProcessor(PropertyProcessor.class); requestedContentType = - ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, ep, EntityProcessor.class); + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, ep, PropertyProcessor.class); - ep.readEntityProperty(request, response, uriInfo, requestedContentType, false); + ep.readProperty(request, response, uriInfo, requestedContentType); } else { throw new ODataHandlerException("not implemented", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); @@ -253,8 +246,10 @@ public class ODataHandler { break; case value: if (request.getMethod().equals(HttpMethod.GET)) { - EntityProcessor ep = selectProcessor(EntityProcessor.class); - ep.readEntityProperty(request, response, uriInfo, requestedContentType, true); + PropertyProcessor ep = selectProcessor(PropertyProcessor.class); + requestedContentType = + ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, ep, PropertyProcessor.class); + ep.readPropertyValue(request, response, uriInfo, requestedContentType); } else { throw new ODataHandlerException("not implemented", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java index 9588619e0..3220ce1f7 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java @@ -111,8 +111,7 @@ public class ODataXmlSerializerImpl implements ODataSerializer { @Override public InputStream entityProperty(EdmProperty edmProperty, Property property, - boolean value, ODataSerializerOptions options) - throws ODataSerializerException{ + ODataSerializerOptions options) throws ODataSerializerException{ throw new ODataSerializerException("error serialization not implemented for XML format", ODataSerializerException.MessageKeys.NOT_IMPLEMENTED); } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java index 46cc6ff1d..e588448c3 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java @@ -392,13 +392,13 @@ public class ODataJsonSerializer implements ODataSerializer { final Set> selectedPaths, JsonGenerator json) throws IOException, EdmPrimitiveTypeException, ODataSerializerException { json.writeStartObject(); - writeProperyValues(edmProperty, properties, selectedPaths, json); + writePropertyValues(edmProperty, properties, selectedPaths, json); json.writeEndObject(); } - private void writeProperyValues(final EdmProperty edmProperty, - final List properties, final Set> selectedPaths, - JsonGenerator json) throws IOException, ODataSerializerException { + private void writePropertyValues(final EdmProperty edmProperty, + final List properties, final Set> selectedPaths, + JsonGenerator json) throws IOException, ODataSerializerException { final EdmComplexType type = (EdmComplexType) edmProperty.getType(); for (final String propertyName : type.getPropertyNames()) { final Property property = findProperty(propertyName, properties); @@ -427,35 +427,30 @@ public class ODataJsonSerializer implements ODataSerializer { @Override public InputStream entityProperty(EdmProperty edmProperty, - Property property, boolean value, ODataSerializerOptions options) + Property property, ODataSerializerOptions options) throws ODataSerializerException { final ContextURL contextURL = checkContextURL(options); CircleStreamBuffer buffer = new CircleStreamBuffer(); try { JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); - if (value) { - // this is always primitive - writePropertyValue(edmProperty, property, null, json); - } else { - json.writeStartObject(); - if (format != ODataFormat.JSON_NO_METADATA) { - if (contextURL != null) { - json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString()); - } + json.writeStartObject(); + if (format != ODataFormat.JSON_NO_METADATA) { + if (contextURL != null) { + json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString()); } - if (property.isPrimitive() && property.isNull()) { - throw new ODataSerializerException("Property value can not be null", - ODataSerializerException.MessageKeys.NULL_INPUT); - } else if (property.isComplex() && !property.isNull()) { - writeProperyValues(edmProperty, property.asComplex(), null, json); - } else if (property.isLinkedComplex() && !property.isNull()) { - writeProperyValues(edmProperty, property.asLinkedComplex().getValue(), null, json); - } else { - json.writeFieldName(Constants.VALUE); - writePropertyValue(edmProperty, property, null, json); - } - json.writeEndObject(); } + if (property.isPrimitive() && property.isNull()) { + throw new ODataSerializerException("Property value can not be null", + ODataSerializerException.MessageKeys.NULL_INPUT); + } else if (property.isComplex() && !property.isNull()) { + writePropertyValues(edmProperty, property.asComplex(), null, json); + } else if (property.isLinkedComplex() && !property.isNull()) { + writePropertyValues(edmProperty, property.asLinkedComplex().getValue(), null, json); + } else { + json.writeFieldName(Constants.VALUE); + writePropertyValue(edmProperty, property, null, json); + } + json.writeEndObject(); json.close(); } catch (final IOException e) { throw new ODataSerializerException("An I/O exception occurred.", e, 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 274b98801..99f64ef3d 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 @@ -23,9 +23,7 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.data.ContextURL.Suffix; import org.apache.olingo.commons.api.data.Property; -import org.apache.olingo.commons.api.edm.Edm; -import org.apache.olingo.commons.api.edm.EdmEntitySet; -import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.*; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; @@ -36,27 +34,25 @@ import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.processor.EntitySetProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; +import org.apache.olingo.server.api.processor.PropertyProcessor; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.ODataSerializerException; import org.apache.olingo.server.api.serializer.ODataSerializerOptions; -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.UriResourceEntitySet; -import org.apache.olingo.server.api.uri.UriResourceProperty; +import org.apache.olingo.server.api.uri.*; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind; import org.apache.olingo.server.tecsvc.data.DataProvider; import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Locale; /** * Technical Processor which provides current implemented processor functionality. */ -public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { +public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor { private OData odata; private DataProvider dataProvider; @@ -213,14 +209,25 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { private EdmEntitySet getEdmEntitySet(final UriInfoResource uriInfo) throws ODataApplicationException { final List resourcePaths = uriInfo.getUriResourceParts(); - if (resourcePaths.size() != 1) { - throw new ODataApplicationException("Invalid resource path.", - HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); - } + // first must be entity set if (!(resourcePaths.get(0) instanceof UriResourceEntitySet)) { throw new ODataApplicationException("Invalid resource type.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } + + List subResPaths = resourcePaths.subList(1, resourcePaths.size()); + for (UriResource subResPath : subResPaths) { + UriResourceKind kind = subResPath.getKind(); + if(kind != UriResourceKind.primitiveProperty + && kind != UriResourceKind.complexProperty + && kind != UriResourceKind.count + && kind != UriResourceKind.value) { + throw new ODataApplicationException("Invalid resource type.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + } + + // final UriResourceEntitySet uriResource = (UriResourceEntitySet) resourcePaths.get(0); if (uriResource.getTypeFilterOnCollection() != null || uriResource.getTypeFilterOnEntry() != null) { throw new ODataApplicationException("Type filters are not supported.", @@ -242,8 +249,8 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { } @Override - public void readEntityProperty(ODataRequest request, - ODataResponse response, UriInfo uriInfo, ContentType contentType, boolean value) { + public void readProperty(ODataRequest request, + ODataResponse response, UriInfo uriInfo, ContentType contentType) { if (!validateOptions(uriInfo.asUriInfoResource())) { response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); @@ -267,7 +274,7 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { } else { final ODataFormat format = ODataFormat.fromContentType(contentType); ODataSerializer serializer = odata.createSerializer(format); - response.setContent(serializer.entityProperty(edmProperty, property, value, + response.setContent(serializer.entityProperty(edmProperty, property, ODataSerializerOptions.with() .contextURL(format == ODataFormat.JSON_NO_METADATA ? null : getContextUrl(serializer, edmEntitySet, true, null, null, edmProperty.getName())) @@ -285,4 +292,45 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor { response.setStatusCode(e.getStatusCode()); } } + + @Override + public void readPropertyValue(ODataRequest request, ODataResponse response, + UriInfo uriInfo, ContentType contentType) { + + if (!validateOptions(uriInfo.asUriInfoResource())) { + response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); + return; + } + try { + final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource()); + final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet); + if (entity == null) { + response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); + } else { + UriResourceProperty uriProperty = (UriResourceProperty) uriInfo + .getUriResourceParts().get(uriInfo.getUriResourceParts().size() - 2); + EdmProperty edmProperty = uriProperty.getProperty(); + Property property = entity.getProperty(edmProperty.getName()); + if (property == null || property.getValue() == null) { + response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode()); + } else { + final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType(); + final String value = type.valueToString(property.getValue(), + edmProperty.isNullable(), edmProperty.getMaxLength(), + edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode()); + response.setContent(new ByteArrayInputStream(value.getBytes("UTF-8"))); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.TEXT_PLAIN.toContentTypeString()); + } + } + } catch (final DataProvider.DataProviderException e) { + response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode()); + } catch (final EdmPrimitiveTypeException e) { + response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode()); + } catch (final UnsupportedEncodingException e) { + response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode()); + } catch (final ODataApplicationException e) { + response.setStatusCode(e.getStatusCode()); + } + } } diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java index 50113a046..1ae9ea391 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java @@ -36,11 +36,8 @@ import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; -import org.apache.olingo.server.api.processor.EntitySetProcessor; -import org.apache.olingo.server.api.processor.MetadataProcessor; -import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; +import org.apache.olingo.server.api.processor.*; import org.apache.olingo.server.api.uri.UriInfo; -import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Before; import org.junit.Test; @@ -262,7 +259,7 @@ public class ODataHandlerTest { } @Test - public void testCountWithNavigation() throws Exception { + public void dispatchCountWithNavigation() throws Exception { ODataRequest request = new ODataRequest(); request.setMethod(HttpMethod.GET); @@ -280,65 +277,62 @@ public class ODataHandlerTest { } @Test - public void testAddressPrimitiveProperty() throws Exception { + public void dispatchAddressPrimitiveProperty() throws Exception { ODataRequest request = new ODataRequest(); request.setMethod(HttpMethod.GET); request.setRawODataPath("ESAllPrim/PropertyInt16"); - EntityProcessor processor = mock(EntityProcessor.class); + PropertyProcessor processor = mock(PropertyProcessor.class); handler.register(processor); ODataResponse response = handler.process(request); assertNotNull(response); - Mockito.verify(processor).readEntityProperty( - Mockito.any(ODataRequest.class), - Mockito.any(ODataResponse.class), - Mockito.any(UriInfo.class), - Mockito.any(ContentType.class), - Mockito.eq(false)); + Mockito.verify(processor).readProperty( + Mockito.any(ODataRequest.class), + Mockito.any(ODataResponse.class), + Mockito.any(UriInfo.class), + Mockito.any(ContentType.class)); } @Test - public void testAddressPrimitivePropertyValue() throws Exception { + public void dispatchAddressPrimitivePropertyValue() throws Exception { ODataRequest request = new ODataRequest(); request.setMethod(HttpMethod.GET); request.setRawODataPath("ESAllPrim/PropertyInt16/$value"); - EntityProcessor processor = mock(EntityProcessor.class); + PropertyProcessor processor = mock(PropertyProcessor.class); handler.register(processor); ODataResponse response = handler.process(request); assertNotNull(response); - Mockito.verify(processor).readEntityProperty( - Mockito.any(ODataRequest.class), - Mockito.any(ODataResponse.class), - Mockito.any(UriInfo.class), - Mockito.any(ContentType.class), - Mockito.eq(true)); + Mockito.verify(processor).readPropertyValue( + Mockito.any(ODataRequest.class), + Mockito.any(ODataResponse.class), + Mockito.any(UriInfo.class), + Mockito.any(ContentType.class)); } @Test - public void testAddressComplexProperty() throws Exception { + public void dispatchAddressComplexProperty() throws Exception { ODataRequest request = new ODataRequest(); request.setMethod(HttpMethod.GET); request.setRawODataPath("ESMixPrimCollComp/PropertyComp"); - EntityProcessor processor = mock(EntityProcessor.class); + PropertyProcessor processor = mock(PropertyProcessor.class); handler.register(processor); ODataResponse response = handler.process(request); assertNotNull(response); - Mockito.verify(processor).readEntityProperty( - Mockito.any(ODataRequest.class), - Mockito.any(ODataResponse.class), - Mockito.any(UriInfo.class), - Mockito.any(ContentType.class), - Mockito.eq(false)); + Mockito.verify(processor).readProperty( + Mockito.any(ODataRequest.class), + Mockito.any(ODataResponse.class), + Mockito.any(UriInfo.class), + Mockito.any(ContentType.class)); } -} +} \ No newline at end of file diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java index 06504806d..250cabb79 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java @@ -45,12 +45,12 @@ import org.apache.olingo.server.api.uri.queryoption.ExpandItem; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectItem; import org.apache.olingo.server.api.uri.queryoption.SelectOption; -import org.apache.olingo.server.core.edm.provider.EdmPropertyImpl; import org.apache.olingo.server.core.serializer.ExpandSelectMock; import org.apache.olingo.server.tecsvc.data.DataProvider; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.hamcrest.CoreMatchers; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; @@ -580,7 +580,7 @@ public class ODataJsonSerializerTest { Entity entity = entitySet.getEntities().get(0); InputStream result = serializer - .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"), false, + .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"), ODataSerializerOptions.with() .contextURL(ContextURL.with().entitySetOrSingletonOrType("Edm.String") .build()) @@ -598,7 +598,7 @@ public class ODataJsonSerializerTest { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString"); InputStream result = serializer - .entityProperty((EdmProperty) edmElement, property, false, + .entityProperty((EdmProperty) edmElement, property, ODataSerializerOptions.with() .contextURL(ContextURL.with().entitySetOrSingletonOrType("Edm.String") .build()) @@ -614,7 +614,7 @@ public class ODataJsonSerializerTest { Entity entity = entitySet.getEntities().get(0); InputStream result = serializer - .entityProperty((EdmProperty) edmElement, entity.getProperty("CollPropertyString"), false, + .entityProperty((EdmProperty) edmElement, entity.getProperty("CollPropertyString"), ODataSerializerOptions.with() .contextURL(ContextURL.with().entitySetOrSingletonOrType("Collection(Edm.String)") .build()) @@ -627,6 +627,7 @@ public class ODataJsonSerializerTest { } @Test + @Ignore("Serialization of value of primitive property is not done by json serializer") public void individualPrimitivePropertyValue() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); final EntitySet entitySet = data.readAll(edmEntitySet); @@ -635,9 +636,9 @@ public class ODataJsonSerializerTest { Entity entity = entitySet.getEntities().get(0); InputStream result = serializer - .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"), true, + .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"), ODataSerializerOptions.with() - .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESAllPrim(1)") + .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESAllPrim(0)") .navOrPropertyPath("PropertyString") .build()) .build()); @@ -654,7 +655,7 @@ public class ODataJsonSerializerTest { Entity entity = entitySet.getEntities().get(0); InputStream result = serializer - .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyComp"), false, + .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyComp"), ODataSerializerOptions.with() .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESMixPrimCollComp.PropertyComp") .build())