OLINGO-1009 Changing serialization to allow for $levels
This commit is contained in:
parent
b1db030cb8
commit
68969d547d
|
@ -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.CountOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
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.ExpandOption;
|
||||||
|
import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
||||||
import org.apache.olingo.server.core.ODataWritableContent;
|
import org.apache.olingo.server.core.ODataWritableContent;
|
||||||
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
|
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.ContextURLBuilder;
|
||||||
import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
|
import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
|
||||||
import org.apache.olingo.server.core.uri.UriHelperImpl;
|
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.JsonFactory;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
@ -164,10 +166,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
writeOperations(entitySet.getOperations(), json);
|
writeOperations(entitySet.getOperations(), json);
|
||||||
json.writeFieldName(Constants.VALUE);
|
json.writeFieldName(Constants.VALUE);
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
writeEntitySet(metadata, entityType, entitySet, null, null, false, json);
|
writeEntitySet(metadata, entityType, entitySet, null, null, null, false, json);
|
||||||
} else {
|
} else {
|
||||||
writeEntitySet(metadata, entityType, entitySet,
|
writeEntitySet(metadata, entityType, entitySet,
|
||||||
options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json);
|
options.getExpand(), null, options.getSelect(), options.getWriteOnlyReferences(), json);
|
||||||
}
|
}
|
||||||
writeNextLink(entitySet, json);
|
writeNextLink(entitySet, json);
|
||||||
|
|
||||||
|
@ -210,10 +212,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
json.writeFieldName(Constants.VALUE);
|
json.writeFieldName(Constants.VALUE);
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
writeEntitySet(metadata, entityType, entitySet, null, null, false, json);
|
writeEntitySet(metadata, entityType, entitySet, null, null, null, false, json);
|
||||||
} else {
|
} else {
|
||||||
writeEntitySet(metadata, entityType, entitySet,
|
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
|
// next link not supported by default for streaming results
|
||||||
// writeNextLink(entitySet, json);
|
// writeNextLink(entitySet, json);
|
||||||
|
@ -238,6 +240,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
JsonGenerator json = new JsonFactory().createGenerator(outputStream);
|
JsonGenerator json = new JsonFactory().createGenerator(outputStream);
|
||||||
writeEntity(metadata, entityType, entity, contextURL,
|
writeEntity(metadata, entityType, entity, contextURL,
|
||||||
options == null ? null : options.getExpand(),
|
options == null ? null : options.getExpand(),
|
||||||
|
null,
|
||||||
options == null ? null : options.getSelect(),
|
options == null ? null : options.getSelect(),
|
||||||
options == null ? false : options.getWriteOnlyReferences(),
|
options == null ? false : options.getWriteOnlyReferences(),
|
||||||
json);
|
json);
|
||||||
|
@ -264,7 +267,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
|
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,
|
final boolean onlyReference, final JsonGenerator json) throws IOException,
|
||||||
SerializerException {
|
SerializerException {
|
||||||
json.writeStartArray();
|
json.writeStartArray();
|
||||||
|
@ -274,7 +277,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
json.writeStringField(Constants.JSON_ID, getEntityId(entity));
|
json.writeStringField(Constants.JSON_ID, getEntityId(entity));
|
||||||
json.writeEndObject();
|
json.writeEndObject();
|
||||||
} else {
|
} else {
|
||||||
writeEntity(metadata, entityType, entity, null, expand, select, false, json);
|
writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json.writeEndArray();
|
json.writeEndArray();
|
||||||
|
@ -308,8 +311,8 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity,
|
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 ContextURL contextURL, final ExpandOption expand, Integer toDepth,
|
||||||
final JsonGenerator json)
|
final SelectOption select, final boolean onlyReference, final JsonGenerator json)
|
||||||
throws IOException, SerializerException {
|
throws IOException, SerializerException {
|
||||||
json.writeStartObject();
|
json.writeStartObject();
|
||||||
if (!isODataMetadataNone) {
|
if (!isODataMetadataNone) {
|
||||||
|
@ -357,7 +360,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
writeProperties(metadata, resolvedType, entity.getProperties(), select, json);
|
writeProperties(metadata, resolvedType, entity.getProperties(), select, json);
|
||||||
writeNavigationProperties(metadata, resolvedType, entity, expand, json);
|
writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, json);
|
||||||
writeOperations(entity.getOperations(), json);
|
writeOperations(entity.getOperations(), json);
|
||||||
json.writeEndObject();
|
json.writeEndObject();
|
||||||
}
|
}
|
||||||
|
@ -442,24 +445,57 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeNavigationProperties(final ServiceMetadata metadata,
|
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 {
|
final JsonGenerator json) throws SerializerException, IOException {
|
||||||
if (ExpandSelectHelper.hasExpand(expand)) {
|
if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) {
|
||||||
final boolean expandAll = ExpandSelectHelper.isExpandAll(expand);
|
final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand);
|
||||||
final Set<String> expanded = expandAll ? new HashSet<String>() :
|
|
||||||
ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems());
|
|
||||||
for (final String propertyName : type.getNavigationPropertyNames()) {
|
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 EdmNavigationProperty property = type.getNavigationProperty(propertyName);
|
||||||
final Link navigationLink = linked.getNavigationLink(property.getName());
|
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,
|
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.getSelectOption(),
|
||||||
innerOptions == null ? null : innerOptions.getCountOption(),
|
innerOptions == null ? null : innerOptions.getCountOption(),
|
||||||
innerOptions == null ? false : innerOptions.hasCountPath(),
|
innerOptions == null ? false : innerOptions.hasCountPath(),
|
||||||
|
@ -484,7 +520,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
protected void writeExpandedNavigationProperty(
|
protected void writeExpandedNavigationProperty(
|
||||||
final ServiceMetadata metadata, final EdmNavigationProperty property,
|
final ServiceMetadata metadata, final EdmNavigationProperty property,
|
||||||
final Link navigationLink, final ExpandOption innerExpand,
|
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 boolean writeOnlyCount, final boolean writeOnlyRef,
|
||||||
final JsonGenerator json) throws IOException, SerializerException {
|
final JsonGenerator json) throws IOException, SerializerException {
|
||||||
|
|
||||||
|
@ -508,7 +544,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
writeInlineCount(property.getName(), navigationLink.getInlineEntitySet().getCount(), json);
|
writeInlineCount(property.getName(), navigationLink.getInlineEntitySet().getCount(), json);
|
||||||
}
|
}
|
||||||
json.writeFieldName(property.getName());
|
json.writeFieldName(property.getName());
|
||||||
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand,
|
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth,
|
||||||
innerSelect, writeOnlyRef, json);
|
innerSelect, writeOnlyRef, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +554,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
json.writeNull();
|
json.writeNull();
|
||||||
} else {
|
} else {
|
||||||
writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
|
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);
|
writeProperties(metadata, type, values, options == null ? null : options.getSelect(), json);
|
||||||
if (!property.isNull() && property.isComplex()) {
|
if (!property.isNull() && property.isComplex()) {
|
||||||
writeNavigationProperties(metadata, type, property.asComplex(),
|
writeNavigationProperties(metadata, type, property.asComplex(),
|
||||||
options == null ? null : options.getExpand(), json);
|
options == null ? null : options.getExpand(), null, json);
|
||||||
}
|
}
|
||||||
json.writeEndObject();
|
json.writeEndObject();
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,15 @@ public abstract class ExpandSelectHelper {
|
||||||
return false;
|
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<String> getExpandedPropertyNames(final List<ExpandItem> expandItems)
|
public static Set<String> getExpandedPropertyNames(final List<ExpandItem> expandItems)
|
||||||
throws SerializerException {
|
throws SerializerException {
|
||||||
Set<String> expanded = new HashSet<String>();
|
Set<String> expanded = new HashSet<String>();
|
||||||
|
@ -137,6 +146,9 @@ public abstract class ExpandSelectHelper {
|
||||||
|
|
||||||
public static ExpandItem getExpandItem(final List<ExpandItem> expandItems, final String propertyName) {
|
public static ExpandItem getExpandItem(final List<ExpandItem> expandItems, final String propertyName) {
|
||||||
for (final ExpandItem item : expandItems) {
|
for (final ExpandItem item : expandItems) {
|
||||||
|
if (item.isStar()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final UriResource resource = item.getResourcePath().getUriResourceParts().get(0);
|
final UriResource resource = item.getResourcePath().getUriResourceParts().get(0);
|
||||||
if (resource instanceof UriResourceNavigation
|
if (resource instanceof UriResourceNavigation
|
||||||
&& propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) {
|
&& propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) {
|
||||||
|
|
|
@ -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.CountOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
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.ExpandOption;
|
||||||
|
import org.apache.olingo.server.api.uri.queryoption.LevelsExpandOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
||||||
import org.apache.olingo.server.core.ODataWritableContent;
|
import org.apache.olingo.server.core.ODataWritableContent;
|
||||||
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
|
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.CircleStreamBuffer;
|
||||||
import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder;
|
import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder;
|
||||||
import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
|
import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
|
||||||
|
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
|
||||||
|
|
||||||
public class ODataXmlSerializer extends AbstractODataSerializer {
|
public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
|
@ -257,10 +259,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
|
boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
writeEntitySet(metadata, entityType, entitySet, null, null, null, writer, writeOnlyRef);
|
writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef);
|
||||||
} else {
|
} else {
|
||||||
writeEntitySet(metadata, entityType, entitySet,
|
writeEntitySet(metadata, entityType, entitySet,
|
||||||
options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
|
options.getExpand(), null,
|
||||||
|
options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
@ -314,10 +317,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
|
boolean writeOnlyRef = (options != null && options.getWriteOnlyReferences());
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
writeEntitySet(metadata, entityType, entitySet, null, null, null, writer, writeOnlyRef);
|
writeEntitySet(metadata, entityType, entitySet, null, null, null, null, writer, writeOnlyRef);
|
||||||
} else {
|
} else {
|
||||||
writeEntitySet(metadata, entityType, entitySet,
|
writeEntitySet(metadata, entityType, entitySet,
|
||||||
options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
|
options.getExpand(), null,
|
||||||
|
options.getSelect(), options.xml10InvalidCharReplacement(), writer, writeOnlyRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
@ -356,6 +360,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
writer.writeStartDocument(DEFAULT_CHARSET, "1.0");
|
writer.writeStartDocument(DEFAULT_CHARSET, "1.0");
|
||||||
writeEntity(metadata, entityType, entity, contextURL,
|
writeEntity(metadata, entityType, entity, contextURL,
|
||||||
options == null ? null : options.getExpand(),
|
options == null ? null : options.getExpand(),
|
||||||
|
null,
|
||||||
options == null ? null : options.getSelect(),
|
options == null ? null : options.getSelect(),
|
||||||
options == null ? null : options.xml10InvalidCharReplacement(),
|
options == null ? null : options.xml10InvalidCharReplacement(),
|
||||||
writer, true, false);
|
writer, true, false);
|
||||||
|
@ -397,17 +402,18 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
|
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)
|
final String xml10InvalidCharReplacement,final XMLStreamWriter writer, final boolean writeOnlyRef)
|
||||||
throws XMLStreamException, SerializerException {
|
throws XMLStreamException, SerializerException {
|
||||||
for (final Entity entity : entitySet) {
|
for (final Entity entity : entitySet) {
|
||||||
writeEntity(metadata, entityType, entity, null, expand, select,
|
writeEntity(metadata, entityType, entity, null, expand, toDepth, select,
|
||||||
xml10InvalidCharReplacement, writer, false, writeOnlyRef);
|
xml10InvalidCharReplacement, writer, false, writeOnlyRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType,
|
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 SelectOption select, final String xml10InvalidCharReplacement,
|
||||||
final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef)
|
final XMLStreamWriter writer, final boolean top, final boolean writeOnlyRef)
|
||||||
throws XMLStreamException, SerializerException {
|
throws XMLStreamException, SerializerException {
|
||||||
|
@ -466,7 +472,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
EdmEntityType resolvedType = resolveEntityType(metadata, entityType, entity.getType());
|
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.writeStartElement(ATOM, Constants.ATOM_ELEM_CATEGORY, NS_ATOM);
|
||||||
writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, Constants.NS_SCHEME);
|
writer.writeAttribute(Constants.ATOM_ATTR_SCHEME, Constants.NS_SCHEME);
|
||||||
|
@ -591,36 +597,71 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeNavigationProperties(final ServiceMetadata metadata,
|
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)
|
final String xml10InvalidCharReplacement, final XMLStreamWriter writer)
|
||||||
throws SerializerException, XMLStreamException {
|
throws SerializerException, XMLStreamException {
|
||||||
if (ExpandSelectHelper.hasExpand(expand)) {
|
if ((toDepth != null && toDepth > 1) || (toDepth == null && ExpandSelectHelper.hasExpand(expand))) {
|
||||||
final boolean expandAll = ExpandSelectHelper.isExpandAll(expand);
|
final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand);
|
||||||
final Set<String> expanded = expandAll ? new HashSet<String>() :
|
|
||||||
ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems());
|
|
||||||
for (final String propertyName : type.getNavigationPropertyNames()) {
|
for (final String propertyName : type.getNavigationPropertyNames()) {
|
||||||
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
|
final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
|
||||||
final Link navigationLink = getOrCreateLink(linked, propertyName);
|
if (toDepth != null) {
|
||||||
if (expandAll || expanded.contains(propertyName)) {
|
final EdmNavigationProperty property = type.getNavigationProperty(propertyName);
|
||||||
final ExpandItem innerOptions = expandAll ? null :
|
final Link navigationLink = getOrCreateLink(linked, propertyName);
|
||||||
ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName);
|
writeLink(writer, navigationLink, false);
|
||||||
if (innerOptions != null && innerOptions.getLevelsOption() != null) {
|
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
|
||||||
throw new SerializerException("Expand option $levels is not supported.",
|
writeExpandedNavigationProperty(metadata, property, navigationLink,
|
||||||
SerializerException.MessageKeys.NOT_IMPLEMENTED);
|
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 (navigationLink != null) {
|
|
||||||
writeLink(writer, navigationLink, false);
|
if (levelsOption != null) {
|
||||||
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_INLINE, NS_METADATA);
|
if (levelsOption.isMax()) {
|
||||||
writeExpandedNavigationProperty(metadata, property, navigationLink,
|
levels = Integer.MAX_VALUE;
|
||||||
innerOptions == null ? null : innerOptions.getExpandOption(),
|
} else {
|
||||||
innerOptions == null ? null : innerOptions.getSelectOption(),
|
levels = levelsOption.getValue();
|
||||||
innerOptions == null ? null : innerOptions.getCountOption(),
|
}
|
||||||
innerOptions == null ? false : innerOptions.hasCountPath(),
|
|
||||||
innerOptions == null ? false : innerOptions.isRef(),
|
|
||||||
xml10InvalidCharReplacement, writer);
|
|
||||||
writer.writeEndElement();
|
|
||||||
writer.writeEndElement();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
writeLink(writer, getOrCreateLink(linked, propertyName));
|
writeLink(writer, getOrCreateLink(linked, propertyName));
|
||||||
}
|
}
|
||||||
|
@ -676,7 +717,8 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
protected void writeExpandedNavigationProperty(final ServiceMetadata metadata,
|
protected void writeExpandedNavigationProperty(final ServiceMetadata metadata,
|
||||||
final EdmNavigationProperty property, final Link navigationLink,
|
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 boolean writeNavigationCount, final boolean writeOnlyRef,final String xml10InvalidCharReplacement,
|
||||||
final XMLStreamWriter writer) throws XMLStreamException, SerializerException {
|
final XMLStreamWriter writer) throws XMLStreamException, SerializerException {
|
||||||
if (property.isCollection()) {
|
if (property.isCollection()) {
|
||||||
|
@ -688,7 +730,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
if (coutOption != null && coutOption.getValue()) {
|
if (coutOption != null && coutOption.getValue()) {
|
||||||
writeCount(navigationLink.getInlineEntitySet(), writer);
|
writeCount(navigationLink.getInlineEntitySet(), writer);
|
||||||
}
|
}
|
||||||
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand,
|
writeEntitySet(metadata, property.getType(), navigationLink.getInlineEntitySet(), innerExpand, toDepth,
|
||||||
innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef);
|
innerSelect, xml10InvalidCharReplacement, writer, writeOnlyRef);
|
||||||
}
|
}
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
@ -696,7 +738,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
} else {
|
} else {
|
||||||
if (navigationLink != null && navigationLink.getInlineEntity() != null) {
|
if (navigationLink != null && navigationLink.getInlineEntity() != null) {
|
||||||
writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
|
writeEntity(metadata, property.getType(), navigationLink.getInlineEntity(), null,
|
||||||
innerExpand, innerSelect, xml10InvalidCharReplacement, writer, false, writeOnlyRef);
|
innerExpand, toDepth, innerSelect, xml10InvalidCharReplacement, writer, false, writeOnlyRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.CountOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
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.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.SelectItem;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
||||||
import org.apache.olingo.server.core.serializer.ExpandSelectMock;
|
import org.apache.olingo.server.core.serializer.ExpandSelectMock;
|
||||||
|
@ -1357,6 +1358,53 @@ public class ODataJsonSerializerTest {
|
||||||
resultString);
|
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
|
@Test
|
||||||
public void primitiveProperty() throws Exception {
|
public void primitiveProperty() throws Exception {
|
||||||
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
|
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
|
||||||
|
|
Loading…
Reference in New Issue