diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java index a99f02c0d..39eae0ee5 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/EntityWithStreamITCase.java @@ -109,4 +109,127 @@ public class EntityWithStreamITCase extends AbstractParamTecSvcITCase { link.getType().name()); assertEquals("eTag", link.getMediaETag()); } + + /** + * These tests can be uncommented once client API's are fixed for V4.01 + */ + /*@Test + public void readExpandOfStreamPropOnComplexProperty() { + ODataEntityRequest request = getClient().getRetrieveRequestFactory() + .getEntityRequest(getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("ESStreamOnComplexProp").appendKeySegment(7) + .expand("PropertyCompWithStream/PropertyStream," + + "PropertyEntityStream," + + "PropertyCompWithStream/NavPropertyETStreamOnComplexPropOne($expand=PropertyStream)," + + "PropertyCompWithStream/NavPropertyETStreamOnComplexPropMany/$count") + .build()); + + assertNotNull(request); + setCookieHeader(request); + request.addCustomHeader("OData-Version", "4.01"); + request.setAccept("application/json;odata.metadata=full"); + + final ODataRetrieveResponse response = request.execute(); + saveCookieHeader(response); + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + assertEquals("application/json; odata.metadata=full", response.getContentType()); + + final ClientEntity entity = response.getBody(); + assertNotNull(entity); + + assertNotNull(entity.getProperties()); + assertEquals(10, entity.getProperties().size()); + + ClientProperty property = entity.getProperty("PropertyEntityStream"); + assertNotNull(property); + assertEquals(String.valueOf("eTag"), + entity.getProperty("PropertyEntityStream@mediaEtag").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("image/jpeg"), + entity.getProperty("PropertyEntityStream@mediaContentType").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("\ufffdioz\ufffd\"\ufffd"), + entity.getProperty("PropertyEntityStream").getPrimitiveValue().toValue()); + + property = entity.getProperty("PropertyCompWithStream"); + assertNotNull(property); + assertEquals(String.valueOf("eTag"), + property.getComplexValue().get("PropertyStream@mediaEtag").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("image/jpeg"), + property.getComplexValue().get("PropertyStream@mediaContentType").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("\ufffdioz\ufffd\"\ufffd"), + property.getComplexValue().get("PropertyStream").getPrimitiveValue().toValue()); + ClientComplexValue complexValue = property.getComplexValue(); + assertNotNull(complexValue); + + assertNotNull(complexValue.get("NavPropertyETStreamOnComplexPropOne@navigationLink")); + assertNotNull(complexValue.get("NavPropertyETStreamOnComplexPropMany@navigationLink")); + + property = complexValue.get("NavPropertyETStreamOnComplexPropOne"); + assertNotNull(property); + assertNotNull(property.getComplexValue()); + assertEquals(String.valueOf("eTag"), + property.getComplexValue().get("PropertyStream@mediaEtag").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("image/jpeg"), + property.getComplexValue().get("PropertyStream@mediaContentType").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("\ufffdioz\ufffd\"\ufffd"), + property.getComplexValue().get("PropertyStream").getPrimitiveValue().toValue()); + + property = complexValue.get("NavPropertyETStreamOnComplexPropMany@count"); + assertNotNull(property); + assertEquals(Integer.parseInt("2"), property.getPrimitiveValue().toValue()); + } + + @Test + public void readExpandOfStreamPropOnComplexPropertyWithRef() { + ODataEntityRequest request = getClient().getRetrieveRequestFactory() + .getEntityRequest(getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("ESStreamOnComplexProp").appendKeySegment(7) + .expand("PropertyCompWithStream/NavPropertyETStreamOnComplexPropMany/$ref") + .build()); + + assertNotNull(request); + setCookieHeader(request); + request.addCustomHeader("OData-Version", "4.01"); + request.setAccept("application/json;odata.metadata=full"); + + final ODataRetrieveResponse response = request.execute(); + saveCookieHeader(response); + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + assertEquals("application/json; odata.metadata=full", response.getContentType()); + + final ClientEntity entity = response.getBody(); + assertNotNull(entity); + + assertNotNull(entity.getProperties()); + assertEquals(9, entity.getProperties().size()); + + ClientProperty property = entity.getProperty("PropertyEntityStream"); + assertNull(property); + assertEquals(String.valueOf("eTag"), + entity.getProperty("PropertyEntityStream@mediaEtag").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("image/jpeg"), + entity.getProperty("PropertyEntityStream@mediaContentType").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("http://mediaserver:1234/editLink"), + entity.getProperty("PropertyEntityStream@mediaEditLink").getPrimitiveValue().toValue()); + + property = entity.getProperty("PropertyCompWithStream"); + assertNotNull(property); + assertEquals(String.valueOf("eTag"), + property.getComplexValue().get("PropertyStream@mediaEtag").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("image/jpeg"), + property.getComplexValue().get("PropertyStream@mediaContentType").getPrimitiveValue().toValue()); + assertEquals(String.valueOf("http://mediaserver:1234/editLink"), + property.getComplexValue().get("PropertyStream@mediaEditLink").getPrimitiveValue().toValue()); + ClientComplexValue complexValue = property.getComplexValue(); + assertNotNull(complexValue); + + assertNotNull(complexValue.get("NavPropertyETStreamOnComplexPropOne@navigationLink")); + assertNotNull(complexValue.get("NavPropertyETStreamOnComplexPropMany@navigationLink")); + + property = complexValue.get("NavPropertyETStreamOnComplexPropMany"); + assertNotNull(property); + assertEquals(2, property.getCollectionValue().size()); + for (ClientValue value : property.getCollectionValue()) { + assertEquals("id", value.asComplex().getAnnotations().get(0).getTerm()); + } + }*/ } diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java index abdb2781c..697c97008 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java @@ -250,6 +250,66 @@ public class BasicStreamITCase extends AbstractBaseTestITCase { assertFalse(content.contains("\"@odata.count\":504")); } + @Test + public void expandStreamPropOnComplexTypeJson() throws Exception { + URL url = new URL(SERVICE_URI + "ESStreamOnComplexProp(7)?$expand=PropertyCompWithStream/PropertyStream," + + "PropertyEntityStream,PropertyCompWithStream/NavPropertyETStreamOnComplexPropOne($expand=PropertyStream)," + + "PropertyCompWithStream/NavPropertyETStreamOnComplexPropMany/$count&$format=json"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty("OData-Version", "4.01"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE))); + + final String content = IOUtils.toString(connection.getInputStream()); + + assertTrue(content.contains("\"NavPropertyETStreamOnComplexPropOne\":{" + + "\"PropertyInt16\":7," + + "\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyStream\":\"\ufffdioz\ufffd\\\"\ufffd\"}")); + assertTrue(content.contains("\"NavPropertyETStreamOnComplexPropMany@count\":2")); + assertTrue(content.contains("\"PropertyCompWithStream\":{" + + "\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyStream\":\"\ufffdioz\ufffd\\\"\ufffd\"," + + "\"PropertyComp\":{\"PropertyInt16\":333,\"PropertyString\":\"TEST123\"}")); + assertFalse(content.contains("\"PropertyInt16\":7," + + "\"PropertyInt32\":10," + + "\"PropertyEntityStream@mediaEtag\":\"eTag\"," + + "\"PropertyEntityStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyEntityStream\":\"ufffdioz\ufffd\\\"\ufffd\"")); + } + + @Test + public void expandStreamPropOnComplexTypeWithRefJson() throws Exception { + URL url = new URL(SERVICE_URI + "ESStreamOnComplexProp(7)?$expand=" + + "PropertyCompWithStream/NavPropertyETStreamOnComplexPropMany/$ref&$format=json"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty("OData-Version", "4.01"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE))); + + final String content = IOUtils.toString(connection.getInputStream()); + + assertTrue(content.contains("\"PropertyInt16\":7," + + "\"PropertyInt32\":10,\"PropertyEntityStream@mediaEtag\":\"eTag\"," + + "\"PropertyEntityStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyCompWithStream\":{\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyComp\":{\"PropertyInt16\":333,\"PropertyString\":\"TEST123\"}," + + "\"NavPropertyETStreamOnComplexPropMany\":[" + + "{\"@id\":\"ESWithStream(32767)\"}," + + "{\"@id\":\"ESWithStream(7)\"}]}")); + } + @Override protected ODataClient getClient() { return null; 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 9f9ab9780..43222106d 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 @@ -451,7 +451,6 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } writeProperties(metadata, resolvedType, entity.getProperties(), select, json, entity, expand); - writeExpandedStreamProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, name, json); writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, name, json); writeOperations(entity.getOperations(), json); } @@ -612,22 +611,6 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } } - protected void writeExpandedStreamProperties(final ServiceMetadata metadata, - final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth, - final Set ancestors, final String name, final JsonGenerator json) - throws SerializerException, IOException, DecoderException { - - if (ExpandSelectHelper.hasExpand(expand)) { - final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); - for (final String propertyName : type.getPropertyNames()) { - EdmProperty edmProperty = (EdmProperty) type.getProperty(propertyName); - if(isStreamProperty(edmProperty) ){ - writeExpandedStreamProperty(expand, propertyName, edmProperty, linked, expandAll, json); - } - } - } - } - private void writeExpandedStreamProperty(ExpandOption expand, String propertyName, EdmProperty edmProperty, Linked linked, ExpandItem expandAll, JsonGenerator json) throws SerializerException, DecoderException, IOException { @@ -637,8 +620,20 @@ public class ODataJsonSerializer extends AbstractODataSerializer { throw new SerializerException("Expand not supported for Stream Property Type!", SerializerException.MessageKeys.UNSUPPORTED_OPERATION_TYPE, "expand", edmProperty.getName()); } - Entity entity = (Entity) linked; - final Property property = (Property) entity.getProperty(propertyName); + Property property = null; + if (linked instanceof Entity) { + Entity entity = (Entity) linked; + property = (Property) entity.getProperty(propertyName); + } else if (linked instanceof ComplexValue) { + List properties = ((ComplexValue) linked).getValue(); + for (Property prop : properties) { + if (prop.getName().equals(propertyName)) { + property = prop; + break; + } + } + } + if((property == null || property.isNull()) && edmProperty.isNullable() == Boolean.FALSE ){ throw new SerializerException("Non-nullable property not present!", SerializerException.MessageKeys.MISSING_PROPERTY, edmProperty.getName()); @@ -781,6 +776,15 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writePrimitive((EdmPrimitiveType) type, property, edmProperty.isNullable(), edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(), json); + // If there is expand on a stream property + if (isStreamProperty(edmProperty) && null != expand) { + final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); + try { + writeExpandedStreamProperty(expand, property.getName(), edmProperty, linked, expandAll, json); + } catch (DecoderException e) { + throw new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + } + } } } else if (property.isComplex()) { if (edmProperty.isCollection()) { @@ -1091,6 +1095,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { throw new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); } } + private Property findProperty(final String propertyName, final List properties) { for (final Property property : properties) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java index 99cb32bef..f92476834 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java @@ -249,7 +249,13 @@ public abstract class ExpandSelectHelper { continue; } final List resourceParts = item.getResourcePath().getUriResourceParts(); - final UriResource resource = resourceParts.get(0); + UriResource resource = null; + if (resourceParts.get(resourceParts.size() - 1) instanceof UriResourceRef || + resourceParts.get(resourceParts.size() - 1) instanceof UriResourceCount) { + resource = resourceParts.get(resourceParts.size() - 2); + } else { + resource = resourceParts.get(resourceParts.size() - 1); + } if ((resource instanceof UriResourceNavigation && propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) || resource instanceof UriResourceProperty diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java index 94b16cf47..cd6fdf031 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java @@ -99,6 +99,7 @@ public class DataCreator { data.put("ETCont", createETCont(edm, odata)); data.put("ETBaseCont", createETBaseCont(edm, odata)); data.put("ETTwoCont", createETTwoCont(edm, odata)); + data.put("ESStreamOnComplexProp", createETStreamOnComplexProp(edm, odata)); linkSINav(data); linkESTwoPrim(data); @@ -116,8 +117,109 @@ public class DataCreator { linkPropMixPrimCompInESCompMixPrimCollCompToETTwoKeyNav(data); linkPropMixPrimCompInESCompMixPrimCollCompToCollETTwoKeyNav(data); linkColPropCompInESMixPrimCollCompToETTwoKeyNav(data); + linkETStreamOnComplexPropWithNavigationProperty(data); + linkETStreamOnComplexPropWithNavigationPropertyMany(data); + } + + private void linkETStreamOnComplexPropWithNavigationProperty(Map data) { + EntityCollection collection = data.get("ESStreamOnComplexProp"); + Entity entity = collection.getEntities().get(1); + ComplexValue complexValue = entity.getProperties().get(3).asComplex(); + final List esStreamTargets = data.get("ESWithStream").getEntities(); + Link link = new Link(); + link.setRel(Constants.NS_NAVIGATION_LINK_REL + "NavPropertyETStreamOnComplexPropOne"); + link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE); + link.setTitle("NavPropertyETStreamOnComplexPropOne"); + link.setInlineEntity(esStreamTargets.get(1)); + link.setHref(esStreamTargets.get(1).getId().toASCIIString()); + complexValue.getNavigationLinks().add(link); } + private void linkETStreamOnComplexPropWithNavigationPropertyMany( + Map data) { + EntityCollection collection = data.get("ESStreamOnComplexProp"); + Entity entity = collection.getEntities().get(1); + ComplexValue complexValue = entity.getProperties().get(3).asComplex(); + final List esStreamTargets = data.get("ESWithStream").getEntities(); + Link link = new Link(); + link.setRel(Constants.NS_NAVIGATION_LINK_REL + "NavPropertyETStreamOnComplexPropMany"); + link.setType(Constants.ENTITY_SET_NAVIGATION_LINK_TYPE); + link.setTitle("NavPropertyETStreamOnComplexPropMany"); + EntityCollection target = new EntityCollection(); + target.setCount(2); + target.getEntities().addAll(Arrays.asList(esStreamTargets.get(0), esStreamTargets.get(1))); + link.setInlineEntitySet(target); + link.setHref(entity.getId().toASCIIString() + "/" + + entity.getProperties().get(3).getName() + "/" + + "NavPropertyETStreamOnComplexPropMany"); + complexValue.getNavigationLinks().add(link); + } + + private EntityCollection createETStreamOnComplexProp(Edm edm, OData odata) { + EntityCollection entityCollection = new EntityCollection(); + + Link readLink = new Link(); + readLink.setRel(Constants.NS_MEDIA_READ_LINK_REL); + readLink.setHref("readLink"); + Entity entity = new Entity(); + entity.addProperty(createPrimitive("PropertyStream", createImage("darkturquoise"))); + readLink.setInlineEntity(entity); + + Link readLink1 = new Link(); + readLink1.setRel(Constants.NS_MEDIA_READ_LINK_REL); + readLink1.setHref("readLink"); + entity = new Entity(); + entity.addProperty(createPrimitive("PropertyEntityStream", createImage("darkturquoise"))); + readLink1.setInlineEntity(entity); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE)) + .addProperty(createPrimitive("PropertyInt32", Integer.MAX_VALUE)) + .addProperty(new Property(null, "PropertyEntityStream", ValueType.PRIMITIVE, readLink1)) + .addProperty(createComplex("PropertyCompWithStream", + ComplexTypeProvider.nameCTWithStreamProp.getFullQualifiedNameAsString(), + new Property(null, "PropertyStream", ValueType.PRIMITIVE, readLink), + createComplex("PropertyComp", + ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(), + createPrimitive("PropertyInt16", (short) 333), + createPrimitive("PropertyString", "TEST123"))))); + + Link editLink = new Link(); + editLink.setRel(Constants.NS_MEDIA_EDIT_LINK_REL); + editLink.setHref("http://mediaserver:1234/editLink"); + editLink.setMediaETag("eTag"); + editLink.setType("image/jpeg"); + entity = new Entity(); + entity.addProperty(createPrimitive("PropertyStream", createImage("royalblue"))); + editLink.setInlineEntity(entity); + + Link editLink2 = new Link(); + editLink2.setRel(Constants.NS_MEDIA_EDIT_LINK_REL); + editLink2.setHref("http://mediaserver:1234/editLink"); + editLink2.setMediaETag("eTag"); + editLink2.setType("image/jpeg"); + entity = new Entity(); + entity.addProperty(createPrimitive("PropertyEntityStream", createImage("royalblue"))); + editLink2.setInlineEntity(entity); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) 7)) + .addProperty(createPrimitive("PropertyInt32", (Integer) 10)) + .addProperty(new Property(null, "PropertyEntityStream", ValueType.PRIMITIVE, editLink2)) + .addProperty(createComplex("PropertyCompWithStream", + ComplexTypeProvider.nameCTWithStreamProp.getFullQualifiedNameAsString(), + new Property(null, "PropertyStream", ValueType.PRIMITIVE, editLink), + createComplex("PropertyComp", + ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(), + createPrimitive("PropertyInt16", (short) 333), + createPrimitive("PropertyString", "TEST123"))))); + + setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETStreamOnComplexProp)); + createEntityId(edm, odata, "ESStreamOnComplexProp", entityCollection); + createOperations("ESStreamOnComplexProp", entityCollection, EntityTypeProvider.nameETStreamOnComplexProp); + return entityCollection; + } + @SuppressWarnings("unchecked") private void linkCollPropCompInESCompMixPrimCollCompToETTwoKeyNav(Map data2) { EntityCollection collection = data.get("ESCompMixPrimCollComp"); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java index 8e24965fc..e0106c35d 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java @@ -58,6 +58,8 @@ public class ComplexTypeProvider { public static final FullQualifiedName nameCTMixEnumDef = new FullQualifiedName(SchemaProvider.NAMESPACE, "CTMixEnumDef"); public static final FullQualifiedName nameCTNavCont = new FullQualifiedName(SchemaProvider.NAMESPACE, "CTNavCont"); + public static final FullQualifiedName nameCTWithStreamProp = + new FullQualifiedName(SchemaProvider.NAMESPACE, "CTWithStreamProp"); public CsdlComplexType getComplexType(final FullQualifiedName complexTypeName) throws ODataException { @@ -217,6 +219,14 @@ public class ComplexTypeProvider { PropertyProvider.collPropertyEnumString_ENString, PropertyProvider.propertyTypeDefinition_TDString, PropertyProvider.collPropertyTypeDefinition_TDString)); + } else if (complexTypeName.equals(nameCTWithStreamProp)) { + return new CsdlComplexType() + .setName("CTWithStreamProp") + .setProperties(Arrays.asList( + PropertyProvider.propertyStream, + PropertyProvider.propertyComp_CTTwoPrim)) + .setNavigationProperties(Arrays.asList(PropertyProvider.navPropertyETStreamOnComplexProp_ETStreamNav, + PropertyProvider.navPropertyETStreamOnComplexPropMany_ETStreamNav)); } return null; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java index 0ec96cac5..aed408e2a 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java @@ -705,7 +705,11 @@ public class ContainerProvider { .setPath("NavPropertyETAllPrimMany") .setTarget("ESAllPrim"))); - } + } else if (name.equals("ESStreamOnComplexProp")) { + return new CsdlEntitySet() + .setName("ESStreamOnComplexProp") + .setType(EntityTypeProvider.nameETStreamOnComplexProp); + } } return null; } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java index 079a1f8f4..06699567f 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java @@ -98,6 +98,9 @@ public class EntityTypeProvider { public static final FullQualifiedName nameETTwoCont = new FullQualifiedName(SchemaProvider.NAMESPACE, "ETTwoCont"); + public static final FullQualifiedName nameETStreamOnComplexProp = + new FullQualifiedName(SchemaProvider.NAMESPACE, "ETStreamOnComplexProp"); + public CsdlEntityType getEntityType(final FullQualifiedName entityTypeName) throws ODataException { if(entityTypeName.equals(nameETAllPrimDefaultValues)){ return new CsdlEntityType() @@ -560,6 +563,16 @@ public class EntityTypeProvider { PropertyProvider.propertyBinary, PropertyProvider.propertyDate, PropertyProvider.propertyDateTimeOffset, PropertyProvider.propertyDuration, PropertyProvider.propertyGuid, PropertyProvider.propertyTimeOfDay )); + } else if (entityTypeName.equals(nameETStreamOnComplexProp)) { + return new CsdlEntityType() + .setName("ETStreamOnComplexProp") + .setKey(Arrays.asList( + new CsdlPropertyRef().setName("PropertyInt16"))) + .setProperties(Arrays.asList( + PropertyProvider.propertyInt16_NotNullable, + PropertyProvider.propertyInt32, PropertyProvider.propertyEntityStream, + PropertyProvider.propertyCompWithStream_CTWithStreamProp + )); } return null; } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java index e74fd6d8d..4c306d312 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java @@ -667,6 +667,11 @@ public class PropertyProvider { .setType(nameStream) .setNullable(true); + public static final CsdlProperty propertyEntityStream = new CsdlProperty() + .setName("PropertyEntityStream") + .setType(nameStream) + .setNullable(true); + // Complex Properties ---------------------------------------------------------------------------------------------- public static final CsdlProperty collPropertyComp_CTPrimComp = new CsdlProperty() .setName("CollPropertyComp") @@ -1018,4 +1023,17 @@ public class PropertyProvider { .setCollection(true) .setType(EntityTypeProvider.nameETBaseCont); + public static final CsdlProperty propertyCompWithStream_CTWithStreamProp = new CsdlProperty() + .setName("PropertyCompWithStream") + .setType(ComplexTypeProvider.nameCTWithStreamProp); + + public static final CsdlNavigationProperty navPropertyETStreamOnComplexProp_ETStreamNav = new CsdlNavigationProperty() + .setName("NavPropertyETStreamOnComplexPropOne") + .setType(EntityTypeProvider.nameETStream); + + public static final CsdlNavigationProperty + navPropertyETStreamOnComplexPropMany_ETStreamNav = new CsdlNavigationProperty() + .setName("NavPropertyETStreamOnComplexPropMany") + .setType(EntityTypeProvider.nameETStream) + .setCollection(true); } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java index 72c4f2728..ba83fabad 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java @@ -90,6 +90,7 @@ public class SchemaProvider { entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETCont)); entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETBaseCont)); entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETTwoCont)); + entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETStreamOnComplexProp)); // ComplexTypes List complexTypes = new ArrayList(); @@ -113,6 +114,7 @@ public class SchemaProvider { complexTypes.add(prov.getComplexType(ComplexTypeProvider.nameCTCompCollCompAno)); complexTypes.add(prov.getComplexType(ComplexTypeProvider.nameCTTwoPrimAno)); complexTypes.add(prov.getComplexType(ComplexTypeProvider.nameCTBaseAno)); + complexTypes.add(prov.getComplexType(ComplexTypeProvider.nameCTWithStreamProp)); // Actions List actions = new ArrayList(); diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java index a89096608..859f48bb1 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java @@ -55,13 +55,17 @@ public final class ExpandSelectMock { if (edmElement.getType().getKind() == EdmTypeKind.ENTITY) { UriResourceNavigation element = Mockito.mock(UriResourceNavigation.class); Mockito.when(element.getProperty()).thenReturn((EdmNavigationProperty) edmElement); + Mockito.when(element.getSegmentValue()).thenReturn(((EdmNavigationProperty) edmElement).getName()); + Mockito.when(element.getType()).thenReturn(((EdmNavigationProperty) edmElement).getType()); elements.add(element); } else { final EdmProperty property = (EdmProperty) edmElement; UriResourceProperty element = Mockito.mock(UriResourceProperty.class); Mockito.when(element.getProperty()).thenReturn(property); + Mockito.when(element.getSegmentValue()).thenReturn(property.getName()); elements.add(element); type = property.isPrimitive() ? null : (EdmStructuredType) property.getType(); + Mockito.when(element.getType()).thenReturn(type); } } UriInfoResource resource = Mockito.mock(UriInfoResource.class); 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 e95728a42..d6a608c24 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 @@ -34,6 +34,7 @@ import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.olingo.commons.api.constants.Constantsv01; import org.apache.olingo.commons.api.data.ComplexValue; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Suffix; @@ -106,6 +107,12 @@ public class ODataJsonSerializerTest { private final ODataSerializer serializerIEEECompatible = new ODataJsonSerializer(ContentType.create(ContentType.JSON, ContentType.PARAMETER_IEEE754_COMPATIBLE, "true")); private final UriHelper helper = odata.createUriHelper(); + private final ODataSerializer serializerV401 = new ODataJsonSerializer(ContentType.JSON, new Constantsv01()); + private final ODataSerializer serializerNoMetadataV401 = + new ODataJsonSerializer(ContentType.JSON_NO_METADATA, new Constantsv01()); + private final ODataSerializer serializerFullMetadataV401 = + new ODataJsonSerializer(ContentType.JSON_FULL_METADATA, new Constantsv01()); + @Test public void entitySimple() throws Exception { @@ -2776,4 +2783,84 @@ public class ODataJsonSerializerTest { + "\"ESTwoKeyNav(PropertyInt16=1,PropertyString='2')\"," + "\"NavPropertyETMediaOne@odata.navigationLink\":\"ESMedia(2)\"}",resultString); } + + @Test + public void expandStreamPropertyOnComplex() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESStreamOnComplexProp"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + final ExpandItem expandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, + "PropertyCompWithStream", "PropertyStream"); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(expandItem)); + InputStream result = serializerV401.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESStreamOnComplexProp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\",\"PropertyInt16\":7," + + "\"PropertyInt32\":10,\"PropertyEntityStream@mediaEtag\":\"eTag\"," + + "\"PropertyEntityStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyCompWithStream\":{\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\",\"PropertyStream\":" + + "\"\ufffdioz\ufffd\\\"\ufffd\",\"PropertyComp\":{\"PropertyInt16\":333," + + "\"PropertyString\":\"TEST123\"}}}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void expandStreamPropertyOnComplexWithFullMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESStreamOnComplexProp"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + final ExpandItem expandItem1 = ExpandSelectMock.mockExpandItem(edmEntitySet, + "PropertyCompWithStream", "PropertyStream"); + final ExpandItem expandItem2 = ExpandSelectMock.mockExpandItem(edmEntitySet, + "PropertyEntityStream"); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(expandItem1, expandItem2)); + InputStream result = serializerFullMetadataV401.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESStreamOnComplexProp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@type\":\"#olingo.odata.test1.ETStreamOnComplexProp\"," + + "\"@id\":\"ESStreamOnComplexProp(7)\",\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":7,\"PropertyInt32@type\":\"#Int32\",\"PropertyInt32\":10," + + "\"PropertyEntityStream@type\":\"#Stream\",\"PropertyEntityStream@mediaEtag\":\"eTag\"," + + "\"PropertyEntityStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyEntityStream@mediaEditLink\":\"http://mediaserver:1234/editLink\"," + + "\"PropertyEntityStream\":\"\ufffdioz\ufffd\\\"\ufffd\"," + + "\"PropertyCompWithStream\":{\"@type\":\"#olingo.odata.test1.CTWithStreamProp\"," + + "\"PropertyStream@type\":\"#Stream\",\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyStream@mediaEditLink\":\"http://mediaserver:1234/editLink\"," + + "\"PropertyStream\":\"\ufffdioz\ufffd\\\"\ufffd\",\"PropertyComp\":" + + "{\"@type\":\"#olingo.odata.test1.CTTwoPrim\",\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":333,\"PropertyString\":\"TEST123\"}," + + "\"NavPropertyETStreamOnComplexPropOne@navigationLink\":\"ESWithStream(7)\"," + + "\"NavPropertyETStreamOnComplexPropMany@navigationLink\":" + + "\"ESStreamOnComplexProp(7)/PropertyCompWithStream/NavPropertyETStreamOnComplexPropMany\"}}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void expandStreamPropertyOnComplexWithNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESStreamOnComplexProp"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + final ExpandItem expandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, + "PropertyCompWithStream", "PropertyStream"); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(expandItem)); + InputStream result = serializerNoMetadataV401.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"PropertyInt16\":7,\"PropertyInt32\":10," + + "\"PropertyCompWithStream\":{\"PropertyStream\":\"\ufffdioz\ufffd\\\"\ufffd\"," + + "\"PropertyComp\":{\"PropertyInt16\":333,\"PropertyString\":\"TEST123\"}}}"; + Assert.assertEquals(expectedResult, resultString); + } } diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java index acbf2e4b7..e6ec8e188 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java @@ -191,22 +191,6 @@ public class ContextURLHelperTest { assertEquals("$metadata#ESTwoPrim(NavPropertyETAllPrimOne())", ContextURLBuilder.create(contextURL).toASCIIString()); } - - @Test - public void buildExpandWithNavigationProperty() throws Exception { - final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoPrim"); - final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList( - ExpandSelectMock.mockExpandItem(entitySet, "NavPropertyETAllPrimOne", "PropertyString"))); - final SelectItem selectItem1 = ExpandSelectMock.mockSelectItem(entitySet, "PropertyInt16"); - final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( - selectItem1)); - - final ContextURL contextURL = ContextURL.with().entitySet(entitySet) - .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), expand, select)).build(); - assertEquals("$metadata#ESTwoPrim(PropertyInt16,NavPropertyETAllPrimOne/PropertyString)", - ContextURLBuilder.create(contextURL).toASCIIString()); - } - @Test public void buildExpandSelect() throws Exception {