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 8c60373fc..513df382d 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 @@ -64,6 +64,7 @@ import org.apache.olingo.server.api.uri.UriHelper; import org.apache.olingo.server.api.uri.queryoption.CountOption; 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.LevelsExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.core.ODataWritableContent; import org.apache.olingo.server.core.serializer.AbstractODataSerializer; @@ -73,6 +74,7 @@ import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper; import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder; import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper; import org.apache.olingo.server.core.uri.UriHelperImpl; +import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; @@ -164,10 +166,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeOperations(entitySet.getOperations(), json); json.writeFieldName(Constants.VALUE); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, false, json); + writeEntitySet(metadata, entityType, entitySet, null, null, null, false, json); } else { writeEntitySet(metadata, entityType, entitySet, - options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json); + options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), json); } writeNextLink(entitySet, json); @@ -210,10 +212,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } json.writeFieldName(Constants.VALUE); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, false, json); + writeEntitySet(metadata, entityType, entitySet, null, null, null, false, json); } else { writeEntitySet(metadata, entityType, entitySet, - options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json); + options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), json); } // next link not supported by default for streaming results // writeNextLink(entitySet, json); @@ -238,6 +240,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { JsonGenerator json = new JsonFactory().createGenerator(outputStream); writeEntity(metadata, entityType, entity, contextURL, options == null ? null : options.getExpand(), + null, options == null ? null : options.getSelect(), options == null ? false : options.getWriteOnlyReferences(), json); @@ -264,7 +267,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType, - final AbstractEntityCollection entitySet, final ExpandOption expand, final SelectOption select, + final AbstractEntityCollection entitySet, final ExpandOption expand, Integer toDepth, final SelectOption select, final boolean onlyReference, final JsonGenerator json) throws IOException, SerializerException { json.writeStartArray(); @@ -274,7 +277,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeStringField(Constants.JSON_ID, getEntityId(entity)); json.writeEndObject(); } else { - writeEntity(metadata, entityType, entity, null, expand, select, false, json); + writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, json); } } json.writeEndArray(); @@ -308,8 +311,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } public void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity, - final ContextURL contextURL, final ExpandOption expand, final SelectOption select, final boolean onlyReference, - final JsonGenerator json) + final ContextURL contextURL, final ExpandOption expand, Integer toDepth, + final SelectOption select, final boolean onlyReference, final JsonGenerator json) throws IOException, SerializerException { json.writeStartObject(); if (!isODataMetadataNone) { @@ -357,7 +360,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } writeProperties(metadata, resolvedType, entity.getProperties(), select, json); - writeNavigationProperties(metadata, resolvedType, entity, expand, json); + writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, json); writeOperations(entity.getOperations(), json); json.writeEndObject(); } @@ -442,24 +445,57 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } protected void writeNavigationProperties(final ServiceMetadata metadata, - final EdmStructuredType type, final Linked linked, final ExpandOption expand, + final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth, final JsonGenerator json) throws SerializerException, IOException { - if (ExpandSelectHelper.hasExpand(expand)) { - final boolean expandAll = ExpandSelectHelper.isExpandAll(expand); - final Set expanded = expandAll ? new HashSet() : - ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems()); + if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) { + final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); for (final String propertyName : type.getNavigationPropertyNames()) { - if (expandAll || expanded.contains(propertyName)) { + final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); + if (toDepth != null) { final EdmNavigationProperty property = type.getNavigationProperty(propertyName); final Link navigationLink = linked.getNavigationLink(property.getName()); - final ExpandItem innerOptions = expandAll ? null : - ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); - if (innerOptions != null && innerOptions.getLevelsOption() != null) { - throw new SerializerException("Expand option $levels is not supported.", - SerializerException.MessageKeys.NOT_IMPLEMENTED); - } writeExpandedNavigationProperty(metadata, property, navigationLink, - innerOptions == null ? null : innerOptions.getExpandOption(), + expand, toDepth-1, + innerOptions == null ? null : innerOptions.getSelectOption(), + innerOptions == null ? null : innerOptions.getCountOption(), + innerOptions == null ? false : innerOptions.hasCountPath(), + innerOptions == null ? false : innerOptions.isRef(), + json); + continue; + } + Integer levels = null; + if (expandAll != null || innerOptions != null) { + final EdmNavigationProperty property = type.getNavigationProperty(propertyName); + final Link navigationLink = linked.getNavigationLink(property.getName()); + ExpandOption childExpand = null; + LevelsExpandOption levelsOption = null; + if (innerOptions != null) { + levelsOption = innerOptions.getLevelsOption(); + if (levelsOption == null) { + childExpand = innerOptions.getExpandOption(); + } else { + ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl(); + expandOptionImpl.addExpandItem(innerOptions); + childExpand = expandOptionImpl; + } + } else if (expandAll != null) { + levels = 1; + levelsOption = expandAll.getLevelsOption(); + ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl(); + expandOptionImpl.addExpandItem(expandAll); + childExpand = expandOptionImpl; + } + + if (levelsOption != null) { + if (levelsOption.isMax()) { + levels = Integer.MAX_VALUE; + } else { + levels = levelsOption.getValue(); + } + } + + writeExpandedNavigationProperty(metadata, property, navigationLink, + childExpand, levels, innerOptions == null ? null : innerOptions.getSelectOption(), innerOptions == null ? null : innerOptions.getCountOption(), innerOptions == null ? false : innerOptions.hasCountPath(), @@ -484,7 +520,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { protected void writeExpandedNavigationProperty( final ServiceMetadata metadata, final EdmNavigationProperty property, final Link navigationLink, final ExpandOption innerExpand, - final SelectOption innerSelect, final CountOption innerCount, + Integer toDepth, final SelectOption innerSelect, final CountOption innerCount, final boolean writeOnlyCount, final boolean writeOnlyRef, final JsonGenerator json) throws IOException, SerializerException { @@ -508,7 +544,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeInlineCount(property.getName(), navigationLink.getInlineEntitySet().getCount(), json); } json.writeFieldName(property.getName()); - writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, + writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth, innerSelect, writeOnlyRef, json); } } @@ -518,7 +554,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeNull(); } else { writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null, - innerExpand, innerSelect, writeOnlyRef, json); + innerExpand, toDepth, innerSelect, writeOnlyRef, json); } } } @@ -847,7 +883,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeProperties(metadata, type, values, options == null ? null : options.getSelect(), json); if (!property.isNull() && property.isComplex()) { writeNavigationProperties(metadata, type, property.asComplex(), - options == null ? null : options.getExpand(), json); + options == null ? null : options.getExpand(), null, json); } json.writeEndObject(); 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 13e158f76..4424b6198 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 @@ -121,7 +121,16 @@ public abstract class ExpandSelectHelper { } return false; } - + + public static ExpandItem getExpandAll(final ExpandOption expand) { + for (final ExpandItem item : expand.getExpandItems()) { + if (item.isStar()) { + return item; + } + } + return null; + } + public static Set getExpandedPropertyNames(final List expandItems) throws SerializerException { Set expanded = new HashSet(); @@ -137,6 +146,9 @@ public abstract class ExpandSelectHelper { public static ExpandItem getExpandItem(final List expandItems, final String propertyName) { for (final ExpandItem item : expandItems) { + if (item.isStar()) { + continue; + } final UriResource resource = item.getResourcePath().getUriResourceParts().get(0); if (resource instanceof UriResourceNavigation && propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java index 47489c90c..d6de50f53 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java @@ -70,6 +70,7 @@ import org.apache.olingo.server.api.serializer.SerializerStreamResult; import org.apache.olingo.server.api.uri.queryoption.CountOption; 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.LevelsExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.core.ODataWritableContent; import org.apache.olingo.server.core.serializer.AbstractODataSerializer; @@ -77,6 +78,7 @@ import org.apache.olingo.server.core.serializer.SerializerResultImpl; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder; import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper; +import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl; public class ODataXmlSerializer extends AbstractODataSerializer { @@ -257,10 +259,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer { boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences()); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, null, writer, writeOnlyRef); + writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef); } else { writeEntitySet(metadata, entityType, entitySet, - options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef); + options.getExpand(), null, + options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef); } writer.writeEndElement(); @@ -314,10 +317,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer { boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences()); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, null, writer, writeOnlyRef); + writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef); } else { writeEntitySet(metadata, entityType, entitySet, - options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef); + options.getExpand(), null, + options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef); } writer.writeEndElement(); @@ -356,6 +360,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { writer.writeStartDocument(DEFAULT_CHARSET, "1.0"); writeEntity(metadata, entityType, entity, contextURL, options == null ? null : options.getExpand(), + null, options == null ? null : options.getSelect(), options == null ? null : options.xml10InvalidCharReplacement(), writer, true, false); @@ -397,17 +402,18 @@ public class ODataXmlSerializer extends AbstractODataSerializer { } protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType, - final AbstractEntityCollection entitySet, final ExpandOption expand, final SelectOption select, + final AbstractEntityCollection entitySet, final ExpandOption expand, + final Integer toDepth, final SelectOption select, final String xml10InvalidCharReplacement,final XMLStreamWriter writer, final boolean writeOnlyRef) throws XMLStreamException, SerializerException { for (final Entity entity : entitySet) { - writeEntity(metadata, entityType, entity, null, expand, select, + writeEntity(metadata, entityType, entity, null, expand, toDepth, select, xml10InvalidCharReplacement, writer, false, writeOnlyRef); } } protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, - final Entity entity, final ContextURL contextURL, final ExpandOption expand, + final Entity entity, final ContextURL contextURL, final ExpandOption expand, final Integer toDepth, final SelectOption select, final String xml10InvalidCharReplacement, final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef) throws XMLStreamException, SerializerException { @@ -466,7 +472,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { } EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType()); - writeNavigationProperties(metadata, resolvedType, entity, expand, xml10InvalidCharReplacement, writer); + writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, xml10InvalidCharReplacement, writer); writer.writeStartElement(ATOM, Constants.ATOM_ELEM_CATEGORY, NS_ATOM); writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, Constants.NS_SCHEME); @@ -591,36 +597,71 @@ public class ODataXmlSerializer extends AbstractODataSerializer { } protected void writeNavigationProperties(final ServiceMetadata metadata, - final EdmStructuredType type, final Linked linked, final ExpandOption expand, + final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth, final String xml10InvalidCharReplacement, final XMLStreamWriter writer) throws SerializerException, XMLStreamException { - if (ExpandSelectHelper.hasExpand(expand)) { - final boolean expandAll = ExpandSelectHelper.isExpandAll(expand); - final Set expanded = expandAll ? new HashSet() : - ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems()); + if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) { + final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); for (final String propertyName : type.getNavigationPropertyNames()) { - final EdmNavigationProperty property = type.getNavigationProperty(propertyName); - final Link navigationLink = getOrCreateLink(linked, propertyName); - if (expandAll || expanded.contains(propertyName)) { - final ExpandItem innerOptions = expandAll ? null : - ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); - if (innerOptions != null && innerOptions.getLevelsOption() != null) { - throw new SerializerException("Expand option $levels is not supported.", - SerializerException.MessageKeys.NOT_IMPLEMENTED); - } - if (navigationLink != null) { - writeLink(writer, navigationLink, false); - writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA); - writeExpandedNavigationProperty(metadata, property, navigationLink, - innerOptions == null ? null : innerOptions.getExpandOption(), - innerOptions == null ? null : innerOptions.getSelectOption(), - innerOptions == null ? null : innerOptions.getCountOption(), - innerOptions == null ? false : innerOptions.hasCountPath(), - innerOptions == null ? false : innerOptions.isRef(), - xml10InvalidCharReplacement, writer); - writer.writeEndElement(); - writer.writeEndElement(); + final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); + if (toDepth != null) { + final EdmNavigationProperty property = type.getNavigationProperty(propertyName); + final Link navigationLink = getOrCreateLink(linked, propertyName); + writeLink(writer, navigationLink, false); + writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA); + writeExpandedNavigationProperty(metadata, property, navigationLink, + expand, toDepth - 1, + innerOptions == null ? null : innerOptions.getSelectOption(), + innerOptions == null ? null : innerOptions.getCountOption(), + innerOptions == null ? false : innerOptions.hasCountPath(), + innerOptions == null ? false : innerOptions.isRef(), + xml10InvalidCharReplacement, writer); + writer.writeEndElement(); + writer.writeEndElement(); + continue; + } + Integer levels = null; + if (expandAll != null || innerOptions != null) { + final EdmNavigationProperty property = type.getNavigationProperty(propertyName); + final Link navigationLink = getOrCreateLink(linked, propertyName); + ExpandOption childExpand = null; + LevelsExpandOption levelsOption = null; + if (innerOptions != null) { + levelsOption = innerOptions.getLevelsOption(); + if (levelsOption == null) { + childExpand = innerOptions.getExpandOption(); + } else { + ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl(); + expandOptionImpl.addExpandItem(innerOptions); + childExpand = expandOptionImpl; + } + } else if (expandAll != null) { + levels = 1; + levelsOption = expandAll.getLevelsOption(); + ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl(); + expandOptionImpl.addExpandItem(expandAll); + childExpand = expandOptionImpl; + } + + if (levelsOption != null) { + if (levelsOption.isMax()) { + levels = Integer.MAX_VALUE; + } else { + levels = levelsOption.getValue(); + } } + + writeLink(writer, navigationLink, false); + writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA); + writeExpandedNavigationProperty(metadata, property, navigationLink, + childExpand, levels, + innerOptions == null ? null : innerOptions.getSelectOption(), + innerOptions == null ? null : innerOptions.getCountOption(), + innerOptions == null ? false : innerOptions.hasCountPath(), + innerOptions == null ? false : innerOptions.isRef(), + xml10InvalidCharReplacement, writer); + writer.writeEndElement(); + writer.writeEndElement(); } else { writeLink(writer, getOrCreateLink(linked, propertyName)); } @@ -676,7 +717,8 @@ public class ODataXmlSerializer extends AbstractODataSerializer { protected void writeExpandedNavigationProperty(final ServiceMetadata metadata, final EdmNavigationProperty property, final Link navigationLink, - final ExpandOption innerExpand, final SelectOption innerSelect, final CountOption coutOption, + final ExpandOption innerExpand, final Integer toDepth, + final SelectOption innerSelect, final CountOption coutOption, final boolean writeNavigationCount, final boolean writeOnlyRef,final String xml10InvalidCharReplacement, final XMLStreamWriter writer) throws XMLStreamException, SerializerException { if (property.isCollection()) { @@ -688,7 +730,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { if (coutOption != null && coutOption.getValue()) { writeCount(navigationLink.getInlineEntitySet(), writer); } - writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, + writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth, innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef); } writer.writeEndElement(); @@ -696,7 +738,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { } else { if (navigationLink != null && navigationLink.getInlineEntity() != null) { writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null, - innerExpand, innerSelect, xml10InvalidCharReplacement, writer, false, writeOnlyRef); + innerExpand, toDepth, innerSelect, xml10InvalidCharReplacement, writer, false, writeOnlyRef); } } } 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 2e8629843..efd0713c6 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 @@ -65,6 +65,7 @@ import org.apache.olingo.server.api.uri.UriHelper; import org.apache.olingo.server.api.uri.queryoption.CountOption; 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.LevelsExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectItem; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.core.serializer.ExpandSelectMock; @@ -1356,6 +1357,53 @@ public class ODataJsonSerializerTest { + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}", resultString); } + + @Test + public void expandStarTwoLevels() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final EdmEntitySet innerEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + ExpandItem expandItem = Mockito.mock(ExpandItem.class); + Mockito.when(expandItem.isStar()).thenReturn(true); + LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class); + Mockito.when(levels.getValue()).thenReturn(2); + Mockito.when(expandItem.getLevelsOption()).thenReturn(levels); + final SelectOption select = ExpandSelectMock.mockSelectOption(Collections.singletonList( + ExpandSelectMock.mockSelectItem(innerEntitySet, "PropertyInt32"))); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(expandItem)); + final String resultString = IOUtils.toString(serializer + .entity(metadata, entityType, entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(helper.buildContextURLSelectList(entityType, expand, select)) + .suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent()); + Assert.assertEquals("{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\"," + + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"," + + "\"NavPropertyETAllPrimOne\":null," + + "\"NavPropertyETAllPrimMany\":[" + + "{\"PropertyInt16\":-32768,\"PropertyString\":\"Second Resource - negative values\"," + + "\"PropertyBoolean\":false,\"PropertyByte\":0,\"PropertySByte\":-128,\"PropertyInt32\":-2147483648," + + "\"PropertyInt64\":-9223372036854775808,\"PropertySingle\":-1.79E8,\"PropertyDouble\":-179000.0," + + "\"PropertyDecimal\":-34,\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyDate\":\"2015-11-05\"," + + "\"PropertyDateTimeOffset\":\"2005-12-03T07:17:08Z\",\"PropertyDuration\":\"PT9S\"," + + "\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789dddfff\",\"PropertyTimeOfDay\":\"23:49:14\"," + + "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}," + + "{\"PropertyInt16\":0,\"PropertyString\":\"\",\"PropertyBoolean\":false,\"PropertyByte\":0," + + "\"PropertySByte\":0,\"PropertyInt32\":0,\"PropertyInt64\":0,\"PropertySingle\":0.0," + + "\"PropertyDouble\":0.0,\"PropertyDecimal\":0,\"PropertyBinary\":\"\"," + + "\"PropertyDate\":\"1970-01-01\",\"PropertyDateTimeOffset\":\"2005-12-03T00:00:00Z\"," + + "\"PropertyDuration\":\"PT0S\",\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789cccddd\"," + + "\"PropertyTimeOfDay\":\"00:01:01\",\"NavPropertyETTwoPrimOne\":null," + + "\"NavPropertyETTwoPrimMany\":[" + + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}," + + "{\"PropertyInt16\":-32766,\"PropertyString\":null}," + + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}", + resultString); + } @Test public void primitiveProperty() throws Exception {