[OLINGO-1099] OData V4.0: $levels refactoring Signed-off-by: Christian Amend <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/f5520556 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/f5520556 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/f5520556 Branch: refs/heads/master Commit: f55205561ea5a4f7d37b2015e5f06bfdbb704c89 Parents: 173f0d7 Author: Archana Rai <[email protected]> Authored: Thu Apr 27 15:47:19 2017 +0530 Committer: Christian Amend <[email protected]> Committed: Thu Apr 27 13:01:40 2017 +0200 ---------------------------------------------------------------------- .../fit/tecsvc/client/BatchClientITCase.java | 8 +- .../serializer/json/ODataJsonSerializer.java | 104 +++++++++---------- .../core/serializer/utils/ContextURLHelper.java | 4 +- .../serializer/utils/ExpandSelectHelper.java | 9 -- .../core/serializer/xml/ODataXmlSerializer.java | 101 ++++++++---------- .../ExpandSystemQueryOptionHandler.java | 2 +- .../json/ODataJsonSerializerTest.java | 17 ++- 7 files changed, 111 insertions(+), 134 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java ---------------------------------------------------------------------- diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java index 53bfa58..9e1537d 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BatchClientITCase.java @@ -161,7 +161,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase { assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size()); assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next()); assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size()); - assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); + assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); assertContentType(oDataResponse.getContentType()); } @@ -193,7 +193,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase { assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size()); assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next()); assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size()); - assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); + assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); assertContentType(oDataResponse.getContentType()); } @@ -292,7 +292,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase { assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size()); assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next()); assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size()); - assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); + assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); assertContentType(oDataResponse.getContentType()); // Check second get request @@ -398,7 +398,7 @@ public class BatchClientITCase extends AbstractParamTecSvcITCase { assertEquals(1, oDataResponse.getHeader(HttpHeader.ODATA_VERSION).size()); assertEquals("4.0", oDataResponse.getHeader(HttpHeader.ODATA_VERSION).iterator().next()); assertEquals(1, oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).size()); - assertEquals(isJson() ? "605" : "2246", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); + assertEquals(isJson() ? "605" : "2223", oDataResponse.getHeader(HttpHeader.CONTENT_LENGTH).iterator().next()); assertContentType(oDataResponse.getContentType()); // Check second get request http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java ---------------------------------------------------------------------- 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 c5ac9f3..518b5cc 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 @@ -20,6 +20,7 @@ package org.apache.olingo.server.core.serializer.json; import java.io.IOException; import java.io.OutputStream; +import java.net.URI; import java.util.Collections; import java.util.EnumMap; import java.util.HashSet; @@ -180,6 +181,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeStartObject(); final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL()); + String name = contextURL == null ? null:contextURL.getEntitySetOrSingletonOrType(); writeContextURL(contextURL, json); writeMetadataETag(metadata, json); @@ -190,10 +192,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeOperations(entitySet.getOperations(), json); json.writeFieldName(Constants.VALUE); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, json); + writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, name, json); } else { writeEntitySet(metadata, entityType, entitySet, - options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, json); + options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, name, json); } writeNextLink(entitySet, json); @@ -235,11 +237,12 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeInlineCount("", entitySet.getCount(), json); } json.writeFieldName(Constants.VALUE); + String name = contextURL == null ? null:contextURL.getEntitySetOrSingletonOrType() ; if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, json); + writeEntitySet(metadata, entityType, entitySet, null, null, null, false, null, name, json); } else { writeEntitySet(metadata, entityType, entitySet, - options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, json); + options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), null, name, json); } // next link support for streaming results writeNextLink(entitySet, json); @@ -262,12 +265,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer { CircleStreamBuffer buffer = new CircleStreamBuffer(); outputStream = buffer.getOutputStream(); JsonGenerator json = new JsonFactory().createGenerator(outputStream); + String name = contextURL == null ? null:contextURL.getEntitySetOrSingletonOrType(); writeEntity(metadata, entityType, entity, contextURL, options == null ? null : options.getExpand(), null, options == null ? null : options.getSelect(), options == null ? false : options.getWriteOnlyReferences(), - null, + null, name, json); json.close(); @@ -293,16 +297,16 @@ public class ODataJsonSerializer extends AbstractODataSerializer { protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType, final AbstractEntityCollection entitySet, final ExpandOption expand, Integer toDepth, final SelectOption select, - final boolean onlyReference, final Set<String> ancestors, final JsonGenerator json) throws IOException, - SerializerException { + final boolean onlyReference, final Set<String> ancestors, String name, final JsonGenerator json) + throws IOException, SerializerException { json.writeStartArray(); for (final Entity entity : entitySet) { if (onlyReference) { json.writeStartObject(); - json.writeStringField(Constants.JSON_ID, getEntityId(entity)); + json.writeStringField(Constants.JSON_ID, getEntityId(entity, entityType, name)); json.writeEndObject(); } else { - writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, ancestors, json); + writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, ancestors, name, json); } } json.writeEndArray(); @@ -313,11 +317,19 @@ public class ODataJsonSerializer extends AbstractODataSerializer { * or thrown an {@link SerializerException} if id is <code>null</code>. * * @param entity the entity + * @param entityType + * @param name * @return ascii representation of the entity id */ - private String getEntityId(Entity entity) throws SerializerException { + private String getEntityId(Entity entity, EdmEntityType entityType, String name) throws SerializerException { if(entity.getId() == null) { - throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID); + if(entity == null || entityType == null || entityType.getKeyPredicateNames() == null + || name == null) { + throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID); + }else{ + final UriHelper uriHelper = new UriHelperImpl(); + entity.setId(URI.create(name + '(' + uriHelper.buildKeyPredicate(entityType, entity) + ')')); + } } return entity.getId().toASCIIString(); } @@ -337,14 +349,15 @@ public class ODataJsonSerializer extends AbstractODataSerializer { protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity, final ContextURL contextURL, final ExpandOption expand, Integer toDepth, - final SelectOption select, final boolean onlyReference, Set<String> ancestors, final JsonGenerator json) + final SelectOption select, final boolean onlyReference, Set<String> ancestors, + String name, final JsonGenerator json) throws IOException, SerializerException { boolean cycle = false; if (expand != null) { if (ancestors == null) { ancestors = new HashSet<String>(); } - cycle = !ancestors.add(getEntityId(entity)); + cycle = !ancestors.add(getEntityId(entity, entityType, name)); } try { json.writeStartObject(); @@ -373,14 +386,14 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } } if (cycle || onlyReference) { - json.writeStringField(Constants.JSON_ID, getEntityId(entity)); + json.writeStringField(Constants.JSON_ID, getEntityId(entity, entityType, name)); } else { final EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType()); if ((!isODataMetadataNone && !resolvedType.equals(entityType)) || isODataMetadataFull) { json.writeStringField(Constants.JSON_TYPE, "#" + entity.getType()); } if ((!isODataMetadataNone && !areKeyPredicateNamesSelected(select, resolvedType)) || isODataMetadataFull) { - json.writeStringField(Constants.JSON_ID, getEntityId(entity)); + json.writeStringField(Constants.JSON_ID, getEntityId(entity, resolvedType, name)); } if (isODataMetadataFull) { @@ -393,13 +406,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } writeProperties(metadata, resolvedType, entity.getProperties(), select, json); - writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, json); + writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, name, json); writeOperations(entity.getOperations(), json); } json.writeEndObject(); } finally { if (expand != null && !cycle && ancestors != null) { - ancestors.remove(getEntityId(entity)); + ancestors.remove(getEntityId(entity, entityType, name)); } } } @@ -484,7 +497,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer { protected void writeNavigationProperties(final ServiceMetadata metadata, final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth, - final Set<String> ancestors, final JsonGenerator json) throws SerializerException, IOException { + final Set<String> ancestors, final String name, final JsonGenerator json) + throws SerializerException, IOException { if (isODataMetadataFull) { for (final String propertyName : type.getNavigationPropertyNames()) { final Link navigationLink = linked.getNavigationLink(propertyName); @@ -501,48 +515,28 @@ public class ODataJsonSerializer extends AbstractODataSerializer { final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); for (final String propertyName : type.getNavigationPropertyNames()) { final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); - if (toDepth != null) { - final EdmNavigationProperty property = type.getNavigationProperty(propertyName); - final Link navigationLink = linked.getNavigationLink(property.getName()); - 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(), - ancestors, - json); - continue; - } - Integer levels = null; - if (expandAll != null || innerOptions != null) { + if (innerOptions != null || expandAll != null || toDepth != null) { + Integer levels = 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; - } + childExpand = levelsOption == null ? innerOptions.getExpandOption() : new ExpandOptionImpl().addExpandItem( + innerOptions); } else if (expandAll != null) { levels = 1; levelsOption = expandAll.getLevelsOption(); - ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl(); - expandOptionImpl.addExpandItem(expandAll); - childExpand = expandOptionImpl; + childExpand = new ExpandOptionImpl().addExpandItem(expandAll); } - if (levelsOption != null) { - if (levelsOption.isMax()) { - levels = Integer.MAX_VALUE; - } else { - levels = levelsOption.getValue(); - } + if (levelsOption != null) { + levels = levelsOption.isMax() ? Integer.MAX_VALUE : levelsOption.getValue(); + } + if (toDepth != null) { + levels = toDepth - 1; + childExpand = expand; } writeExpandedNavigationProperty(metadata, property, navigationLink, @@ -551,7 +545,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { innerOptions == null ? null : innerOptions.getCountOption(), innerOptions == null ? false : innerOptions.hasCountPath(), innerOptions == null ? false : innerOptions.isRef(), - ancestors, + ancestors, name, json); } } @@ -563,7 +557,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { final Link navigationLink, final ExpandOption innerExpand, Integer toDepth, final SelectOption innerSelect, final CountOption innerCount, final boolean writeOnlyCount, final boolean writeOnlyRef, final Set<String> ancestors, - final JsonGenerator json) throws IOException, SerializerException { + String name, final JsonGenerator json) throws IOException, SerializerException { if (property.isCollection()) { if (writeOnlyCount) { @@ -586,7 +580,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } json.writeFieldName(property.getName()); writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth, - innerSelect, writeOnlyRef, ancestors, json); + innerSelect, writeOnlyRef, ancestors, name, json); } } } else { @@ -595,7 +589,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeNull(); } else { writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null, - innerExpand, toDepth, innerSelect, writeOnlyRef, ancestors, json); + innerExpand, toDepth, innerSelect, writeOnlyRef, ancestors, name, json); } } } @@ -998,6 +992,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer { SerializerException cachedException = null; try { final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL()); + final String name = contextURL == null ? null: + contextURL.getEntitySetOrSingletonOrType(); CircleStreamBuffer buffer = new CircleStreamBuffer(); outputStream = buffer.getOutputStream(); JsonGenerator json = new JsonFactory().createGenerator(outputStream); @@ -1014,7 +1010,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(), null, null, json); + options == null ? null : options.getExpand(), null, null, name, json); } json.writeEndObject(); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java index 129f242..66dd84f 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java @@ -57,7 +57,7 @@ public final class ContextURLHelper { handleSelect(type, select, result); } - if (ExpandSelectHelper.hasExpand(expand) && !ExpandSelectHelper.isExpandAll(expand)) { + if (ExpandSelectHelper.hasExpand(expand) && !(null != ExpandSelectHelper.getExpandAll(expand))) { handleExpand(type, expand, result); } return result.length() == 0 ? null : result.toString(); @@ -111,7 +111,7 @@ public final class ContextURLHelper { if (expandedPropertyNames.contains(propertyName)) { final ExpandItem expandItem = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); if (ExpandSelectHelper.hasExpand(expandItem.getExpandOption()) - && !ExpandSelectHelper.isExpandAll(expandItem.getExpandOption()) + && !(null != ExpandSelectHelper.getExpandAll(expandItem.getExpandOption())) || ExpandSelectHelper.hasSelect(expandItem.getSelectOption())) { final String innerSelectList = buildSelectList(type.getNavigationProperty(propertyName).getType(), expandItem.getExpandOption(), expandItem.getSelectOption()); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java ---------------------------------------------------------------------- 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 4424b61..981b302 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 @@ -113,15 +113,6 @@ public abstract class ExpandSelectHelper { return expand != null && expand.getExpandItems() != null && !expand.getExpandItems().isEmpty(); } - public static boolean isExpandAll(final ExpandOption expand) { - for (final ExpandItem item : expand.getExpandItems()) { - if (item.isStar()) { - return true; - } - } - return false; - } - public static ExpandItem getExpandAll(final ExpandOption expand) { for (final ExpandItem item : expand.getExpandItems()) { if (item.isStar()) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java ---------------------------------------------------------------------- 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 c7ea2e2..b66c755 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 @@ -20,6 +20,7 @@ package org.apache.olingo.server.core.serializer.xml; import java.io.IOException; import java.io.OutputStream; +import java.net.URI; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; @@ -67,6 +68,7 @@ import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.serializer.SerializerResult; import org.apache.olingo.server.api.serializer.SerializerStreamResult; +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; @@ -78,6 +80,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.UriHelperImpl; import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl; public class ODataXmlSerializer extends AbstractODataSerializer { @@ -221,6 +224,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { final EntityCollectionSerializerOptions options) throws SerializerException { final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL()); + final String name = contextURL == null ? null : contextURL.getEntitySetOrSingletonOrType(); if (options != null && options.getWriteOnlyReferences()) { ReferenceCollectionSerializerOptions rso = ReferenceCollectionSerializerOptions.with() .contextURL(contextURL).build(); @@ -259,11 +263,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer { boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences()); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef, null); + writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef, name, null); } else { writeEntitySet(metadata, entityType, entitySet, options.getExpand(), null, - options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef, null); + options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef, name, null); } writer.writeEndElement(); @@ -291,6 +295,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { EntityCollectionSerializerOptions options, OutputStream outputStream) throws SerializerException { final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL()); + final String name = contextURL == null ? null : contextURL.getEntitySetOrSingletonOrType(); SerializerException cachedException; try { XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, DEFAULT_CHARSET); @@ -319,11 +324,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer { } boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences()); if (options == null) { - writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef,null); + writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef, name, null); } else { writeEntitySet(metadata, entityType, entitySet, options.getExpand(), null, - options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef,null); + options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef, name, null); } writer.writeEndElement(); @@ -347,7 +352,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity, final EntitySerializerOptions options) throws SerializerException { final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL()); - + final String name = contextURL == null ? null : contextURL.getEntitySetOrSingletonOrType(); if (options != null && options.getWriteOnlyReferences()) { return entityReference(entity, ReferenceSerializerOptions.with().contextURL(contextURL).build()); @@ -365,7 +370,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { null, options == null ? null : options.getSelect(), options == null ? null : options.xml10InvalidCharReplacement(), - writer, true, false, null); + writer, true, false, name, null); writer.writeEndDocument(); writer.flush(); @@ -407,11 +412,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer { final AbstractEntityCollection entitySet, final ExpandOption expand, final Integer toDepth, final SelectOption select, final String xml10InvalidCharReplacement,final XMLStreamWriter writer, - final boolean writeOnlyRef,final Set<String> ancestors) + final boolean writeOnlyRef, final String name,final Set<String> ancestors) throws XMLStreamException, SerializerException { for (final Entity entity : entitySet) { writeEntity(metadata, entityType, entity, null, expand, toDepth, select, - xml10InvalidCharReplacement, writer, false, writeOnlyRef, ancestors); + xml10InvalidCharReplacement, writer, false, writeOnlyRef, name, ancestors); } } @@ -420,26 +425,35 @@ public class ODataXmlSerializer extends AbstractODataSerializer { * or thrown an {@link SerializerException} if id is <code>null</code>. * * @param entity the entity + * @param entityType the entity Type + * @param name the entity name * @return ascii representation of the entity id */ - private String getEntityId(Entity entity) throws SerializerException { + private String getEntityId(Entity entity, EdmEntityType entityType, String name) throws SerializerException { if(entity.getId() == null) { - throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID); + if((entity == null || entityType == null || entityType.getKeyPredicateNames() == null + || name == null)) { + throw new SerializerException("Entity id is null.", SerializerException.MessageKeys.MISSING_ID); + }else{ + final UriHelper uriHelper = new UriHelperImpl(); + entity.setId(URI.create(name + '(' + uriHelper.buildKeyPredicate(entityType, entity) + ')')); + } } return entity.getId().toASCIIString(); } + protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, 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, Set<String> ancestors) + final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef,String name, Set<String> ancestors) throws XMLStreamException, SerializerException { boolean cycle = false; if (expand != null) { if (ancestors == null) { ancestors = new HashSet<String>(); } - cycle = !ancestors.add(getEntityId(entity)); + cycle = !ancestors.add(getEntityId(entity, entityType, name)); } if (cycle || writeOnlyRef) { @@ -498,7 +512,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType()); writeNavigationProperties(metadata, resolvedType, entity, expand, - toDepth, xml10InvalidCharReplacement, ancestors, writer); + toDepth, xml10InvalidCharReplacement, ancestors, name, writer); writer.writeStartElement(ATOM, Constants.ATOM_ELEM_CATEGORY, NS_ATOM); writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, Constants.NS_SCHEME); @@ -525,7 +539,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { writer.writeEndElement(); // entry } finally { if (!cycle && ancestors != null) { - ancestors.remove(getEntityId(entity)); + ancestors.remove(getEntityId(entity, entityType, name)); } } } @@ -629,59 +643,36 @@ public class ODataXmlSerializer extends AbstractODataSerializer { protected void writeNavigationProperties(final ServiceMetadata metadata, final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth, - final String xml10InvalidCharReplacement, final Set<String> ancestors, final XMLStreamWriter writer) + final String xml10InvalidCharReplacement, final Set<String> ancestors, String name, final XMLStreamWriter writer) throws SerializerException, XMLStreamException { if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) { final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); for (final String propertyName : type.getNavigationPropertyNames()) { 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, ancestors, writer); - writer.writeEndElement(); - writer.writeEndElement(); - continue; - } - Integer levels = null; - if (expandAll != null || innerOptions != null) { + if (expandAll != null || innerOptions != null || toDepth != null) { + Integer levels = 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; - } + childExpand = levelsOption == null ? innerOptions.getExpandOption() : + new ExpandOptionImpl().addExpandItem(innerOptions); } else if (expandAll != null) { levels = 1; levelsOption = expandAll.getLevelsOption(); - ExpandOptionImpl expandOptionImpl = new ExpandOptionImpl(); - expandOptionImpl.addExpandItem(expandAll); - childExpand = expandOptionImpl; - } - + childExpand = new ExpandOptionImpl().addExpandItem(expandAll); + } + if (levelsOption != null) { - if (levelsOption.isMax()) { - levels = Integer.MAX_VALUE; - } else { - levels = levelsOption.getValue(); - } + levels = levelsOption.isMax() ? Integer.MAX_VALUE : + levelsOption.getValue(); + } + if (toDepth != null) { + levels = toDepth - 1; + childExpand = expand; } - writeLink(writer, navigationLink, false); writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA); writeExpandedNavigationProperty(metadata, property, navigationLink, @@ -690,7 +681,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { innerOptions == null ? null : innerOptions.getCountOption(), innerOptions == null ? false : innerOptions.hasCountPath(), innerOptions == null ? false : innerOptions.isRef(), - xml10InvalidCharReplacement, ancestors, writer); + xml10InvalidCharReplacement, ancestors, name, writer); writer.writeEndElement(); writer.writeEndElement(); } else { @@ -751,7 +742,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { final ExpandOption innerExpand, final Integer toDepth, final SelectOption innerSelect, final CountOption coutOption, final boolean writeNavigationCount, final boolean writeOnlyRef,final String xml10InvalidCharReplacement, - final Set<String> ancestors, + final Set<String> ancestors, String name, final XMLStreamWriter writer) throws XMLStreamException, SerializerException { if (property.isCollection()) { if (navigationLink != null && navigationLink.getInlineEntitySet() != null) { @@ -763,7 +754,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { writeCount(navigationLink.getInlineEntitySet(), writer); } writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth, - innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef, ancestors); + innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef, name, ancestors); } writer.writeEndElement(); } @@ -771,7 +762,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer { if (navigationLink != null && navigationLink.getInlineEntity() != null) { writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null, innerExpand, toDepth, innerSelect, xml10InvalidCharReplacement, writer, - false, writeOnlyRef, ancestors); + false, writeOnlyRef, name, ancestors); } } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java index 7ddad53..8886a0c 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java @@ -217,7 +217,7 @@ public class ExpandSystemQueryOptionHandler { newEntity.getAssociationLinks().addAll(entity.getAssociationLinks()); newEntity.getNavigationBindings().addAll(entity.getNavigationBindings()); newEntity.getOperations().addAll(entity.getOperations()); - + newEntity.getNavigationLinks().addAll(entity.getNavigationLinks()); return newEntity; } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f5520556/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java ---------------------------------------------------------------------- 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 9796aef..4ce1768 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 @@ -1286,7 +1286,7 @@ public class ODataJsonSerializerTest { Assert.assertEquals(false, resultString.contains(METADATA_TEXT)); } - @Test(expected = SerializerException.class) + @Test public void selectMissingId() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); final EdmEntityType entityType = edmEntitySet.getEntityType(); @@ -1296,20 +1296,19 @@ public class ODataJsonSerializerTest { final SelectItem selectItem2 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyBoolean"); final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( selectItem1, selectItem2, selectItem2)); - - try { - serializer.entity(metadata, entityType, entity, + InputStream result = serializer.entity(metadata, entityType, entity, EntitySerializerOptions.with() .contextURL(ContextURL.with().entitySet(edmEntitySet) .selectList(helper.buildContextURLSelectList(entityType, null, select)) .suffix(Suffix.ENTITY).build()) .select(select) .build()).getContent(); - Assert.fail("Expected exception not thrown!"); - } catch (final SerializerException e) { - Assert.assertEquals(SerializerException.MessageKeys.MISSING_ID, e.getMessageKey()); - throw e; - } + Assert.assertNotNull(result); + final String resultString = IOUtils.toString(result); + Assert.assertEquals( "{\"@odata.context\":\"$metadata#ESAllPrim(PropertyBoolean,PropertyDate)/$entity\","+ + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\",\"@odata.id\":\"ESAllPrim(32767)\","+ + "\"PropertyBoolean\":true,\"PropertyDate\":\"2012-12-03\"}", + resultString); } @Test
