diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java index 42ddb93ee..abdb2781c 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java @@ -58,6 +58,18 @@ public class BasicStreamITCase extends AbstractBaseTestITCase { assertTrue(content.contains("\"PropertyString\":\"TEST 1->streamed\"")); assertTrue(content.contains("\"PropertyString\":\"TEST 2->streamed\"")); } + + @Test + public void streamESWithStreamJson() throws Exception { + URL url = new URL(SERVICE_URI + "ESWithStream?$expand=PropertyStream&$format=json"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.connect(); + + assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), connection.getResponseCode()); + assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE))); + } @Test public void streamESStreamXml() throws Exception { diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/IConstants.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/IConstants.java new file mode 100644 index 000000000..b20ae952e --- /dev/null +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/IConstants.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.commons.api; + +/** + * Constant values related to the OData protocol. + */ +public interface IConstants { + + public String getMetadata(); + + public String getType(); + + public String getId(); + + public String getReadLink(); + + public String getEditLink(); + + public String getContext(); + + public String getEtag(); + + public String getMediaEtag(); + + public String getMediaContentType(); + + public String getMediaReadLink(); + + public String getMediaEditLink(); + + public String getMetadataEtag(); + + public String getBind(); + + public String getAssociationLink(); + + public String getNavigationLink(); + + public String getCount(); + + public String getNextLink(); + + public String getDeltaLink(); +} diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/constants/Constantsv00.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/constants/Constantsv00.java new file mode 100644 index 000000000..de39b7a02 --- /dev/null +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/constants/Constantsv00.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.commons.api.constants; + +import org.apache.olingo.commons.api.IConstants; + +/** + * Constant values related to the OData protocol. + */ +public final class Constantsv00 implements IConstants{ + + // JSON stuff + public static final String JSON_METADATA = "odata.metadata"; + + public static final String JSON_TYPE = "@odata.type"; + + public static final String JSON_ID = "@odata.id"; + + public static final String JSON_READ_LINK = "@odata.readLink"; + + public static final String JSON_EDIT_LINK = "@odata.editLink"; + + public static final String JSON_CONTEXT = "@odata.context"; + + public static final String JSON_ETAG = "@odata.etag"; + + public static final String JSON_MEDIA_ETAG = "@odata.mediaEtag"; + + public static final String JSON_MEDIA_CONTENT_TYPE = "@odata.mediaContentType"; + + public static final String JSON_MEDIA_READ_LINK = "@odata.mediaReadLink"; + + public static final String JSON_MEDIA_EDIT_LINK = "@odata.mediaEditLink"; + + public static final String JSON_METADATA_ETAG = "@odata.metadataEtag"; + + public static final String JSON_BIND_LINK_SUFFIX = "@odata.bind"; + + public static final String JSON_ASSOCIATION_LINK = "@odata.associationLink"; + + public static final String JSON_NAVIGATION_LINK = "@odata.navigationLink"; + + public static final String JSON_COUNT = "@odata.count"; + + public static final String JSON_NEXT_LINK = "@odata.nextLink"; + + public static final String JSON_DELTA_LINK = "@odata.deltaLink"; + + @Override + public String getMetadata() { + return JSON_METADATA; + } + + @Override + public String getType() { + return JSON_TYPE; + } + + @Override + public String getId() { + return JSON_ID; + } + + @Override + public String getReadLink() { + return JSON_READ_LINK; + } + + @Override + public String getEditLink() { + return JSON_EDIT_LINK; + } + + @Override + public String getContext() { + return JSON_CONTEXT; + } + + @Override + public String getEtag() { + return JSON_ETAG; + } + + @Override + public String getMediaEtag() { + return JSON_MEDIA_ETAG; + } + + @Override + public String getMediaContentType() { + return JSON_MEDIA_CONTENT_TYPE; + } + + @Override + public String getMediaReadLink() { + return JSON_MEDIA_READ_LINK; + } + + @Override + public String getMediaEditLink() { + return JSON_MEDIA_EDIT_LINK; + } + + @Override + public String getMetadataEtag() { + return JSON_METADATA_ETAG; + } + + @Override + public String getBind() { + return JSON_BIND_LINK_SUFFIX; + } + + @Override + public String getAssociationLink() { + return JSON_ASSOCIATION_LINK; + } + + @Override + public String getNavigationLink() { + return JSON_NAVIGATION_LINK; + } + + @Override + public String getCount() { + return JSON_COUNT; + } + + @Override + public String getNextLink() { + return JSON_NEXT_LINK; + } + + @Override + public String getDeltaLink() { + return JSON_DELTA_LINK; + } +} diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/constants/Constantsv01.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/constants/Constantsv01.java new file mode 100644 index 000000000..9954e4a2d --- /dev/null +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/constants/Constantsv01.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.commons.api.constants; + +import org.apache.olingo.commons.api.IConstants; + +/** + * Constant values related to the OData protocol. + */ +public final class Constantsv01 implements IConstants{ + + // JSON stuff + public static final String JSON_METADATA = "metadata"; + + public static final String JSON_TYPE = "@type"; + + public static final String JSON_ID = "@id"; + + public static final String JSON_READ_LINK = "@readLink"; + + public static final String JSON_EDIT_LINK = "@editLink"; + + public static final String JSON_CONTEXT = "@context"; + + public static final String JSON_ETAG = "@etag"; + + public static final String JSON_MEDIA_ETAG = "@mediaEtag"; + + public static final String JSON_MEDIA_CONTENT_TYPE = "@mediaContentType"; + + public static final String JSON_MEDIA_READ_LINK = "@mediaReadLink"; + + public static final String JSON_MEDIA_EDIT_LINK = "@mediaEditLink"; + + public static final String JSON_METADATA_ETAG = "@metadataEtag"; + + public static final String JSON_BIND_LINK_SUFFIX = "@bind"; + + public static final String JSON_ASSOCIATION_LINK = "@associationLink"; + + public static final String JSON_NAVIGATION_LINK = "@navigationLink"; + + public static final String JSON_COUNT = "@count"; + + public static final String JSON_NEXT_LINK = "@nextLink"; + + public static final String JSON_DELTA_LINK = "@deltaLink"; + + @Override + public String getMetadata() { + return JSON_METADATA; + } + + @Override + public String getType() { + return JSON_TYPE; + } + + @Override + public String getId() { + return JSON_ID; + } + + @Override + public String getReadLink() { + return JSON_READ_LINK; + } + + @Override + public String getEditLink() { + return JSON_EDIT_LINK; + } + + @Override + public String getContext() { + return JSON_CONTEXT; + } + + @Override + public String getEtag() { + return JSON_ETAG; + } + + @Override + public String getMediaEtag() { + return JSON_MEDIA_ETAG; + } + + @Override + public String getMediaContentType() { + return JSON_MEDIA_CONTENT_TYPE; + } + + @Override + public String getMediaReadLink() { + return JSON_MEDIA_READ_LINK; + } + + @Override + public String getMediaEditLink() { + return JSON_MEDIA_EDIT_LINK; + } + + @Override + public String getMetadataEtag() { + return JSON_METADATA_ETAG; + } + + @Override + public String getBind() { + return JSON_BIND_LINK_SUFFIX; + } + + @Override + public String getAssociationLink() { + return JSON_ASSOCIATION_LINK; + } + + @Override + public String getNavigationLink() { + return JSON_NAVIGATION_LINK; + } + + @Override + public String getCount() { + return JSON_COUNT; + } + + @Override + public String getNextLink() { + return JSON_NEXT_LINK; + } + + @Override + public String getDeltaLink() { + return JSON_DELTA_LINK; + } +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java index 9e0041396..16cca295d 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/OData.java @@ -78,6 +78,16 @@ public abstract class OData { * @param contentType any format supported by Olingo (XML, JSON ...) */ public abstract ODataSerializer createSerializer(ContentType contentType) throws SerializerException; + + /** + * Creates a new serializer object for rendering content in the specified format. + * Serializers are used in Processor implementations. + * + * @param contentType any format supported by Olingo (XML, JSON ...) + * @param versions any v4 version supported by Olingo (4.0, 4.01 ...) + */ + public abstract ODataSerializer createSerializer(ContentType contentType, + final List versions) throws SerializerException; /** * Creates a new serializer object for rendering content in a fixed format, e.g., for binary output or multipart/mixed diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java index 62a0dd564..ebb301bc0 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/SerializerException.java @@ -51,6 +51,7 @@ public class SerializerException extends ODataLibraryException { WRONG_PRIMITIVE_VALUE, UNKNOWN_TYPE, WRONG_BASE_TYPE, + UNSUPPORTED_OPERATION_TYPE, /** parameter: encoding-name */ UNSUPPORTED_ENCODING; diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java index ef42e6279..c657952c2 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java @@ -21,6 +21,9 @@ package org.apache.olingo.server.core; import java.util.Collection; import java.util.List; +import org.apache.olingo.commons.api.constants.Constantsv00; +import org.apache.olingo.commons.api.constants.Constantsv01; +import org.apache.olingo.commons.api.IConstants; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; @@ -71,7 +74,36 @@ public class ODataImpl extends OData { || ContentType.VALUE_ODATA_METADATA_MINIMAL.equalsIgnoreCase(metadata) || ContentType.VALUE_ODATA_METADATA_NONE.equalsIgnoreCase(metadata) || ContentType.VALUE_ODATA_METADATA_FULL.equalsIgnoreCase(metadata)) { - serializer = new ODataJsonSerializer(contentType); + serializer = new ODataJsonSerializer(contentType, new Constantsv00()); + } + } else if (contentType.isCompatible(ContentType.APPLICATION_XML) + || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)) { + serializer = new ODataXmlSerializer(); + } + + if (serializer == null) { + throw new SerializerException("Unsupported format: " + contentType.toContentTypeString(), + SerializerException.MessageKeys.UNSUPPORTED_FORMAT, contentType.toContentTypeString()); + } else { + return serializer; + } + } + + @Override + public ODataSerializer createSerializer(final ContentType contentType, + final List versions) throws SerializerException { + ODataSerializer serializer = null; + IConstants constants = new Constantsv00(); + if(versions!=null && versions.size()>0 && getMaxVersion(versions)>4){ + constants = new Constantsv01() ; + } + if (contentType.isCompatible(ContentType.APPLICATION_JSON)) { + final String metadata = contentType.getParameter(ContentType.PARAMETER_ODATA_METADATA); + if (metadata == null + || ContentType.VALUE_ODATA_METADATA_MINIMAL.equalsIgnoreCase(metadata) + || ContentType.VALUE_ODATA_METADATA_NONE.equalsIgnoreCase(metadata) + || ContentType.VALUE_ODATA_METADATA_FULL.equalsIgnoreCase(metadata)) { + serializer = new ODataJsonSerializer(contentType, constants); } } else if (contentType.isCompatible(ContentType.APPLICATION_XML) || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java index 8f6b21371..9cc6e81bf 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java @@ -27,10 +27,10 @@ import org.apache.olingo.commons.api.data.EntityIterator; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.server.api.ODataContent; -import org.apache.olingo.server.api.ODataLibraryException; -import org.apache.olingo.server.api.ServiceMetadata; import org.apache.olingo.server.api.ODataContentWriteErrorCallback; import org.apache.olingo.server.api.ODataContentWriteErrorContext; +import org.apache.olingo.server.api.ODataLibraryException; +import org.apache.olingo.server.api.ServiceMetadata; import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.SerializerException; @@ -181,7 +181,7 @@ public class ODataWritableContent implements ODataContent { StreamContent input = new StreamContentForJson(entities, entityType, (ODataJsonSerializer) serializer, metadata, options); return new ODataWritableContent(input); - } else if (serializer instanceof ODataXmlSerializer) { + }else if (serializer instanceof ODataXmlSerializer) { StreamContentForXml input = new StreamContentForXml(entities, entityType, (ODataXmlSerializer) serializer, metadata, options); return new ODataWritableContent(input); 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 dabfea32d..249e82128 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 @@ -28,7 +28,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; import org.apache.olingo.commons.api.Constants; +import org.apache.olingo.commons.api.IConstants; +import org.apache.olingo.commons.api.constants.Constantsv00; import org.apache.olingo.commons.api.data.AbstractEntityCollection; import org.apache.olingo.commons.api.data.ComplexValue; import org.apache.olingo.commons.api.data.ContextURL; @@ -109,11 +113,20 @@ public class ODataJsonSerializer extends AbstractODataSerializer { private final boolean isIEEE754Compatible; private final boolean isODataMetadataNone; private final boolean isODataMetadataFull; + private IConstants constants; + + public ODataJsonSerializer(final ContentType contentType, final IConstants constants) { + isIEEE754Compatible = ContentTypeHelper.isODataIEEE754Compatible(contentType); + isODataMetadataNone = ContentTypeHelper.isODataMetadataNone(contentType); + isODataMetadataFull = ContentTypeHelper.isODataMetadataFull(contentType); + this.constants = constants; + } public ODataJsonSerializer(final ContentType contentType) { isIEEE754Compatible = ContentTypeHelper.isODataIEEE754Compatible(contentType); isODataMetadataNone = ContentTypeHelper.isODataMetadataNone(contentType); isODataMetadataFull = ContentTypeHelper.isODataMetadataFull(contentType); + this.constants = new Constantsv00(); } @Override @@ -208,6 +221,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { cachedException = new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); throw cachedException; + } catch (DecoderException e) { + cachedException = + new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + throw cachedException; } finally { closeCircleStreamBufferOutput(outputStream, cachedException); } @@ -255,6 +272,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { cachedException = new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); throw cachedException; + } catch (DecoderException e) { + cachedException = + new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + throw cachedException; } } @@ -284,6 +305,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { cachedException = new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); throw cachedException; + } catch (DecoderException e) { + cachedException = + new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + throw cachedException; } finally { closeCircleStreamBufferOutput(outputStream, cachedException); } @@ -301,12 +326,12 @@ 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 ancestors, String name, final JsonGenerator json) - throws IOException, SerializerException { + throws IOException, SerializerException, DecoderException { json.writeStartArray(); for (final Entity entity : entitySet) { if (onlyReference) { json.writeStartObject(); - json.writeStringField(Constants.JSON_ID, getEntityId(entity, entityType, name)); + json.writeStringField(constants.getId(), getEntityId(entity, entityType, name)); json.writeEndObject(); } else { writeEntity(metadata, entityType, entity, null, expand, toDepth, select, false, ancestors, name, json); @@ -354,7 +379,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { final ContextURL contextURL, final ExpandOption expand, Integer toDepth, final SelectOption select, final boolean onlyReference, Set ancestors, String name, final JsonGenerator json) - throws IOException, SerializerException { + throws IOException, SerializerException, DecoderException { boolean cycle = false; if (expand != null) { if (ancestors == null) { @@ -371,44 +396,45 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeMetadataETag(metadata, json); } if (entity.getETag() != null) { - json.writeStringField(Constants.JSON_ETAG, entity.getETag()); + json.writeStringField(constants.getEtag(), entity.getETag()); } if (entityType.hasStream()) { if (entity.getMediaETag() != null) { - json.writeStringField(Constants.JSON_MEDIA_ETAG, entity.getMediaETag()); + json.writeStringField(constants.getMediaEtag(), entity.getMediaETag()); } if (entity.getMediaContentType() != null) { - json.writeStringField(Constants.JSON_MEDIA_CONTENT_TYPE, entity.getMediaContentType()); + json.writeStringField(constants.getMediaContentType(), entity.getMediaContentType()); } if (entity.getMediaContentSource() != null) { - json.writeStringField(Constants.JSON_MEDIA_READ_LINK, entity.getMediaContentSource().toString()); + json.writeStringField(constants.getMediaReadLink(), entity.getMediaContentSource().toString()); } if (entity.getMediaEditLinks() != null && !entity.getMediaEditLinks().isEmpty()) { - json.writeStringField(Constants.JSON_MEDIA_EDIT_LINK, entity.getMediaEditLinks().get(0).getHref()); + json.writeStringField(constants.getMediaEditLink(), entity.getMediaEditLinks().get(0).getHref()); } } } if (cycle || onlyReference) { - json.writeStringField(Constants.JSON_ID, getEntityId(entity, entityType, name)); + json.writeStringField(constants.getId(), 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()); + json.writeStringField(constants.getType(), "#" + entity.getType()); } if ((!isODataMetadataNone && !areKeyPredicateNamesSelected(select, resolvedType)) || isODataMetadataFull) { - json.writeStringField(Constants.JSON_ID, getEntityId(entity, resolvedType, name)); + json.writeStringField(constants.getId(), getEntityId(entity, resolvedType, name)); } if (isODataMetadataFull) { if (entity.getSelfLink() != null) { - json.writeStringField(Constants.JSON_READ_LINK, entity.getSelfLink().getHref()); + json.writeStringField(constants.getReadLink(), entity.getSelfLink().getHref()); } if (entity.getEditLink() != null) { - json.writeStringField(Constants.JSON_EDIT_LINK, entity.getEditLink().getHref()); + json.writeStringField(constants.getEditLink(), entity.getEditLink().getHref()); } } writeProperties(metadata, resolvedType, entity.getProperties(), select, json); + writeExpandedStreamProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, name, json); writeNavigationProperties(metadata, resolvedType, entity, expand, toDepth, ancestors, name, json); writeOperations(entity.getOperations(), json); } @@ -501,16 +527,16 @@ 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 ancestors, final String name, final JsonGenerator json) - throws SerializerException, IOException { + throws SerializerException, IOException, DecoderException { if (isODataMetadataFull) { for (final String propertyName : type.getNavigationPropertyNames()) { final Link navigationLink = linked.getNavigationLink(propertyName); if (navigationLink != null) { - json.writeStringField(propertyName + Constants.JSON_NAVIGATION_LINK, navigationLink.getHref()); + json.writeStringField(propertyName + constants.getNavigationLink(), navigationLink.getHref()); } final Link associationLink = linked.getAssociationLink(propertyName); if (associationLink != null) { - json.writeStringField(propertyName + Constants.JSON_ASSOCIATION_LINK, associationLink.getHref()); + json.writeStringField(propertyName + constants.getAssociationLink(), associationLink.getHref()); } } } @@ -555,12 +581,51 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } } + protected void writeExpandedStreamProperties(final ServiceMetadata metadata, + final EdmStructuredType type, final Linked linked, final ExpandOption expand, final Integer toDepth, + final Set ancestors, final String name, final JsonGenerator json) + throws SerializerException, IOException, DecoderException { + + if (ExpandSelectHelper.hasExpand(expand)) { + final ExpandItem expandAll = ExpandSelectHelper.getExpandAll(expand); + for (final String propertyName : type.getPropertyNames()) { + EdmProperty edmProperty = (EdmProperty) type.getProperty(propertyName); + if(isStreamProperty(edmProperty) ){ + writeExpandedStreamProperty(expand, propertyName, edmProperty, linked, expandAll, json); + } + } + } + } + + private void writeExpandedStreamProperty(ExpandOption expand, String propertyName, EdmProperty edmProperty, + Linked linked, ExpandItem expandAll, JsonGenerator json) throws SerializerException, + DecoderException, IOException { + final ExpandItem innerOptions = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); + if (innerOptions != null || expandAll != null) { + if(constants instanceof Constantsv00){ + throw new SerializerException("Expand not supported for Stream Property Type!", + SerializerException.MessageKeys.UNSUPPORTED_OPERATION_TYPE, "expand", edmProperty.getName()); + } + Entity entity = (Entity) linked; + final Property property = (Property) entity.getProperty(propertyName); + if((property == null || property.isNull()) && edmProperty.isNullable() == Boolean.FALSE ){ + throw new SerializerException("Non-nullable property not present!", + SerializerException.MessageKeys.MISSING_PROPERTY, edmProperty.getName()); + } + Link link = (Link) property.getValue(); + Property stream = link.getInlineEntity().getProperty(propertyName); + Base64 decoder = new Base64(true); + byte[] decodedBytes = (byte[]) decoder.decode(stream.getValue()); + json.writeStringField(propertyName, new String(decodedBytes)); + } + } + protected void writeExpandedNavigationProperty( final ServiceMetadata metadata, final EdmNavigationProperty property, final Link navigationLink, final ExpandOption innerExpand, Integer toDepth, final SelectOption innerSelect, final CountOption innerCount, final boolean writeOnlyCount, final boolean writeOnlyRef, final Set ancestors, - String name, final JsonGenerator json) throws IOException, SerializerException { + String name, final JsonGenerator json) throws IOException, SerializerException, DecoderException { if (property.isCollection()) { if (writeOnlyCount) { @@ -612,7 +677,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeFieldName(edmProperty.getName()); } if (property == null || property.isNull()) { - if (edmProperty.isNullable() == Boolean.FALSE) { + if (edmProperty.isNullable() == Boolean.FALSE && !isStreamProperty) { throw new SerializerException("Non-nullable property not present!", SerializerException.MessageKeys.MISSING_PROPERTY, edmProperty.getName()); } else { @@ -635,7 +700,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { if (!isODataMetadataFull) { return; } - String typeName = edmProperty.getName() + Constants.JSON_TYPE; + String typeName = edmProperty.getName() + constants.getType(); final EdmType type = edmProperty.getType(); if (type.getKind() == EdmTypeKind.ENUM || type.getKind() == EdmTypeKind.DEFINITION) { if (edmProperty.isCollection()) { @@ -720,7 +785,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { resolvedType = resolveComplexType(metadata, type, derivedName); } if (!isODataMetadataNone && !resolvedType.equals(type) || isODataMetadataFull) { - json.writeStringField(Constants.JSON_TYPE, "#" + + json.writeStringField(constants.getType(), "#" + resolvedType.getFullQualifiedName().getFullQualifiedNameAsString()); } writeComplexValue(metadata, resolvedType, property.asComplex().getValue(), selectedPaths, @@ -768,7 +833,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { case COLLECTION_COMPLEX: json.writeStartObject(); if (isODataMetadataFull || (!isODataMetadataNone && !derivedType.equals(type))) { - json.writeStringField(Constants.JSON_TYPE, "#" + + json.writeStringField(constants.getType(), "#" + derivedType.getFullQualifiedName().getFullQualifiedNameAsString()); } writeComplexValue(metadata, derivedType, ((ComplexValue) value).getValue(), selectedPaths, json); @@ -824,18 +889,18 @@ public class ODataJsonSerializer extends AbstractODataSerializer { Link stream = (Link)primitiveValue; if (!isODataMetadataNone) { if (stream.getMediaETag() != null) { - json.writeStringField(name+Constants.JSON_MEDIA_ETAG, stream.getMediaETag()); + json.writeStringField(name+constants.getMediaEtag(), stream.getMediaETag()); } if (stream.getType() != null) { - json.writeStringField(name+Constants.JSON_MEDIA_CONTENT_TYPE, stream.getType()); + json.writeStringField(name+constants.getMediaContentType(), stream.getType()); } } if (isODataMetadataFull) { if (stream.getRel() != null && stream.getRel().equals(Constants.NS_MEDIA_READ_LINK_REL)) { - json.writeStringField(name+Constants.JSON_MEDIA_READ_LINK, stream.getHref()); + json.writeStringField(name+constants.getMediaReadLink(), stream.getHref()); } if (stream.getRel() == null || stream.getRel().equals(Constants.NS_MEDIA_EDIT_LINK_REL)) { - json.writeStringField(name+Constants.JSON_MEDIA_EDIT_LINK, stream.getHref()); + json.writeStringField(name+constants.getMediaEditLink(), stream.getHref()); } } } @@ -1035,7 +1100,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { resolvedType = resolveComplexType(metadata, type, property.getType()); } if (!isODataMetadataNone && !resolvedType.equals(type) || isODataMetadataFull) { - json.writeStringField(Constants.JSON_TYPE, "#" + + json.writeStringField(constants.getType(), "#" + resolvedType.getFullQualifiedName().getFullQualifiedNameAsString()); } writeOperations(property.getOperations(), json); @@ -1055,6 +1120,10 @@ public class ODataJsonSerializer extends AbstractODataSerializer { cachedException = new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); throw cachedException; + } catch (DecoderException e) { + cachedException = + new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + throw cachedException; } finally { closeCircleStreamBufferOutput(outputStream, cachedException); } @@ -1074,7 +1143,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeContextURL(contextURL, json); writeMetadataETag(metadata, json); if (isODataMetadataFull) { - json.writeStringField(Constants.JSON_TYPE, "#Collection("+type.getFullQualifiedName().getName()+")"); + json.writeStringField(constants.getType(), "#Collection("+type.getFullQualifiedName().getName()+")"); } writeOperations(property.getOperations(), json); json.writeFieldName(Constants.VALUE); @@ -1112,7 +1181,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { writeContextURL(contextURL, json); writeMetadataETag(metadata, json); if (isODataMetadataFull) { - json.writeStringField(Constants.JSON_TYPE, + json.writeStringField(constants.getType(), "#Collection(" + type.getFullQualifiedName().getFullQualifiedNameAsString() + ")"); } writeOperations(property.getOperations(), json); @@ -1147,7 +1216,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeStartObject(); writeContextURL(contextURL, json); - json.writeStringField(Constants.JSON_ID, uriHelper.buildCanonicalURL(edmEntitySet, entity)); + json.writeStringField(constants.getId(), uriHelper.buildCanonicalURL(edmEntitySet, entity)); json.writeEndObject(); json.close(); @@ -1186,7 +1255,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { json.writeArrayFieldStart(Constants.VALUE); for (final Entity entity : entityCollection) { json.writeStartObject(); - json.writeStringField(Constants.JSON_ID, uriHelper.buildCanonicalURL(edmEntitySet, entity)); + json.writeStringField(constants.getId(), uriHelper.buildCanonicalURL(edmEntitySet, entity)); json.writeEndObject(); } json.writeEndArray(); @@ -1210,7 +1279,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { void writeContextURL(final ContextURL contextURL, final JsonGenerator json) throws IOException { if (!isODataMetadataNone && contextURL != null) { - json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString()); + json.writeStringField(constants.getContext(), ContextURLBuilder.create(contextURL).toASCIIString()); } } @@ -1219,7 +1288,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { && metadata != null && metadata.getServiceMetadataETagSupport() != null && metadata.getServiceMetadataETagSupport().getMetadataETag() != null) { - json.writeStringField(Constants.JSON_METADATA_ETAG, + json.writeStringField(constants.getMetadataEtag(), metadata.getServiceMetadataETagSupport().getMetadataETag()); } } @@ -1228,9 +1297,9 @@ public class ODataJsonSerializer extends AbstractODataSerializer { throws IOException { if (count != null) { if (isIEEE754Compatible) { - json.writeStringField(propertyName + Constants.JSON_COUNT, String.valueOf(count)); + json.writeStringField(propertyName + constants.getCount(), String.valueOf(count)); } else { - json.writeNumberField(propertyName + Constants.JSON_COUNT, count); + json.writeNumberField(propertyName + constants.getCount(), count); } } } @@ -1239,7 +1308,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { throws IOException { if (entitySet.getNext() != null) { pagination = true; - json.writeStringField(Constants.JSON_NEXT_LINK, entitySet.getNext().toASCIIString()); + json.writeStringField(constants.getNextLink(), entitySet.getNext().toASCIIString()); }else{ pagination = false; } @@ -1248,7 +1317,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { void writeDeltaLink(final AbstractEntityCollection entitySet, final JsonGenerator json, boolean pagination) throws IOException { if (entitySet.getDeltaLink() != null && !pagination) { - json.writeStringField(Constants.JSON_DELTA_LINK, entitySet.getDeltaLink().toASCIIString()); + json.writeStringField(constants.getDeltaLink(), entitySet.getDeltaLink().toASCIIString()); } } } 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 981b302c6..9633f70f8 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 @@ -141,8 +141,10 @@ public abstract class ExpandSelectHelper { continue; } final UriResource resource = item.getResourcePath().getUriResourceParts().get(0); - if (resource instanceof UriResourceNavigation - && propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) { + if ((resource instanceof UriResourceNavigation + && propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) || + resource instanceof UriResourceProperty + && propertyName.equals(((UriResourceProperty) resource).getProperty().getName())) { return item; } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java index 60e858d5e..1138a572f 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java @@ -23,10 +23,12 @@ import java.util.Map; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmStructuredType; import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; import org.apache.olingo.commons.api.ex.ODataRuntimeException; +import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.uri.UriInfoKind; import org.apache.olingo.server.api.uri.UriResourceNavigation; @@ -42,6 +44,7 @@ import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl; import org.apache.olingo.server.core.uri.UriResourceCountImpl; import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl; import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl; +import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl; import org.apache.olingo.server.core.uri.UriResourceRefImpl; import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind; import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl; @@ -154,27 +157,31 @@ public class ExpandParser { } } } - - final EdmStructuredType newReferencedType = typeCastSuffix != null ? typeCastSuffix - : (EdmStructuredType) lastPart.getType(); - final boolean newReferencedIsCollection = lastPart.isCollection(); - if (hasSlash || tokenizer.next(TokenKind.SLASH)) { - if (tokenizer.next(TokenKind.REF)) { - resource.addResourcePart(new UriResourceRefImpl()); - item.setIsRef(true); - parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, true, false); + //For handling $expand for Stream property in v 4.01 + if(lastPart instanceof UriResourcePrimitivePropertyImpl){ + item.setResourcePath(resource); + }else{ + final EdmStructuredType newReferencedType = typeCastSuffix != null ? typeCastSuffix + : (EdmStructuredType) lastPart.getType(); + final boolean newReferencedIsCollection = lastPart.isCollection(); + if (hasSlash || tokenizer.next(TokenKind.SLASH)) { + if (tokenizer.next(TokenKind.REF)) { + resource.addResourcePart(new UriResourceRefImpl()); + item.setIsRef(true); + parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, true, false); + } else { + ParserHelper.requireNext(tokenizer, TokenKind.COUNT); + resource.addResourcePart(new UriResourceCountImpl()); + item.setCountPath(true); + parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, true); + } } else { - ParserHelper.requireNext(tokenizer, TokenKind.COUNT); - resource.addResourcePart(new UriResourceCountImpl()); - item.setCountPath(true); - parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, true); + parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, false); } - } else { - parseOptions(tokenizer, newReferencedType, newReferencedIsCollection, item, false, false); + + item.setResourcePath(resource); } - - item.setResourcePath(resource); - } + } return item; } @@ -204,7 +211,12 @@ public class ExpandParser { final EdmNavigationProperty navigationProperty = type.getNavigationProperty(name); if (navigationProperty == null) { - if (tokenizer.next(TokenKind.STAR)) { + //For handling $expand with Stream Properties in version 4.01 + final EdmProperty streamProperty = (EdmProperty) type.getProperty(name); + if(streamProperty != null && streamProperty.getType() == EdmPrimitiveTypeFactory. + getInstance(EdmPrimitiveTypeKind.Stream)){ + resource.addResourcePart(new UriResourcePrimitivePropertyImpl(streamProperty)); + }else if (tokenizer.next(TokenKind.STAR)) { item.setIsStar(true); } else { throw new UriParserSemanticException( diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties index 085afec7e..2589abdb2 100644 --- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties +++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties @@ -111,6 +111,7 @@ SerializerException.IO_EXCEPTION=An I/O exception occurred. SerializerException.NULL_INPUT=The input 'null' is not allowed here. SerializerException.NO_CONTEXT_URL=No context URL has been provided. SerializerException.UNSUPPORTED_PROPERTY_TYPE=The type of the property '%1$s' is not yet supported. +SerializerException.UNSUPPORTED_OPERATION_TYPE=The '%1$s' operation is not supported for '%2$s'. SerializerException.MISSING_DELTA_PROPERTY=The delta property '%1$s' is missing. SerializerException.INCONSISTENT_PROPERTY_TYPE=An inconsistency has been detected in the type definition of property '%1$s'. SerializerException.MISSING_PROPERTY=The non-nullable property '%1$s' is missing. diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java index 4221f922c..2bed5a211 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java @@ -1379,7 +1379,9 @@ public class DataCreator { Link readLink = new Link(); readLink.setRel(Constants.NS_MEDIA_READ_LINK_REL); readLink.setHref("readLink"); - + Entity entity = new Entity(); + entity.addProperty(createPrimitive("PropertyStream", createImage("darkturquoise"))); + readLink.setInlineEntity(entity); entityCollection.getEntities().add(new Entity() .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE)) .addProperty(new Property(null, "PropertyStream", ValueType.PRIMITIVE, readLink))); @@ -1389,6 +1391,9 @@ public class DataCreator { editLink.setHref("http://mediaserver:1234/editLink"); editLink.setMediaETag("eTag"); editLink.setType("image/jpeg"); + entity = new Entity(); + entity.addProperty(createPrimitive("PropertyStream", createImage("royalblue"))); + editLink.setInlineEntity(entity); entityCollection.getEntities().add(new Entity() .addProperty(createPrimitive("PropertyInt16", (short) 7)) diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java index 0a90d120a..c76f04b3f 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java @@ -53,8 +53,8 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.EdmProperty; -import org.apache.olingo.commons.api.edm.EdmStructuredType; import org.apache.olingo.commons.api.edm.EdmSingleton; +import org.apache.olingo.commons.api.edm.EdmStructuredType; import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.edm.EdmTypeDefinition; import org.apache.olingo.commons.api.edm.FullQualifiedName; @@ -859,4 +859,15 @@ public class DataProvider { } return null; } + + public byte[] readStreamProperty(Property property) { + Link link; + if(property!=null && property.getValue()!=null){ + link = (Link)property.getValue(); + if(link.getInlineEntity()!=null){ + return (byte[]) link.getInlineEntity().getProperty(property.getName()).getValue(); + } + } + return null; + } } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index ad4b82fcb..207a0f275 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -709,7 +709,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final ContentType requestedFormat, final ExpandOption expand, final SelectOption select, final CountOption countOption, String id) throws ODataLibraryException { - return odata.createSerializer(requestedFormat).entityCollection( + return odata.createSerializer(requestedFormat, request.getHeaders(HttpHeader.ODATA_VERSION)) + .entityCollection( serviceMetadata, edmEntityType, entityCollection, @@ -836,7 +837,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor ContextURL contextUrl = isODataMetadataNone(requestedFormat) ? null : getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, true, expand, null); - return odata.createSerializer(requestedFormat).entity( + return odata.createSerializer(requestedFormat, request.getHeaders(HttpHeader.ODATA_VERSION)).entity( serviceMetadata, edmEntityType, entity, diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java index 6930d0761..2a99ea9aa 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java @@ -27,6 +27,7 @@ import java.util.Locale; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Builder; import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.Link; import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.edm.EdmComplexType; import org.apache.olingo.commons.api.edm.EdmEntitySet; @@ -84,6 +85,8 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor PrimitiveCollectionProcessor, CountPrimitiveCollectionProcessor, ComplexProcessor, ComplexCollectionProcessor, CountComplexCollectionProcessor { + private static final Object EDMSTREAM = "Edm.Stream"; + public TechnicalPrimitiveComplexProcessor(final DataProvider dataProvider, final ServiceMetadata serviceMetadata) { super(dataProvider, serviceMetadata); @@ -264,7 +267,15 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor if (representationType == RepresentationType.VALUE) { response.setContent(serializePrimitiveValue(property, edmProperty, (EdmPrimitiveType) type, returnType)); - } else { + }else if(representationType == RepresentationType.PRIMITIVE && type.getFullQualifiedName() + .getFullQualifiedNameAsString().equals(EDMSTREAM)){ + response.setContent(odata.createFixedFormatSerializer().binary(dataProvider.readStreamProperty(property))); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, ((Link)property.getValue()).getType()); + if (entity.getMediaETag() != null) { + response.setHeader(HttpHeader.ETAG, entity.getMediaETag()); + } + }else { final ExpandOption expand = uriInfo.getExpandOption(); final SelectOption select = uriInfo.getSelectOption(); final SerializerResult result = serializeProperty(entity, edmEntitySet, path, property, edmProperty, 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 ef7880e99..f0922469a 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 @@ -1037,7 +1037,18 @@ public class ODataJsonSerializerTest { + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}"; Assert.assertEquals(expectedResult, resultString); } - + @Test(expected = SerializerException.class) + public void entityWithStreamExpand() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream"); + final EntityCollection collection = data.readAll(edmEntitySet); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "PropertyStream"))); + serializer.entityCollection(metadata, edmEntitySet.getEntityType(), collection, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .expand(expand).build()).getContent(); + } + @Test public void entityMedia() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerv01Test.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerv01Test.java new file mode 100644 index 000000000..3b4187373 --- /dev/null +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerv01Test.java @@ -0,0 +1,2533 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.server.core.serializer.json; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.olingo.commons.api.IConstants; +import org.apache.olingo.commons.api.constants.Constantsv01; +import org.apache.olingo.commons.api.data.ComplexValue; +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.ContextURL.Suffix; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.EntityIterator; +import org.apache.olingo.commons.api.data.Operation; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.data.ValueType; +import org.apache.olingo.commons.api.edm.EdmComplexType; +import org.apache.olingo.commons.api.edm.EdmEntityContainer; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.edm.geo.Point; +import org.apache.olingo.commons.api.edm.geo.Polygon; +import org.apache.olingo.commons.api.edm.geo.SRID; +import org.apache.olingo.commons.api.edm.geo.Geospatial.Dimension; +import org.apache.olingo.commons.api.edm.geo.GeospatialCollection; +import org.apache.olingo.commons.api.edm.geo.LineString; +import org.apache.olingo.commons.api.edm.geo.MultiLineString; +import org.apache.olingo.commons.api.edm.geo.MultiPoint; +import org.apache.olingo.commons.api.edm.geo.MultiPolygon; +import org.apache.olingo.commons.api.edmx.EdmxReference; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataContent; +import org.apache.olingo.server.api.ODataContentWriteErrorCallback; +import org.apache.olingo.server.api.ODataContentWriteErrorContext; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.serializer.ComplexSerializerOptions; +import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; +import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions; +import org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOptions; +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.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; +import org.apache.olingo.server.tecsvc.MetadataETagSupport; +import org.apache.olingo.server.tecsvc.data.DataProvider; +import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class ODataJsonSerializerv01Test { + private static final OData odata = OData.newInstance(); + private static final ServiceMetadata metadata = odata.createServiceMetadata( + new EdmTechProvider(), Collections. emptyList(), new MetadataETagSupport("W/\"metadataETag\"")); + private static final EdmEntityContainer entityContainer = metadata.getEdm().getEntityContainer(); + private final DataProvider data = new DataProvider(odata, metadata.getEdm()); + private final IConstants constants = new Constantsv01(); + private final ODataSerializer serializer = new ODataJsonSerializer(ContentType.JSON, constants); + private final ODataSerializer serializerNoMetadata = new ODataJsonSerializer( + ContentType.JSON_NO_METADATA, constants); + private final ODataSerializer serializerFullMetadata = new ODataJsonSerializer( + ContentType.JSON_FULL_METADATA, constants); + private final ODataSerializer serializerIEEECompatible = + new ODataJsonSerializer(ContentType.create(ContentType.JSON, + ContentType.PARAMETER_IEEE754_COMPATIBLE, "true"), + constants); + private final UriHelper helper = odata.createUriHelper(); + + @Test + public void entitySimple() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"$metadata#ESAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte\":255," + + "\"PropertySByte\":127," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"" + + "}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entitySimpleMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializerFullMetadata.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{\"@context\":\"$metadata#ESAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@type\":\"#olingo.odata.test1.ETAllPrim\"," + + "\"@id\":\"ESAllPrim(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte@type\":\"#Byte\"," + + "\"PropertyByte\":255," + + "\"PropertySByte@type\":\"#SByte\"," + + "\"PropertySByte\":127," + + "\"PropertyInt32@type\":\"#Int32\"," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64@type\":\"#Int64\"," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle@type\":\"#Single\"," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal@type\":\"#Decimal\"," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary@type\":\"#Binary\"," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate@type\":\"#Date\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset@type\":\"#DateTimeOffset\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration@type\":\"#Duration\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid@type\":\"#Guid\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay@type\":\"#TimeOfDay\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"," + + "\"NavPropertyETTwoPrimOne@navigationLink\":\"ESTwoPrim(32767)\"," + + "\"NavPropertyETTwoPrimMany@navigationLink\":\"ESAllPrim(32767)/NavPropertyETTwoPrimMany\"," + + "\"#olingo.odata.test1.BAETAllPrimRT\":{" + + "\"title\":\"olingo.odata.test1.BAETAllPrimRT\"," + + "\"target\":\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\"" + + "}}"; + + Assert.assertEquals(expected, resultString); + } + + @Test + public void entitySetMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityCollection entityCol = data.readAll(edmEntitySet); + InputStream result = serializerFullMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), entityCol, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{" + + "\"@context\":\"$metadata#ESAllPrim\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"#olingo.odata.test1.BAESAllPrimRTETAllPrim\":{" + + "\"title\":\"olingo.odata.test1.BAESAllPrimRTETAllPrim\"," + + "\"target\":\"ESAllPrim/olingo.odata.test1.BAESAllPrimRTETAllPrim\"" + + "}," + + "\"#olingo.odata.test1.BAESAllPrimRT\":{" + + "\"title\":\"olingo.odata.test1.BAESAllPrimRT\"," + + "\"target\":\"ESAllPrim/olingo.odata.test1.BAESAllPrimRT\"" + + "}," + + "\"#olingo.odata.test1.BFNESAllPrimRTCTAllPrim\":{" + + "\"title\":\"olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"," + + "\"target\":\"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"" + + "}," + + "\"value\":[" + + "{" + + "\"@type\":\"#olingo.odata.test1.ETAllPrim\"," + + "\"@id\":\"ESAllPrim(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte@type\":\"#Byte\"," + + "\"PropertyByte\":255," + + "\"PropertySByte@type\":\"#SByte\"," + + "\"PropertySByte\":127," + + "\"PropertyInt32@type\":\"#Int32\"," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64@type\":\"#Int64\"," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle@type\":\"#Single\"," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal@type\":\"#Decimal\"," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary@type\":\"#Binary\"," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate@type\":\"#Date\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset@type\":\"#DateTimeOffset\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration@type\":\"#Duration\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid@type\":\"#Guid\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay@type\":\"#TimeOfDay\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"," + + "\"NavPropertyETTwoPrimOne@navigationLink\":\"ESTwoPrim(32767)\"," + + "\"NavPropertyETTwoPrimMany@navigationLink\":\"ESAllPrim(32767)/NavPropertyETTwoPrimMany\"," + + "\"#olingo.odata.test1.BAETAllPrimRT\":{" + + "\"title\":\"olingo.odata.test1.BAETAllPrimRT\"," + + "\"target\":\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\"" + + "}},"; + + Assert.assertTrue(resultString.startsWith(expected)); + } + + @Test + public void entitySetMetadataFullWithExpand() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityCollection entityCol = data.readAll(edmEntitySet); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETTwoPrimOne"))); + InputStream result = serializerFullMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), entityCol, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{" + + "\"@context\":\"$metadata#ESAllPrim\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"#olingo.odata.test1.BAESAllPrimRTETAllPrim\":{" + + "\"title\":\"olingo.odata.test1.BAESAllPrimRTETAllPrim\"," + + "\"target\":\"ESAllPrim/olingo.odata.test1.BAESAllPrimRTETAllPrim\"" + + "}," + + "\"#olingo.odata.test1.BAESAllPrimRT\":{" + + "\"title\":\"olingo.odata.test1.BAESAllPrimRT\"," + + "\"target\":\"ESAllPrim/olingo.odata.test1.BAESAllPrimRT\"" + + "}," + + "\"#olingo.odata.test1.BFNESAllPrimRTCTAllPrim\":{" + + "\"title\":\"olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"," + + "\"target\":\"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim\"" + + "}," + + "\"value\":[" + + "{" + + "\"@type\":\"#olingo.odata.test1.ETAllPrim\"," + + "\"@id\":\"ESAllPrim(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte@type\":\"#Byte\"," + + "\"PropertyByte\":255," + + "\"PropertySByte@type\":\"#SByte\"," + + "\"PropertySByte\":127," + + "\"PropertyInt32@type\":\"#Int32\"," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64@type\":\"#Int64\"," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle@type\":\"#Single\"," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal@type\":\"#Decimal\"," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary@type\":\"#Binary\"," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate@type\":\"#Date\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset@type\":\"#DateTimeOffset\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration@type\":\"#Duration\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid@type\":\"#Guid\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay@type\":\"#TimeOfDay\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"," + + "\"NavPropertyETTwoPrimOne@navigationLink\":\"ESTwoPrim(32767)\"," + + "\"NavPropertyETTwoPrimMany@navigationLink\":\"ESAllPrim(32767)/NavPropertyETTwoPrimMany\"," + + "\"NavPropertyETTwoPrimOne\":{" + + "\"@type\":\"#olingo.odata.test1.ETTwoPrim\"," + + "\"@id\":\"ESTwoPrim(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"Test String4\"," + + "\"NavPropertyETAllPrimOne@navigationLink\":\"ESAllPrim(32767)\"," + + "\"#olingo.odata.test1.BAETTwoPrimRTString\":{" + + "\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTString\"" + + "}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":{" + + "\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollString\"" + + "}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":{" + + "\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"" + + "}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":{" + + "\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"" + + "}" + + "}," + + "\"#olingo.odata.test1.BAETAllPrimRT\":{" + + "\"title\":\"olingo.odata.test1.BAETAllPrimRT\"," + + "\"target\":\"ESAllPrim(32767)/olingo.odata.test1.BAETAllPrimRT\"" + + "}},"; + + Assert.assertTrue(resultString.startsWith(expected)); + } + + @Test + public void entityAllPrimAllNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().retainAll(Collections.singletonList(entity.getProperties().get(0))); + final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), + entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent()); + final String expectedResult = "{\"@context\":\"$metadata#ESAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":null,\"PropertyBoolean\":null," + + "\"PropertyByte\":null,\"PropertySByte\":null," + + "\"PropertyInt32\":null,\"PropertyInt64\":null," + + "\"PropertySingle\":null,\"PropertyDouble\":null,\"PropertyDecimal\":null," + + "\"PropertyBinary\":null," + + "\"PropertyDate\":null,\"PropertyDateTimeOffset\":null,\"PropertyDuration\":null," + + "\"PropertyGuid\":null,\"PropertyTimeOfDay\":null}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test(expected = SerializerException.class) + public void entityAllPrimKeyNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().clear(); + serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()); + } + + @Test + public void entityWrongData() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().get(0).setValue(ValueType.PRIMITIVE, false); + try { + serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()); + Assert.fail("Expected exception not thrown!"); + } catch (final SerializerException e) { + Assert.assertEquals(SerializerException.MessageKeys.WRONG_PROPERTY_VALUE, e.getMessageKey()); + final String message = e.getLocalizedMessage(); + Assert.assertThat(message, CoreMatchers.containsString("PropertyInt16")); + Assert.assertThat(message, CoreMatchers.containsString("false")); + } + } + + @Test + public void entitySetCompAllPrim() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompAllPrim"); + EntityCollection entitySet = data.readAll(edmEntitySet); + entitySet.setCount(entitySet.getEntities().size()); + entitySet.setNext(URI.create("/next")); + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + InputStream result = serializer.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .count(countOption) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + + Assert.assertThat(resultString, CoreMatchers.startsWith("{" + + "\"@context\":\"$metadata#ESCompAllPrim\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@count\":4,\"value\":[" + + "{\"@etag\":\"W/\\\"32767\\\"\",")); + Assert.assertThat(resultString, CoreMatchers.endsWith("}}]," + + "\"@nextLink\":\"/next\"}")); + + int count = 0; + int index = -1; + while ((index = resultString.indexOf("PropertyInt16\":", ++index)) > 0) { + count++; + } + Assert.assertEquals(8, count); + } + + @Test + public void entityCollectionStreamed() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityIterator entityIterator = new EntityIterator() { + EntityCollection entityCollection = data.readAll(edmEntitySet); + Iterator innerIterator = entityCollection.iterator(); + + @Override + public List getOperations() { + return entityCollection.getOperations(); + } + + @Override + public boolean hasNext() { + return innerIterator.hasNext(); + } + @Override + public Entity next() { + return innerIterator.next(); + } + }; + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + + ODataContent result = serializer.entityCollectionStreamed( + metadata, edmEntitySet.getEntityType(), entityIterator, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getODataContent(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + result.write(bout); + final String resultString = new String(bout.toByteArray(), "UTF-8"); + + Assert.assertThat(resultString, CoreMatchers.startsWith("{" + + "\"@context\":\"$metadata#ESAllPrim\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"PropertyInt16\":32767,\"PropertyString\"")); + Assert.assertThat(resultString, CoreMatchers.endsWith( + "\"PropertyTimeOfDay\":\"00:01:01\"}]}")); + + int count = 0; + int index = -1; + while ((index = resultString.indexOf("PropertyInt16\":", ++index)) > 0) { + count++; + } + Assert.assertEquals(3, count); + } + + @Test + public void entityCollectionStreamedWithError() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityIterator entityIterator = new EntityIterator() { + EntityCollection entityCollection = data.readAll(edmEntitySet); + Iterator innerIterator = entityCollection.iterator(); + + @Override + public List getOperations() { + return entityCollection.getOperations(); + } + + @Override + public boolean hasNext() { + return innerIterator.hasNext(); + } + @Override + public Entity next() { + Entity e = new Entity(); + e.setId(URI.create("id")); + return e; + } + }; + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + + ODataContentWriteErrorCallback errorCallback = new ODataContentWriteErrorCallback() { + @Override + public void handleError(ODataContentWriteErrorContext context, WritableByteChannel channel) { + try { + Exception ex = context.getException(); + Assert.assertEquals(ex, context.getODataLibraryException()); + String msgKey = context.getODataLibraryException().getMessageKey().getKey(); + String toChannel = "ERROR: " + msgKey; + channel.write(ByteBuffer.wrap(toChannel.getBytes("UTF-8"))); + } catch (IOException e) { + throw new RuntimeException("Error in error."); + } + } + }; + + ODataContent result = serializer.entityCollectionStreamed( + metadata, edmEntitySet.getEntityType(), entityIterator, + EntityCollectionSerializerOptions.with() + .writeContentErrorCallback(errorCallback) + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getODataContent(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + result.write(bout); + final String resultString = new String(bout.toByteArray(), "UTF-8"); + Assert.assertEquals("ERROR: MISSING_PROPERTY", resultString); + } + + + @Test + public void entityCollAllPrim() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().serviceRoot(URI.create("http://host/service/")) + .entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"http://host/service/$metadata#ESCollAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":1," + + "\"CollPropertyString\":" + + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]," + + "\"CollPropertyBoolean\":[true,false,true]," + + "\"CollPropertyByte\":[50,200,249]," + + "\"CollPropertySByte\":[-120,120,126]," + + "\"CollPropertyInt16\":[1000,2000,30112]," + + "\"CollPropertyInt32\":[23232323,11223355,10000001]," + + "\"CollPropertyInt64\":[929292929292,333333333333,444444444444]," + + "\"CollPropertySingle\":[1790.0,26600.0,3210.0]," + + "\"CollPropertyDouble\":[-17900.0,-2.78E7,3210.0]," + + "\"CollPropertyDecimal\":[12,-2,1234]," + + "\"CollPropertyBinary\":[\"q83v\",\"ASNF\",\"VGeJ\"]," + + "\"CollPropertyDate\":[\"1958-12-03\",\"1999-08-05\",\"2013-06-25\"]," + + "\"CollPropertyDateTimeOffset\":[\"2015-08-12T03:08:34Z\",\"1970-03-28T12:11:10Z\"," + + "\"1948-02-17T09:09:09Z\"]," + + "\"CollPropertyDuration\":[\"PT13S\",\"PT5H28M0S\",\"PT1H0S\"]," + + "\"CollPropertyGuid\":[\"ffffff67-89ab-cdef-0123-456789aaaaaa\",\"eeeeee67-89ab-cdef-0123-456789bbbbbb\"," + + "\"cccccc67-89ab-cdef-0123-456789cccccc\"]," + + "\"CollPropertyTimeOfDay\":[\"04:14:13\",\"23:59:59\",\"01:12:33\"]" + + "}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityCompAllPrim() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"$metadata#ESCompAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@etag\":\"W/\\\"32767\\\"\"," + + "\"PropertyInt16\":32767," + + "\"PropertyComp\":{" + + "\"PropertyString\":\"First Resource - first\"," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte\":255," + + "\"PropertyDate\":\"2012-10-03\"," + + "\"PropertyDateTimeOffset\":\"2012-10-03T07:16:23.1234567Z\"," + + "\"PropertyDecimal\":34.27," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyInt16\":32767," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySByte\":127," + + "\"PropertyTimeOfDay\":\"01:00:01\"" + + "}}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityMixPrimCollComp() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"$metadata#ESMixPrimCollComp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767," + + "\"CollPropertyString\":" + + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]," + + "\"PropertyComp\":{\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"}," + + "\"CollPropertyComp\":[" + + "{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"}," + + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"}," + + "{\"@type\":\"#olingo.odata.test1.CTBase\",\"PropertyInt16\":789," + + "\"PropertyString\":\"TEST 3\",\"AdditionalPropString\":\"ADD TEST\"}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void derivedEntityESCompCollDerived() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollDerived"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"$metadata#ESCompCollDerived/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":12345," + + "\"PropertyCompAno\":{" + + "\"@type\":\"#olingo.odata.test1.CTBaseAno\"," + + "\"PropertyString\":\"Num111\"," + + "\"AdditionalPropString\":\"Test123\"" + + "}," + + "\"CollPropertyCompAno\":[" + + "{\"@type\":\"#olingo.odata.test1.CTBaseAno\"," + + "\"PropertyString\":\"TEST12345\"," + + "\"AdditionalPropString\":\"Additional12345\"}," + + "{\"PropertyString\":\"TESTabcd\"}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void deriveEntityESAllPrimDerivedOne() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrimDerived"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETTwoPrimOne"))); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESAllPrimDerived/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767,\"PropertyString\":\"First Resource - positive values\",\"PropertyBoolean\":true," + + "\"PropertyByte\":255,\"PropertySByte\":127,\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle\":1.79E20,\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":34,\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":\"2012-12-03\",\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\",\"PropertyTimeOfDay\":\"03:26:05\"," + + "\"NavPropertyETTwoPrimOne\":{\"@type\":\"#olingo.odata.test1.ETBase\",\"PropertyInt16\":32766," + + "\"PropertyString\":\"Test String1\",\"AdditionalPropertyString_5\":\"Additional String1\"}}"; + Assert.assertEquals(expectedResult, resultString); + } + + + @Test + public void deriveEntityWithNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrimDerived"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETTwoPrimOne"))); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESAllPrimDerived/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\",\"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}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void deriveEntityESAllPrimDerived() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrimDerived"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(2); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETTwoPrimMany"))); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + + final String expectedResult = "{\"@context\":\"$metadata#ESAllPrimDerived/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\",\"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\"," + + "\"NavPropertyETTwoPrimMany\":[" + + "{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"}," + + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}," + + "{\"@type\":\"#olingo.odata.test1.ETBase\"," + + "\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"," + + "\"AdditionalPropertyString_5\":\"Additional String1\"}]}"; + Assert.assertEquals(expectedResult, resultString); + + } + + @Test + public void entityMixPrimCollCompAllNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().retainAll(Collections.singletonList(entity.getProperties().get(0))); + final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent()); + final String expectedResult = "{\"@context\":\"$metadata#ESMixPrimCollComp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767," + + "\"CollPropertyString\":[],\"PropertyComp\":null,\"CollPropertyComp\":[]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void nullCollectionButInDataMap() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixEnumDefCollComp"); + Entity entity = new Entity(); + entity.setId(URI.create("id")); + entity.addProperty(new Property(null, "PropertyEnumString", ValueType.ENUM, 6)); + entity.addProperty(new Property(null, "CollPropertyEnumString", ValueType.COLLECTION_ENUM, null)); + entity.addProperty(new Property(null, "PropertyDefString", ValueType.PRIMITIVE, "Test")); + entity.addProperty(new Property(null, "CollPropertyDefString", ValueType.COLLECTION_PRIMITIVE, null)); + ComplexValue complexValue = new ComplexValue(); + complexValue.getValue().add(entity.getProperty("PropertyEnumString")); + complexValue.getValue().add(entity.getProperty("CollPropertyEnumString")); + complexValue.getValue().add(entity.getProperty("PropertyDefString")); + complexValue.getValue().add(entity.getProperty("CollPropertyDefString")); + entity.addProperty(new Property(null, "PropertyCompMixedEnumDef", ValueType.COMPLEX, complexValue)); + entity.addProperty(new Property(null, "CollPropertyCompMixedEnumDef", ValueType.COLLECTION_COMPLEX, null)); + final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent()); + Assert.assertEquals("{\"@context\":\"$metadata#ESMixEnumDefCollComp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyEnumString\":\"String2,String3\"," + + "\"CollPropertyEnumString\":[]," + + "\"PropertyDefString\":\"Test\"," + + "\"CollPropertyDefString\":[]," + + "\"PropertyCompMixedEnumDef\":{\"PropertyEnumString\":\"String2,String3\"," + + "\"CollPropertyEnumString\":[]," + + "\"PropertyDefString\":\"Test\",\"CollPropertyDefString\":[]}," + + "\"CollPropertyCompMixedEnumDef\":[]}", + resultString); + } + + @Test + public void nullComplexValueButInDataMapAndNullCollectionsNotInDataMap() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixEnumDefCollComp"); + Entity entity = new Entity(); + entity.setId(URI.create("id")); + entity.addProperty(new Property(null, "PropertyEnumString", ValueType.ENUM, 6)); + entity.addProperty(new Property(null, "PropertyDefString", ValueType.PRIMITIVE, "Test")); + entity.addProperty(new Property(null, "PropertyCompMixedEnumDef", ValueType.COMPLEX, null)); + final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent()); + Assert.assertEquals("{\"@context\":\"$metadata#ESMixEnumDefCollComp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyEnumString\":\"String2,String3\"," + + "\"CollPropertyEnumString\":[]," + + "\"PropertyDefString\":\"Test\"," + + "\"CollPropertyDefString\":[]," + + "\"PropertyCompMixedEnumDef\":null," + + "\"CollPropertyCompMixedEnumDef\":[]}", + resultString); + } + + @Test + public void enumAndTypeDefinition() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixEnumDefCollComp"); + Entity entity = new Entity(); + entity.setId(URI.create("id")); + entity.addProperty(new Property(null, "PropertyEnumString", ValueType.ENUM, 6)); + entity.addProperty(new Property(null, "CollPropertyEnumString", ValueType.COLLECTION_ENUM, + Arrays.asList(2, 4, 6))); + entity.addProperty(new Property(null, "PropertyDefString", ValueType.PRIMITIVE, "Test")); + entity.addProperty(new Property(null, "CollPropertyDefString", ValueType.COLLECTION_PRIMITIVE, + Arrays.asList("Test1", "Test2"))); + ComplexValue complexValue = new ComplexValue(); + complexValue.getValue().add(entity.getProperty("PropertyEnumString")); + complexValue.getValue().add(entity.getProperty("CollPropertyEnumString")); + complexValue.getValue().add(entity.getProperty("PropertyDefString")); + complexValue.getValue().add(entity.getProperty("CollPropertyDefString")); + entity.addProperty(new Property(null, "PropertyCompMixedEnumDef", ValueType.COMPLEX, complexValue)); + entity.addProperty(new Property(null, "CollPropertyCompMixedEnumDef", ValueType.COLLECTION_COMPLEX, + Collections.singletonList(complexValue))); + final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent()); + Assert.assertEquals("{\"@context\":\"$metadata#ESMixEnumDefCollComp/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyEnumString\":\"String2,String3\"," + + "\"CollPropertyEnumString\":[\"String2\",\"String3\",\"String2,String3\"]," + + "\"PropertyDefString\":\"Test\"," + + "\"CollPropertyDefString\":[\"Test1\",\"Test2\"]," + + "\"PropertyCompMixedEnumDef\":{\"PropertyEnumString\":\"String2,String3\"," + + "\"CollPropertyEnumString\":[\"String2\",\"String3\",\"String2,String3\"]," + + "\"PropertyDefString\":\"Test\",\"CollPropertyDefString\":[\"Test1\",\"Test2\"]}," + + "\"CollPropertyCompMixedEnumDef\":[{\"PropertyEnumString\":\"String2,String3\"," + + "\"CollPropertyEnumString\":[\"String2\",\"String3\",\"String2,String3\"]," + + "\"PropertyDefString\":\"Test\",\"CollPropertyDefString\":[\"Test1\",\"Test2\"]}]}", + resultString); + } + + @Test + public void entityTwoPrimNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + final String resultString = IOUtils.toString(serializerNoMetadata + .entity(metadata, edmEntitySet.getEntityType(), entity, null).getContent()); + final String expectedResult = "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityTwoPrimWithMetadataMinimal() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializer + .entity(metadata, edmEntitySet.getEntityType(), entity, EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESTwoPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entitySetTwoPrimWithMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + InputStream result = serializerFullMetadata + .entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()) + .getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESTwoPrim\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"@type\":\"#olingo.odata.test1.ETTwoPrim\",\"@id\":\"ESTwoPrim(32766)\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":32766," + + "\"PropertyString\":\"Test String1\"," + + "\"#olingo.odata.test1.BAETTwoPrimRTString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\"," + + "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\"," + + "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCollString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"," + + "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"," + + "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}" + + "}," + + "{\"@type\":\"#olingo.odata.test1.ETTwoPrim\",\"@id\":\"ESTwoPrim(-365)\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":-365," + + "\"PropertyString\":\"Test String2\"," + + "\"NavPropertyETAllPrimMany@navigationLink\":\"ESTwoPrim(-365)/NavPropertyETAllPrimMany\"," + + "\"#olingo.odata.test1.BAETTwoPrimRTString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\"," + + "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\"," + + "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCollString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"," + + "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"," + + "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}}," + + "{\"@type\":\"#olingo.odata.test1.ETTwoPrim\",\"@id\":\"ESTwoPrim(-32766)\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":-32766," + + "\"PropertyString\":null," + + "\"#olingo.odata.test1.BAETTwoPrimRTString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\"," + + "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\"," + + "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCollString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"," + + "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"," + + "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}}," + + "{\"@type\":\"#olingo.odata.test1.ETTwoPrim\",\"@id\":\"ESTwoPrim(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":32767," + + "\"PropertyString\":\"Test String4\"," + + "\"NavPropertyETAllPrimOne@navigationLink\":\"ESAllPrim(32767)\"," + + "\"#olingo.odata.test1.BAETTwoPrimRTString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollString\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"}," + + "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":" + + "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"," + + "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}" + + "}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityWithStreamMetadataMinimal() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream"); + final EntityCollection collection = data.readAll(edmEntitySet); + InputStream result = serializer.entityCollection(metadata, edmEntitySet.getEntityType(), collection, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESWithStream\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"PropertyInt16\":32767}," + + "{\"PropertyInt16\":7,\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\"}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityWithStreamMetadataNone() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream"); + final EntityCollection collection = data.readAll(edmEntitySet); + InputStream result = serializerNoMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), collection, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"value\":[{\"PropertyInt16\":32767}," + + "{\"PropertyInt16\":7}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityWithStreamMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream"); + final EntityCollection collection = data.readAll(edmEntitySet); + InputStream result = serializerFullMetadata.entityCollection(metadata, edmEntitySet.getEntityType(), collection, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESWithStream\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{" + + "\"@type\":\"#olingo.odata.test1.ETWithStream\"," + + "\"@id\":\"ESWithStream(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":32767," + + "\"PropertyStream@type\":\"#Stream\"," + + "\"PropertyStream@mediaReadLink\":\"readLink\"}," + + "{" + + "\"@type\":\"#olingo.odata.test1.ETWithStream\"," + + "\"@id\":\"ESWithStream(7)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":7," + + "\"PropertyStream@type\":\"#Stream\"," + + "\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\"," + + "\"PropertyStream@mediaEditLink\":\"http://mediaserver:1234/editLink\"" + + "}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + + @Test + public void entityWithStreamExpand() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESWithStream"); + final EntityCollection collection = data.readAll(edmEntitySet); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "PropertyStream"))); + InputStream result = serializer.entityCollection(metadata, edmEntitySet.getEntityType(), collection, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .expand(expand).build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESWithStream\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"PropertyInt16\":32767,\"PropertyStream\":\"�ioz�\\\"�\"}," + + "{\"PropertyInt16\":7,\"PropertyStream@mediaEtag\":\"eTag\"," + + "\"PropertyStream@mediaContentType\":\"image/jpeg\",\"PropertyStream\":\"�ioz�\\\"�\"}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entitySetTwoPrimNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + final String resultString = IOUtils.toString(serializerNoMetadata + .entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getContent()); + final String expectedResult = "{\"value\":[" + + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}," + + "{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"}," + + "{\"PropertyInt16\":-32766,\"PropertyString\":null}," + + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityMedia() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + final String resultString = IOUtils.toString(serializer.entity(metadata, edmEntitySet.getEntityType(), + entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent()); + final String expectedResult = "{\"@context\":\"$metadata#ESMedia/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@mediaEtag\":\"W/\\\"1\\\"\"," + + "\"@mediaContentType\":\"image/svg+xml\"," + + "\"@mediaEditLink\":\"ESMedia(1)/$value\"," + + "\"PropertyInt16\":1}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entitySetMedia() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + final String resultString = IOUtils.toString(serializer.entityCollection(metadata, + edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()).build()).getContent()); + final String expectedResult = "{\"@context\":\"$metadata#ESMedia\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[" + + "{\"@mediaEtag\":\"W/\\\"1\\\"\",\"@mediaContentType\":\"image/svg+xml\"," + + "\"@mediaEditLink\":\"ESMedia(1)/$value\",\"PropertyInt16\":1}," + + "{\"@mediaEtag\":\"W/\\\"2\\\"\",\"@mediaContentType\":\"image/svg+xml\"," + + "\"@mediaEditLink\":\"ESMedia(2)/$value\",\"PropertyInt16\":2}," + + "{\"@mediaEtag\":\"W/\\\"3\\\"\",\"@mediaContentType\":\"image/svg+xml\"," + + "\"@mediaEditLink\":\"ESMedia(3)/$value\",\"PropertyInt16\":3}," + + "{\"@mediaEtag\":\"W/\\\"4\\\"\",\"@mediaContentType\":\"image/svg+xml\"," + + "\"@mediaEditLink\":\"ESMedia(4)/$value\",\"PropertyInt16\":4}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityMediaWithMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.setMediaETag("W/\\\"08D25949E3BFB7AB\\\""); + InputStream result = serializerFullMetadata + .entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with().contextURL(ContextURL.with() + .entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()).build()) + .getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESMedia/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@mediaEtag\":\"W/\\\\\\\"08D25949E3BFB7AB\\\\\\\"\",\"@mediaContentType\":\"image/svg+xml\"," + + "\"@mediaEditLink\":\"ESMedia(1)/$value\"," + + "\"@type\":\"#olingo.odata.test1.ETMedia\",\"@id\":\"ESMedia(1)\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":1}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void primitiveValuesAllNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllNullable"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + final String resultString = IOUtils.toString(serializer.entityCollection(metadata, + edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()).build()).getContent()); + + final String expected = "{\"@context\":\"$metadata#ESAllNullable\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"PropertyKey\":1," + + "\"PropertyInt16\":null,\"PropertyString\":null,\"PropertyBoolean\":null,\"PropertyByte\":null," + + "\"PropertySByte\":null,\"PropertyInt32\":null,\"PropertyInt64\":null,\"PropertySingle\":null," + + "\"PropertyDouble\":null,\"PropertyDecimal\":null,\"PropertyBinary\":null,\"PropertyDate\":null," + + "\"PropertyDateTimeOffset\":null,\"PropertyDuration\":null,\"PropertyGuid\":null,\"PropertyTimeOfDay\":null," + + "\"CollPropertyString\":[\"spiderman@comic.com\",null,\"spidergirl@comic.com\"]," + + "\"CollPropertyBoolean\":[true,null,false],\"CollPropertyByte\":[50,null,249]," + + "\"CollPropertySByte\":[-120,null,126],\"CollPropertyInt16\":[1000,null,30112]," + + "\"CollPropertyInt32\":[23232323,null,10000001],\"CollPropertyInt64\":[929292929292,null,444444444444]," + + "\"CollPropertySingle\":[1790.0,null,3210.0],\"CollPropertyDouble\":[-17900.0,null,3210.0]," + + "\"CollPropertyDecimal\":" + + "[12,null,1234],\"CollPropertyBinary\":[\"q83v\",null,\"VGeJ\"],\"CollPropertyDate\":" + + "[\"1958-12-03\",null,\"2013-06-25\"],\"CollPropertyDateTimeOffset\":[\"2015-08-12T03:08:34Z\",null," + + "\"1948-02-17T09:09:09Z\"],\"CollPropertyDuration\":[\"PT13S\",null,\"PT1H0S\"],\"CollPropertyGuid\":" + + "[\"ffffff67-89ab-cdef-0123-456789aaaaaa\",null,\"cccccc67-89ab-cdef-0123-456789cccccc\"]," + + "\"CollPropertyTimeOfDay\":[\"04:14:13\",null,\"00:37:13\"]}]}"; + + Assert.assertEquals(expected, resultString); + } + + @Test + public void select() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + final SelectItem selectItem1 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyDate"); + final SelectItem selectItem2 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyBoolean"); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( + selectItem1, selectItem2, selectItem2)); + 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(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"$metadata#ESAllPrim(PropertyBoolean,PropertyDate)/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@id\":\"ESAllPrim(32767)\"," + + "\"PropertyBoolean\":true,\"PropertyDate\":\"2012-12-03\"}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void selectAll() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + final SelectItem selectItem1 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyString"); + SelectItem selectItem2 = Mockito.mock(SelectItem.class); + Mockito.when(selectItem2.isStar()).thenReturn(true); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem1, selectItem2)); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .select(select) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESTwoPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void selectComplex() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESFourKeyAlias"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final EntityCollection entitySet = data.readAll(edmEntitySet); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( + ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyInt16"), + ExpandSelectMock.mockSelectItem(edmEntitySet,"PropertyCompComp", "PropertyComp", "PropertyString"))); + InputStream result = serializer + .entityCollection(metadata, entityType, entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(helper.buildContextURLSelectList(entityType, null, select)) + .build()) + .select(select) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{" + + "\"@context\":\"$metadata#ESFourKeyAlias" + + "(PropertyInt16,PropertyCompComp/PropertyComp/PropertyString)\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[" + + "{" + + "\"@id\":\"" + + "ESFourKeyAlias(PropertyInt16=1,KeyAlias1=11,KeyAlias2='Num11',KeyAlias3='Num111')\"," + + "\"PropertyInt16\":1," + + "\"PropertyCompComp\":{" + + "\"PropertyComp\":{" + + "\"@type\":\"#olingo.odata.test1.CTBase\"," + + "\"PropertyString\":\"Num111\"" + + "}}}]}"; + + Assert.assertEquals(expected, resultString); + } + + @Test + public void selectExtendedComplexType() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESFourKeyAlias"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final EntityCollection entitySet = data.readAll(edmEntitySet); + InputStream result = serializer + .entityCollection(metadata, entityType, entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + + final String expected = "{" + + "\"@context\":\"$metadata#ESFourKeyAlias\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{" + + "\"PropertyInt16\":1," + + "\"PropertyComp\":{" + + "\"PropertyInt16\":11," + + "\"PropertyString\":\"Num11\"" + + "}," + + "\"PropertyCompComp\":{" + + "\"PropertyComp\":{" + + "\"@type\":\"#olingo.odata.test1.CTBase\"," + + "\"PropertyInt16\":111," + + "\"PropertyString\":\"Num111\"," + + "\"AdditionalPropString\":\"Test123\"" + + "}}}]}"; + + Assert.assertEquals(expected, resultString); + } + + @Test + public void selectComplexTwice() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESFourKeyAlias"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final EntityCollection entitySet = data.readAll(edmEntitySet); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( + ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyComp", "PropertyString"), + ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyCompComp", "PropertyComp"))); + final String resultString = IOUtils.toString(serializer + .entityCollection(metadata, entityType, entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(helper.buildContextURLSelectList(entityType, null, select)) + .build()) + .select(select) + .build()).getContent()); + + String expected = "{" + + "\"@context\":\"$metadata#ESFourKeyAlias" + + "(PropertyComp/PropertyString,PropertyCompComp/PropertyComp)\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{" + + "\"@id\":\"ESFourKeyAlias(PropertyInt16=1,KeyAlias1=11,KeyAlias2='Num11',KeyAlias3='Num111')\"," + + "\"PropertyComp\":{" + + "\"PropertyString\":\"Num11\"" + + "}," + + "\"PropertyCompComp\":{" + + "\"PropertyComp\":{" + + "\"@type\":\"#olingo.odata.test1.CTBase\"," + + "\"PropertyInt16\":111," + + "\"PropertyString\":\"Num111\"," + + "\"AdditionalPropString\":\"Test123\"" + + "}}}]}"; + + Assert.assertEquals(expected, resultString); + } + + @Test + public void selectComplexNestedCollectionOfComplexWithMetadataFull() throws Exception{ + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + InputStream result = serializerFullMetadata + .entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()) + .getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESCompCollComp\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"@type\":\"#olingo.odata.test1.ETCompCollComp\"," + + "\"@id\":\"ESCompCollComp(32767)\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":32767," + + "\"PropertyComp\":{" + + "\"@type\":\"#olingo.odata.test1.CTCompCollComp\"," + + "\"CollPropertyComp@type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\"," + + "\"CollPropertyComp\":[" + + "{" + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":555," + + "\"PropertyString\":\"1 Test Complex in Complex Property\"" + + "},{" + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":666," + + "\"PropertyString\":\"2 Test Complex in Complex Property\"" + + "},{" + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":777," + + "\"PropertyString\":\"3 Test Complex in Complex Property\"" + + "}]}},{" + + "\"@type\":\"#olingo.odata.test1.ETCompCollComp\"," + + "\"@id\":\"ESCompCollComp(12345)\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":12345," + + "\"PropertyComp\":{" + + "\"@type\":\"#olingo.odata.test1.CTCompCollComp\"," + + "\"CollPropertyComp@type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\"," + + "\"CollPropertyComp\":[" + + "{" + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":888," + + "\"PropertyString\":\"11 Test Complex in Complex Property\"" + + "},{" + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":999," + + "\"PropertyString\":\"12 Test Complex in Complex Property\"" + + "},{" + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\"," + + "\"PropertyInt16\":0," + + "\"PropertyString\":\"13 Test Complex in Complex Property\"" + + "}]}}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void selectComplexNestedCollectionOfComplexWithMetadataMinimal() throws Exception{ + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + InputStream result = serializer + .entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()) + .getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{\"@context\":\"$metadata#ESCompCollComp\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{" + + "\"PropertyInt16\":32767," + + "\"PropertyComp\":{" + + "\"CollPropertyComp\":[" + + "{" + + "\"PropertyInt16\":555," + + "\"PropertyString\":\"1 Test Complex in Complex Property\"" + + "},{" + + "\"PropertyInt16\":666," + + "\"PropertyString\":\"2 Test Complex in Complex Property\"" + + "},{" + + "\"PropertyInt16\":777," + + "\"PropertyString\":\"3 Test Complex in Complex Property\"" + + "}]}},{" + + "\"PropertyInt16\":12345," + + "\"PropertyComp\":{" + + "\"CollPropertyComp\":[" + + "{" + + "\"PropertyInt16\":888," + + "\"PropertyString\":\"11 Test Complex in Complex Property\"" + + "},{" + + "\"PropertyInt16\":999," + + "\"PropertyString\":\"12 Test Complex in Complex Property\"" + + "},{" + + "\"PropertyInt16\":0," + + "\"PropertyString\":\"13 Test Complex in Complex Property\"" + + "}]}}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void selectComplexNestedCollectionOfComplexWithMetadataNone() throws Exception{ + final String METADATA_TEXT = "@"; + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp"); + final EntityCollection entitySet = data.readAll(edmEntitySet); + InputStream result = serializerNoMetadata + .entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()) + .getContent(); + final String resultString = IOUtils.toString(result); + Assert.assertEquals(false, resultString.contains(METADATA_TEXT)); + } + + @Test + public void selectMissingId() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.setId(null); + final SelectItem selectItem1 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyDate"); + final SelectItem selectItem2 = ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyBoolean"); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( + selectItem1, selectItem2, selectItem2)); + 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.assertNotNull(result); + final String resultString = IOUtils.toString(result); + Assert.assertEquals( "{\"@context\":\"$metadata#ESAllPrim(PropertyBoolean,PropertyDate)/$entity\","+ + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\",\"@id\":\"ESAllPrim(32767)\","+ + "\"PropertyBoolean\":true,\"PropertyDate\":\"2012-12-03\"}", + resultString); + } + + @Test + public void expand() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(3); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList( + ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETAllPrimOne"))); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + Assert.assertEquals("{\"@context\":\"$metadata#ESTwoPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," + + "\"NavPropertyETAllPrimOne\":{" + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte\":255," + + "\"PropertySByte\":127," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"}}", + resultString); + } + + @Test + public void expandSelect() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(3); + final SelectOption select = ExpandSelectMock.mockSelectOption(Collections.singletonList( + ExpandSelectMock.mockSelectItem(entityContainer.getEntitySet("ESAllPrim"), "PropertyDate"))); + ExpandItem expandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETAllPrimOne"); + Mockito.when(expandItem.getSelectOption()).thenReturn(select); + 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("{" + + "\"@context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimOne(PropertyDate))/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," + + "\"NavPropertyETAllPrimOne\":{\"@id\":\"ESAllPrim(32767)\",\"PropertyDate\":\"2012-12-03\"}}", + resultString); + } + + @Test + public void expandAll() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + final ExpandItem expandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETTwoPrimOne"); + ExpandItem expandItemAll = Mockito.mock(ExpandItem.class); + Mockito.when(expandItemAll.isStar()).thenReturn(true); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList( + expandItem, expandItem, expandItemAll)); + final SelectOption select = ExpandSelectMock.mockSelectOption(Collections.singletonList( + ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertySByte"))); + 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) + .select(select) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESAllPrim(PropertySByte)/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@id\":\"ESAllPrim(32767)\"," + + "\"PropertySByte\":127," + + "\"NavPropertyETTwoPrimOne\":{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}," + + "\"NavPropertyETTwoPrimMany\":[{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"}]}", + resultString); + } + + @Test + public void expandNoData() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmEntityType entityType = edmEntitySet.getEntityType(); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + ExpandItem expandItemAll = Mockito.mock(ExpandItem.class); + Mockito.when(expandItemAll.isStar()).thenReturn(true); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(expandItemAll)); + final SelectOption select = ExpandSelectMock.mockSelectOption(Collections.singletonList( + ExpandSelectMock.mockSelectItem(edmEntitySet, "PropertyTimeOfDay"))); + 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) + .select(select) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESAllPrim(PropertyTimeOfDay)/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@id\":\"ESAllPrim(-32768)\"," + + "\"PropertyTimeOfDay\":\"23:49:14\"," + + "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}", + resultString); + } + + @Test + public void expandTwoLevels() 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 expandItemSecond = Mockito.mock(ExpandItem.class); + Mockito.when(expandItemSecond.isStar()).thenReturn(true); + final ExpandOption expandInner = ExpandSelectMock.mockExpandOption(Collections.singletonList(expandItemSecond)); + ExpandItem expandItemFirst = ExpandSelectMock.mockExpandItem(edmEntitySet, "NavPropertyETAllPrimMany"); + Mockito.when(expandItemFirst.getExpandOption()).thenReturn(expandInner); + final SelectOption select = ExpandSelectMock.mockSelectOption(Collections.singletonList( + ExpandSelectMock.mockSelectItem(innerEntitySet, "PropertyInt32"))); + Mockito.when(expandItemFirst.getSelectOption()).thenReturn(select); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(expandItemFirst)); + 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("{" + + "\"@context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"," + + "\"NavPropertyETAllPrimMany\":[" + + "{\"@id\":\"ESAllPrim(-32768)\",\"PropertyInt32\":-2147483648," + + "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}," + + "{\"@id\":\"ESAllPrim(0)\",\"PropertyInt32\":0,\"NavPropertyETTwoPrimOne\":{" + + "\"@type\":\"#olingo.odata.test1.ETBase\",\"PropertyInt16\":111," + + "\"PropertyString\":\"TEST A\",\"AdditionalPropertyString_5\":\"TEST A 0815\"}," + + "\"NavPropertyETTwoPrimMany\":[" + + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}," + + "{\"PropertyInt16\":-32766,\"PropertyString\":null}," + + "{\"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("{\"@context\":\"$metadata#ESTwoPrim/$entity\"," + + "\"@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\":{" + + "\"@type\":\"#olingo.odata.test1.ETBase\",\"PropertyInt16\":111," + + "\"PropertyString\":\"TEST A\",\"AdditionalPropertyString_5\":\"TEST A 0815\"}," + + "\"NavPropertyETTwoPrimMany\":[" + + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}," + + "{\"PropertyInt16\":-32766,\"PropertyString\":null}," + + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}", + resultString); + } + + @Test + public void primitiveProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyString"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializer + .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName()) + .build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESAllPrim(32767)/PropertyString\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":\"First Resource - positive values\"}", + resultString); + } + + @Test + public void primitivePropertyNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyString"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializerNoMetadata + .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, null).getContent()); + Assert.assertEquals("{\"value\":\"First Resource - positive values\"}", resultString); + } + + @Test + public void primitivePropertyWithMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType() + .getProperty("PropertyString"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0) + .getProperty(edmProperty.getName()); + final String resultString = IOUtils + .toString(serializerFullMetadata + .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .keyPath("32767") + .navOrPropertyPath(edmProperty.getName()).build()) + .build()) + .getContent()); + Assert.assertEquals( + "{\"@context\":\"$metadata#ESAllPrim(32767)/PropertyString\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":\"First Resource - positive values\"}", + resultString); + } + + @Test(expected = SerializerException.class) + public void primitivePropertyNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyString"); + final Property property = new Property("Edm.String", edmProperty.getName(), ValueType.PRIMITIVE, null); + serializer.primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("4242").navOrPropertyPath(edmProperty.getName()) + .build()) + .build()); + } + + @Test + public void primitiveCollectionProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyString"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + + final String resultString = IOUtils.toString(serializer + .primitiveCollection(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName()) + .build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESCollAllPrim(1)/CollPropertyString\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]}", + resultString); + } + + @Test + public void primitiveCollectionNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyString"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializerNoMetadata + .primitiveCollection(metadata, (EdmPrimitiveType) edmProperty.getType(), property, null).getContent()); + Assert.assertEquals("{\"value\":[\"Employee1@company.example\"," + + "\"Employee2@company.example\",\"Employee3@company.example\"]}", + resultString); + } + + @Test + public void primitiveCollectionPropertyWithMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyString"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + + final String resultString = IOUtils.toString(serializerFullMetadata + .primitiveCollection(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName()) + .build()) + .build()).getContent()); + Assert.assertEquals("{\"@context\":\"$metadata#ESCollAllPrim(1)/CollPropertyString\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@type\":\"#Collection(String)\",\"value\":[\"Employee1@company.example\"," + + "\"Employee2@company.example\",\"Employee3@company.example\"]}", resultString); + } + + @Test + public void complexProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty("PropertyComp"); + + final String resultString = IOUtils.toString(serializer + .complex(metadata, (EdmComplexType) edmProperty.getType(), property, + ComplexSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName()) + .build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESMixPrimCollComp(32767)/PropertyComp\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"}", + resultString); + } + + @Test + public void complexPropertyNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty("PropertyComp"); + final String resultString = IOUtils.toString(serializerNoMetadata + .complex(metadata, (EdmComplexType) edmProperty.getType(), property, null).getContent()); + Assert.assertEquals("{\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"}", resultString); + } + + @Test + public void complexPropertyWithMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty("PropertyComp"); + final String resultString = IOUtils.toString(serializerFullMetadata + .complex(metadata, (EdmComplexType) edmProperty.getType(), property, + ComplexSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName()) + .build()).build()).getContent()); + Assert.assertEquals("{\"@context\":\"$metadata#ESMixPrimCollComp(32767)/PropertyComp\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":111," + + "\"PropertyString\":\"TEST A\"}",resultString); + } + + @Test + public void complexCollectionProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + + final String resultString = IOUtils.toString(serializer + .complexCollection(metadata, (EdmComplexType) edmProperty.getType(), property, + ComplexSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName()) + .build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESMixPrimCollComp(32767)/CollPropertyComp\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"}," + + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"}," + + "{\"@type\":\"#olingo.odata.test1.CTBase\",\"PropertyInt16\":789," + + "\"PropertyString\":\"TEST 3\",\"AdditionalPropString\":\"ADD TEST\"}]}", + resultString); + } + + @Test + public void complexCollectionPropertyNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializerNoMetadata + .complexCollection(metadata, (EdmComplexType) edmProperty.getType(), property, null).getContent()); + Assert.assertEquals("{\"value\":[{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"}," + + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"}," + + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\",\"AdditionalPropString\":\"ADD TEST\"}]}", + resultString); + } + + @Test + public void complexCollectionPropertyWithMetadataFull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializerFullMetadata + .complexCollection(metadata, (EdmComplexType) edmProperty.getType(), + property, ComplexSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .keyPath("32767") + .navOrPropertyPath(edmProperty.getName()).build()) + .build()) + .getContent()); + final String expectedResult = "{\"@context\":\"$metadata#ESMixPrimCollComp(32767)/CollPropertyComp\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\"," + + "\"value\":[{\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":123," + + "\"PropertyString\":\"TEST 1\"}," + + "{\"@type\":\"#olingo.odata.test1.CTTwoPrim\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":456," + + "\"PropertyString\":\"TEST 2\"}," + + "{\"@type\":\"#olingo.odata.test1.CTBase\"," + + "\"PropertyInt16@type\":\"#Int16\",\"PropertyInt16\":789," + + "\"PropertyString\":\"TEST 3\",\"AdditionalPropString\":\"ADD TEST\"}]}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityReference() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + + final SerializerResult serializerResult = serializer.reference(metadata, edmEntitySet, entity, + ReferenceSerializerOptions.with().contextURL(ContextURL.with().suffix(Suffix.REFERENCE).build()).build()); + final String resultString = IOUtils.toString(serializerResult.getContent()); + + Assert.assertEquals("{\"@context\":\"$metadata#$ref\"," + + "\"@id\":\"ESAllPrim(32767)\"}", + resultString); + } + + @Test + public void entityReferenceNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + final String resultString = IOUtils.toString( + serializerNoMetadata.reference(metadata, edmEntitySet, entity, null).getContent()); + Assert.assertEquals("{\"@id\":\"ESAllPrim(32767)\"}", resultString); + } + + @Test + public void entityCollectionReference() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityCollection entityCollection = data.readAll(edmEntitySet); + + final SerializerResult serializerResult = serializer.referenceCollection(metadata, + edmEntitySet, + entityCollection, + ReferenceCollectionSerializerOptions.with() + .contextURL(ContextURL.with().asCollection().suffix(Suffix.REFERENCE).build()) + .build()); + + final String resultString = IOUtils.toString(serializerResult.getContent()); + + Assert.assertEquals("{\"@context\":\"$metadata#Collection($ref)\"," + + "\"value\":[{\"@id\":\"ESAllPrim(32767)\"}," + + "{\"@id\":\"ESAllPrim(-32768)\"}," + + "{\"@id\":\"ESAllPrim(0)\"}]}", + resultString); + } + + @Test + public void entityCollectionReferenceEmpty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityCollection entityCollection = new EntityCollection(); + + final SerializerResult serializerResult = serializer.referenceCollection(metadata, + edmEntitySet, entityCollection, + ReferenceCollectionSerializerOptions.with() + .contextURL(ContextURL.with().asCollection().suffix(Suffix.REFERENCE).build()) + .build()); + + final String resultString = IOUtils.toString(serializerResult.getContent()); + + Assert.assertEquals("{\"@context\":\"$metadata#Collection($ref)\"," + + "\"value\":[]}", resultString); + } + + @Test + public void entityCollectionReferenceEmptyNoMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityCollection entityCollection = new EntityCollection(); + final String resultString = IOUtils.toString(serializerNoMetadata + .referenceCollection(metadata, edmEntitySet, entityCollection, null).getContent()); + Assert.assertEquals("{\"value\":[]}", resultString); + } + + @Test + public void entityIEE754Compatible() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializerIEEECompatible.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"$metadata#ESAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":true," + + "\"PropertyByte\":255," + + "\"PropertySByte\":127," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":\"" + Long.MAX_VALUE + "\"," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":\"34\"," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"" + + "}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entityCollAllPrimIEEE754Compatible() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializerIEEECompatible.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().serviceRoot(URI.create("http://host/service/")) + .entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expectedResult = "{" + + "\"@context\":\"http://host/service/$metadata#ESCollAllPrim/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"PropertyInt16\":1," + + "\"CollPropertyString\":" + + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]," + + "\"CollPropertyBoolean\":[true,false,true]," + + "\"CollPropertyByte\":[50,200,249]," + + "\"CollPropertySByte\":[-120,120,126]," + + "\"CollPropertyInt16\":[1000,2000,30112]," + + "\"CollPropertyInt32\":[23232323,11223355,10000001]," + + "\"CollPropertyInt64\":[\"929292929292\",\"333333333333\",\"444444444444\"]," + + "\"CollPropertySingle\":[1790.0,26600.0,3210.0]," + + "\"CollPropertyDouble\":[-17900.0,-2.78E7,3210.0]," + + "\"CollPropertyDecimal\":[\"12\",\"-2\",\"1234\"]," + + "\"CollPropertyBinary\":[\"q83v\",\"ASNF\",\"VGeJ\"]," + + "\"CollPropertyDate\":[\"1958-12-03\",\"1999-08-05\",\"2013-06-25\"]," + + "\"CollPropertyDateTimeOffset\":[\"2015-08-12T03:08:34Z\",\"1970-03-28T12:11:10Z\"," + + "\"1948-02-17T09:09:09Z\"]," + + "\"CollPropertyDuration\":[\"PT13S\",\"PT5H28M0S\",\"PT1H0S\"]," + + "\"CollPropertyGuid\":[\"ffffff67-89ab-cdef-0123-456789aaaaaa\",\"eeeeee67-89ab-cdef-0123-456789bbbbbb\"," + + "\"cccccc67-89ab-cdef-0123-456789cccccc\"]," + + "\"CollPropertyTimeOfDay\":[\"04:14:13\",\"23:59:59\",\"01:12:33\"]" + + "}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void primitiveCollectionPropertyIEEE754CompatibleInt64() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyInt64"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + + final String resultString = IOUtils.toString(serializerIEEECompatible + .primitiveCollection(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName()).build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESCollAllPrim(1)/CollPropertyInt64\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[\"929292929292\",\"333333333333\",\"444444444444\"]}", + resultString); + } + + @Test + public void primitiveCollectionPropertyIEEE754CompatibleDecimal() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyDecimal"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + + final String resultString = IOUtils.toString(serializerIEEECompatible + .primitiveCollection(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName()).build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESCollAllPrim(1)/CollPropertyDecimal\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[\"12\",\"-2\",\"1234\"]}", + resultString); + } + + @Test + public void primitivePropertyIEEE754CompatibleInt64() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyInt64"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializerIEEECompatible + .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName()).build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESAllPrim(32767)/PropertyInt64\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":\"" + Long.MAX_VALUE + "\"}", + resultString); + } + + @Test + public void primitivePropertyIEEE754CompatibleDecimal() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyDecimal"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName()); + final String resultString = IOUtils.toString(serializerIEEECompatible + .primitive(metadata, (EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName()).build()) + .build()).getContent()); + Assert.assertEquals("{" + + "\"@context\":\"$metadata#ESAllPrim(32767)/PropertyDecimal\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":\"34\"}", + resultString); + } + + @Test + public void entitySetAllPrimIEEE754CompatibleCount() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + EntityCollection entitySet = data.readAll(edmEntitySet); + entitySet.setCount(entitySet.getEntities().size()); + entitySet.setNext(URI.create("/next")); + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + InputStream result = serializerIEEECompatible.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .count(countOption) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + + Assert.assertThat(resultString, CoreMatchers.startsWith("{" + + "\"@context\":\"$metadata#ESAllPrim\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@count\":\"3\",\"value\":[")); + Assert.assertThat(resultString, CoreMatchers.endsWith("]," + + "\"@nextLink\":\"/next\"}")); + + int count = 0; + int index = -1; + while ((index = resultString.indexOf("PropertyInt16\":", ++index)) > 0) { + count++; + } + Assert.assertEquals(3, count); + } + + @Test + public void entitySetAllPrimReferenceIEEE754CompatibleCount() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + EntityCollection entitySet = data.readAll(edmEntitySet); + entitySet.setCount(entitySet.getEntities().size()); + entitySet.setNext(URI.create("/next")); + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + InputStream result = serializerIEEECompatible.referenceCollection(metadata, edmEntitySet, entitySet, + ReferenceCollectionSerializerOptions.with() + .contextURL(ContextURL.with().asCollection().suffix(Suffix.REFERENCE).build()) + .count(countOption) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + + Assert.assertThat(resultString, CoreMatchers.startsWith("{" + + "\"@context\":\"$metadata#Collection($ref)\"," + + "\"@count\":\"3\",\"value\":[")); + Assert.assertThat(resultString, CoreMatchers.endsWith("]," + + "\"@nextLink\":\"/next\"}")); + + int count = 0; + int index = -1; + while ((index = resultString.indexOf("ESAllPrim(", ++index)) > 0) { + count++; + } + Assert.assertEquals(3, count); + } + + @Test + public void geoPoint() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPoint); + Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + createPoint(1.5, 4.25))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"Point\",\"coordinates\":[1.5,4.25]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + + Point point = new Point(Dimension.GEOMETRY, null); + point.setZ(42); + entity = new Entity().addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + point)); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"Point\",\"coordinates\":[0.0,0.0,42.0]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + @Test + public void geoMultiPoint() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiPoint); + final Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new MultiPoint(Dimension.GEOMETRY, null, Arrays.asList( + createPoint(2.5, 3.125), createPoint(3.5, 4.125), createPoint(4.5, 5.125))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"MultiPoint\",\"coordinates\":[[2.5,3.125],[3.5,4.125],[4.5,5.125]]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + @Test + public void geoLineString() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryLineString); + final Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new LineString(Dimension.GEOMETRY, null, Arrays.asList( + createPoint(1, 1), createPoint(2, 2), createPoint(3, 3), createPoint(4, 4), createPoint(5, 5))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"LineString\",\"coordinates\":[[1.0,1.0],[2.0,2.0],[3.0,3.0],[4.0,4.0],[5.0,5.0]]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + @Test + public void geoMultiLineString() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiLineString); + final Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new MultiLineString(Dimension.GEOMETRY, null, Arrays.asList( + new LineString(Dimension.GEOMETRY, null, Arrays.asList( + createPoint(1, 1), createPoint(2, 2), createPoint(3, 3), createPoint(4, 4), createPoint(5, 5))), + new LineString(Dimension.GEOMETRY, null, Arrays.asList( + createPoint(99.5, 101.5), createPoint(150, 151.25))))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"MultiLineString\",\"coordinates\":[" + + "[[1.0,1.0],[2.0,2.0],[3.0,3.0],[4.0,4.0],[5.0,5.0]]," + + "[[99.5,101.5],[150.0,151.25]]]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + @Test + public void geoPolygon() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPolygon); + Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new Polygon(Dimension.GEOMETRY, null, + Arrays.asList( + createPoint(1, 1), createPoint(1, 2), createPoint(2, 2), createPoint(2, 1), createPoint(1, 1)), + Arrays.asList( + createPoint(0, 0), createPoint(3, 0), createPoint(3, 3), createPoint(0, 3), createPoint(0, 0))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"Polygon\",\"coordinates\":[[[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]]," + + "[[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + + entity = new Entity().addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new Polygon(Dimension.GEOMETRY, null, null, Arrays.asList( + createPoint(10, 10), createPoint(30, 10), createPoint(30, 30), createPoint(10, 30), + createPoint(10, 10))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"Polygon\",\"coordinates\":[[[10.0,10.0],[30.0,10.0],[30.0,30.0],[10.0,30.0],[10.0,10.0]]]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + @Test + public void geoMultiPolygon() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiPolygon); + final Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new MultiPolygon(Dimension.GEOMETRY, null, Arrays.asList( + new Polygon(Dimension.GEOMETRY, null, + Arrays.asList( + createPoint(1, 1), createPoint(1, 2), createPoint(2, 2), createPoint(2, 1), createPoint(1, 1)), + Arrays.asList( + createPoint(0, 0), createPoint(3, 0), createPoint(3, 3), createPoint(0, 3), + createPoint(0, 0))), + new Polygon(Dimension.GEOMETRY, null, + Arrays.asList( + createPoint(10, 10), createPoint(10, 20), createPoint(20, 10), createPoint(10, 10)), + Arrays.asList( + createPoint(0, 0), createPoint(30, 0), createPoint(0, 30), createPoint(0, 0))))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"MultiPolygon\",\"coordinates\":[" + + "[[[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]]," + + "[[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]]," + + "[[[0.0,0.0],[30.0,0.0],[0.0,30.0],[0.0,0.0]]," + + "[[10.0,10.0],[10.0,20.0],[20.0,10.0],[10.0,10.0]]]]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + @Test + public void geoCollection() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryCollection); + final Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new GeospatialCollection(Dimension.GEOMETRY, null, Arrays.asList( + createPoint(100, 0), + new LineString(Dimension.GEOMETRY, null, Arrays.asList(createPoint(101, 0), createPoint(102, 1))))))); + Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{" + + "\"type\":\"GeometryCollection\",\"geometries\":[" + + "{\"type\":\"Point\",\"coordinates\":[100.0,0.0]}," + + "{\"type\":\"LineString\",\"coordinates\":[[101.0,0.0],[102.0,1.0]]}]}}", + IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent())); + } + + private EdmEntityType mockEntityType(final EdmPrimitiveTypeKind type) { + EdmProperty property = Mockito.mock(EdmProperty.class); + final String name = "Property" + type.name(); + Mockito.when(property.getName()).thenReturn(name); + Mockito.when(property.getType()).thenReturn(odata.createPrimitiveTypeInstance(type)); + Mockito.when(property.isPrimitive()).thenReturn(true); + EdmEntityType entityType = Mockito.mock(EdmEntityType.class); + Mockito.when(entityType.getPropertyNames()).thenReturn(Arrays.asList(name)); + Mockito.when(entityType.getStructuralProperty(name)).thenReturn(property); + return entityType; + } + + @Test + public void geoNonstandardSRID() throws Exception { + final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPoint); + final Entity entity = new Entity() + .addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL, + new Point(Dimension.GEOMETRY, SRID.valueOf("42")))); + try { + serializerNoMetadata.entity(metadata, entityType, entity, null); + fail("Expected exception not thrown."); + } catch (final SerializerException e) { + assertNotNull(e); + } + } + + private Point createPoint(final double x, final double y) { + Point point = new Point(Dimension.GEOMETRY, null); + point.setX(x); + point.setY(y); + return point; + } + + @Test + public void expandCycle() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESPeople"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + ExpandItem mockExpandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "friends"); + LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class); + Mockito.when(levels.isMax()).thenReturn(Boolean.TRUE); + Mockito.when(mockExpandItem.getLevelsOption()).thenReturn(levels); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(mockExpandItem)); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()) + .getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{" + + "\"@context\":\"$metadata#ESPeople/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"id\":1," + + "\"name\":\"B\"," + + "\"friends\":[" + + "{" + + "\"id\":0," + + "\"name\":\"A\"," + + "\"friends\":[" + + "{" + + "\"@id\":\"ESPeople(1)\"" + + "}," + + "{" + + "\"id\":2," + + "\"name\":\"C\"," + + "\"friends\":[" + + "{" + + "\"@id\":\"ESPeople(0)\"" + + "}," + + "{" + + "\"id\":3," + + "\"name\":\"D\"," + + "\"friends\":[" + + "]" + + "}" + + "]" + + "}" + + "]" + + "}," + + "{" + + "\"id\":2," + + "\"name\":\"C\"," + + "\"friends\":[" + + "{" + + "\"id\":0," + + "\"name\":\"A\"," + + "\"friends\":[" + + "{" + + "\"@id\":\"ESPeople(1)\"" + + "}," + + "{" + + "\"@id\":\"ESPeople(2)\"" + + "}" + + "]" + + "}," + + "{" + + "\"id\":3," + + "\"name\":\"D\"," + + "\"friends\":[" + + "]" + + "}" + + "]" + + "}" + + "]" + + "}"; + Assert.assertEquals(expected, resultString); + } + + @Test + public void expandCycleWith3Level() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESPeople"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + ExpandItem mockExpandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "friends"); + LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class); + Mockito.when(levels.isMax()).thenReturn(Boolean.FALSE); + Mockito.when(levels.getValue()).thenReturn(3); + Mockito.when(mockExpandItem.getLevelsOption()).thenReturn(levels); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(mockExpandItem)); + InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .expand(expand) + .build()) + .getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{" + + "\"@context\":\"$metadata#ESPeople/$entity\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"id\":1," + + "\"name\":\"B\"," + + "\"friends\":[" + + "{" + + "\"id\":0," + + "\"name\":\"A\"," + + "\"friends\":[" + + "{" + + "\"@id\":\"ESPeople(1)\"" + + "}," + + "{" + + "\"id\":2," + + "\"name\":\"C\"," + + "\"friends\":[" + + "{" + + "\"@id\":\"ESPeople(0)\"" + + "}," + + "{" + + "\"id\":3," + + "\"name\":\"D\"" + + "}" + + "]" + + "}" + + "]" + + "}," + + "{" + + "\"id\":2," + + "\"name\":\"C\"," + + "\"friends\":[" + + "{" + + "\"id\":0," + + "\"name\":\"A\"," + + "\"friends\":[" + + "{" + + "\"@id\":\"ESPeople(1)\"" + + "}," + + "{" + + "\"@id\":\"ESPeople(2)\"" + + "}" + + "]" + + "}," + + "{" + + "\"id\":3," + + "\"name\":\"D\"," + + "\"friends\":[" + + "]" + + "}" + + "]" + + "}" + + "]" + + "}"; + Assert.assertEquals(expected, resultString); + } + + @Test + public void deriveComplexProperty() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + EdmComplexType derivedComplexType = mockComplexType(); + final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("PropertyComp"); + final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty("PropertyComp"); + + final String resultString = IOUtils.toString(serializer + .complex(metadata, derivedComplexType, property, + ComplexSerializerOptions.with() + .contextURL(ContextURL.with() + .entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName() + + "/olingo.odata.test1.CTBase") + .build()) + .build()).getContent()); + Assert.assertEquals("{\"@context\":\"$metadata#ESMixPrimCollComp(32767)/" + + "PropertyComp/olingo.odata.test1.CTBase\"," + + "\"@metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"@type\":\"#olingo.odata.test1.CTBase\"," + + "\"AdditionalPropertyString\":null," + + "\"PropertyInt16\":111," + + "\"PropertyString\":\"TEST A\"}", + resultString); + } + + private EdmComplexType mockComplexType() { + EdmProperty property1 = Mockito.mock(EdmProperty.class); + final String name1 = "AdditionalPropertyString"; + Mockito.when(property1.getName()).thenReturn(name1); + Mockito.when(property1.isNullable()).thenReturn(true); + Mockito.when(property1.getType()).thenReturn(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String)); + Mockito.when(property1.isPrimitive()).thenReturn(true); + + EdmProperty property2 = Mockito.mock(EdmProperty.class); + final String name2 = "PropertyInt16"; + Mockito.when(property2.getName()).thenReturn(name2); + Mockito.when(property2.isNullable()).thenReturn(false); + Mockito.when(property2.getType()).thenReturn(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16)); + Mockito.when(property2.isPrimitive()).thenReturn(true); + + EdmProperty property3 = Mockito.mock(EdmProperty.class); + final String name3 = "PropertyString"; + Mockito.when(property3.getName()).thenReturn(name3); + Mockito.when(property3.isNullable()).thenReturn(false); + Mockito.when(property3.getMaxLength()).thenReturn(50); + Mockito.when(property3.getType()).thenReturn(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String)); + Mockito.when(property3.isPrimitive()).thenReturn(true); + + EdmComplexType complexType = Mockito.mock(EdmComplexType.class); + Mockito.when(complexType.getPropertyNames()).thenReturn(Arrays.asList(name1, name2, name3)); + Mockito.when(complexType.getStructuralProperty(name1)).thenReturn(property1); + Mockito.when(complexType.getStructuralProperty(name2)).thenReturn(property2); + Mockito.when(complexType.getStructuralProperty(name3)).thenReturn(property3); + EdmComplexType baseComplexType = metadata.getEdm().getComplexType( + new FullQualifiedName("olingo.odata.test1.CTTwoPrim")); + Mockito.when(complexType.getBaseType()).thenReturn(baseComplexType); + Mockito.when(complexType.getFullQualifiedName()).thenReturn( + new FullQualifiedName("olingo.odata.test1.CTBase")); + Mockito.when(complexType.getName()).thenReturn("CTBase"); + Mockito.when(complexType.getNamespace()).thenReturn("olingo.odata.test1"); + return complexType; + } +}