Repository: olingo-odata4 Updated Branches: refs/heads/OLINGO-832_StreamSerializerPoC [created] f4ad8892a
[OLINGO-832] First idea of PoC Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/f4ad8892 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/f4ad8892 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/f4ad8892 Branch: refs/heads/OLINGO-832_StreamSerializerPoC Commit: f4ad8892adf11a91e99b7bc555f6c765140d5bc9 Parents: d88913f Author: Michael Bolz <[email protected]> Authored: Tue Dec 8 14:49:26 2015 +0100 Committer: Michael Bolz <[email protected]> Committed: Mon Dec 14 09:12:03 2015 +0100 ---------------------------------------------------------------------- .../api/data/EntityStreamCollection.java | 28 +++ .../apache/olingo/server/core/ODataImpl.java | 4 +- .../core/serializer/StreamSerializerResult.java | 166 +++++++++++++++++ .../serializer/json/ODataJsonSerializer.java | 10 +- .../json/ODataJsonStreamSerializer.java | 183 +++++++++++++++++++ .../processor/TechnicalEntityProcessor.java | 116 +++++++++++- 6 files changed, 500 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f4ad8892/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityStreamCollection.java ---------------------------------------------------------------------- diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityStreamCollection.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityStreamCollection.java new file mode 100644 index 0000000..9eae442 --- /dev/null +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/EntityStreamCollection.java @@ -0,0 +1,28 @@ +/* + * 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.data; + +/** + * Data representation for a collection of single entities. + */ +public abstract class EntityStreamCollection extends EntityCollection { + + public abstract boolean hasNext(); + public abstract Entity nextEntity(); +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f4ad8892/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataImpl.java ---------------------------------------------------------------------- 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 ad7d410..df6c7df 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 @@ -49,6 +49,7 @@ import org.apache.olingo.server.core.etag.ETagHelperImpl; import org.apache.olingo.server.core.prefer.PreferencesImpl; import org.apache.olingo.server.core.serializer.FixedFormatSerializerImpl; import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer; +import org.apache.olingo.server.core.serializer.json.ODataJsonStreamSerializer; import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializer; import org.apache.olingo.server.core.uri.UriHelperImpl; @@ -63,7 +64,8 @@ public class ODataImpl extends OData { if (metadata == null || ContentType.VALUE_ODATA_METADATA_MINIMAL.equals(metadata) || ContentType.VALUE_ODATA_METADATA_NONE.equals(metadata)) { - serializer = new ODataJsonSerializer(contentType); +// serializer = new ODataJsonSerializer(contentType); + serializer = new ODataJsonStreamSerializer(contentType); } } else if (contentType.isCompatible(ContentType.APPLICATION_XML) || contentType.isCompatible(ContentType.APPLICATION_ATOM_XML)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f4ad8892/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/StreamSerializerResult.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/StreamSerializerResult.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/StreamSerializerResult.java new file mode 100644 index 0000000..d45c594 --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/StreamSerializerResult.java @@ -0,0 +1,166 @@ +/* + * 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; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityStreamCollection; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.core.serializer.json.ODataJsonStreamSerializer; +import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class StreamSerializerResult implements SerializerResult { + private InputStream content; + + private static class StreamInputStream extends InputStream { + private String head; + private String tail; + private int tailCount = 0; + private int headCount = 0; + private int entityCount = 0; + private InputStream inputStream = null; + private ODataJsonStreamSerializer jsonSerializer; + private EntityStreamCollection coll; + private ServiceMetadata metadata; + private EdmEntityType entityType; + private EntitySerializerOptions options; + + public StreamInputStream(EntityStreamCollection coll, EdmEntityType entityType, String head, + ODataJsonStreamSerializer jsonSerializer, ServiceMetadata metadata, + EntitySerializerOptions options, String tail) { + this.coll = coll; + this.entityType = entityType; + this.head = head; + this.jsonSerializer = jsonSerializer; + this.metadata = metadata; + this.options = options; + this.tail = tail; + } + + @Override + public int read() throws IOException { + if (headCount < head.length()) { + return head.charAt(headCount++); + } + if (inputStream == null && coll.hasNext()) { + try { + inputStream = serEntity(coll.nextEntity()); + entityCount++; + if (entityCount > 1) { + return (int) ','; + } + } catch (SerializerException e) { + inputStream = null; + return read(); + } + } + if (inputStream != null) { + int read = inputStream.read(); + if (read == -1) { + inputStream = null; + return read(); + } + return read; + } + if (tailCount < tail.length()) { + return tail.charAt(tailCount++); + } + return -1; + } + + private InputStream serEntity(Entity entity) throws SerializerException { + try { + CircleStreamBuffer buffer = new CircleStreamBuffer(); + OutputStream outputStream = buffer.getOutputStream(); + JsonGenerator json = new JsonFactory().createGenerator(outputStream); + jsonSerializer.writeEntity(metadata, entityType, entity, null, + options == null ? null : options.getExpand(), + options == null ? null : options.getSelect(), + options != null && options.getWriteOnlyReferences(), + json); + + json.close(); + outputStream.close(); + return buffer.getInputStream(); + } catch (final IOException e) { + return new ByteArrayInputStream(("ERROR" + e.getMessage()).getBytes()); +// } catch (SerializerException e) { +// return new ByteArrayInputStream(("ERROR" + e.getMessage()).getBytes()); + } + } + } + + @Override + public InputStream getContent() { + return content; + } + + private StreamSerializerResult(InputStream content) { + this.content = content; + } + + public static SerializerResultBuilder with(EntityStreamCollection coll, EdmEntityType entityType, + ODataJsonStreamSerializer jsonSerializer, ServiceMetadata metadata, EntitySerializerOptions options) { + return new SerializerResultBuilder(coll, entityType, jsonSerializer, metadata, options); + } + + public static class SerializerResultBuilder { + private ODataJsonStreamSerializer jsonSerializer; + private EntityStreamCollection coll; + private ServiceMetadata metadata; + private EdmEntityType entityType; + private EntitySerializerOptions options; + private String head; + private String tail; + + public SerializerResultBuilder(EntityStreamCollection coll, EdmEntityType entityType, + ODataJsonStreamSerializer jsonSerializer, ServiceMetadata metadata, EntitySerializerOptions options) { + this.coll = coll; + this.entityType = entityType; + this.jsonSerializer = jsonSerializer; + this.metadata = metadata; + this.options = options; + } + + public SerializerResultBuilder addHead(String head) { + this.head = head; + return this; + } + + public SerializerResultBuilder addTail(String tail) { + this.tail = tail; + return this; + } + + public SerializerResult build() { + InputStream input = new StreamInputStream(coll, entityType, head, jsonSerializer, metadata, options, tail); + return new StreamSerializerResult(input); + } + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f4ad8892/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java index b5a2c6a..4a1a528 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 @@ -203,7 +203,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } } - private ContextURL checkContextURL(final ContextURL contextURL) throws SerializerException { + ContextURL checkContextURL(final ContextURL contextURL) throws SerializerException { if (isODataMetadataNone) { return null; } else if (contextURL == null) { @@ -767,13 +767,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } - private void writeContextURL(final ContextURL contextURL, JsonGenerator json) throws IOException { + void writeContextURL(final ContextURL contextURL, JsonGenerator json) throws IOException { if (!isODataMetadataNone && contextURL != null) { json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString()); } } - private void writeMetadataETag(final ServiceMetadata metadata, JsonGenerator json) throws IOException { + void writeMetadataETag(final ServiceMetadata metadata, JsonGenerator json) throws IOException { if (!isODataMetadataNone && metadata != null && metadata.getServiceMetadataETagSupport() != null @@ -783,7 +783,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } } - private void writeCount(final EntityCollection entityCollection, JsonGenerator json) throws IOException { + void writeCount(final EntityCollection entityCollection, JsonGenerator json) throws IOException { if (entityCollection.getCount() != null) { if (isIEEE754Compatible) { json.writeStringField(Constants.JSON_COUNT, entityCollection.getCount().toString()); @@ -793,7 +793,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { } } - private void writeNextLink(final EntityCollection entitySet, JsonGenerator json) throws IOException { + void writeNextLink(final EntityCollection entitySet, JsonGenerator json) throws IOException { if (entitySet.getNext() != null) { json.writeStringField(Constants.JSON_NEXT_LINK, entitySet.getNext().toASCIIString()); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f4ad8892/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonStreamSerializer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonStreamSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonStreamSerializer.java new file mode 100644 index 0000000..08a30c6 --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonStreamSerializer.java @@ -0,0 +1,183 @@ +/* + * 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 com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import org.apache.olingo.commons.api.Constants; +import org.apache.olingo.commons.api.data.ComplexValue; +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.EntityStreamCollection; +import org.apache.olingo.commons.api.data.Link; +import org.apache.olingo.commons.api.data.Linked; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.edm.EdmComplexType; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +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.EdmType; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory; +import org.apache.olingo.server.api.ODataServerError; +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.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.ExpandItem; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; +import org.apache.olingo.server.core.serializer.AbstractODataSerializer; +import org.apache.olingo.server.core.serializer.SerializerResultImpl; +import org.apache.olingo.server.core.serializer.StreamSerializerResult; +import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; +import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper; +import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder; +import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper; +import org.apache.olingo.server.core.uri.UriHelperImpl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ODataJsonStreamSerializer extends ODataJsonSerializer { + + private final ODataJsonSerializer serializer; + + public ODataJsonStreamSerializer(final ContentType contentType) { + super(contentType); + this.serializer = new ODataJsonSerializer(contentType); + } + + @Override + public SerializerResult entityCollection(final ServiceMetadata metadata, + final EdmEntityType entityType, final EntityCollection entitySet, + final EntityCollectionSerializerOptions options) throws SerializerException { + + EntityStreamCollection coll; + if(entitySet instanceof EntityStreamCollection) { + coll = (EntityStreamCollection) entitySet; + } else { + return serializer.entityCollection(metadata, entityType, entitySet, options); + } + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + SerializerException cachedException = null; + try { + JsonGenerator json = new JsonFactory().createGenerator(outputStream); + json.writeStartObject(); + + final ContextURL contextURL = serializer.checkContextURL(options == null ? null : options.getContextURL()); + serializer.writeContextURL(contextURL, json); + + serializer.writeMetadataETag(metadata, json); + + if (options != null && options.getCount() != null && options.getCount().getValue()) { + serializer.writeCount(entitySet, json); + } + json.writeFieldName(Constants.VALUE); + json.writeStartArray(); + json.close(); + outputStream.close(); + String temp = new String(outputStream.toByteArray(), Charset.forName("UTF-8")); + String head = temp.substring(0, temp.length()-2); + // if (options == null) { +// writeEntitySet(metadata, entityType, entitySet, null, null, false, json); +// } else { +// writeEntitySet(metadata, entityType, entitySet, +// options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json); +// } + + outputStream = new ByteArrayOutputStream(); + outputStream.write(']'); + outputStream.write('}'); + outputStream.close(); + String tail = new String(outputStream.toByteArray(), Charset.forName("UTF-8")); + + EntitySerializerOptions.Builder opt = EntitySerializerOptions.with(); + if(options != null) { + opt.expand(options.getExpand()).select(options + .getSelect()).writeOnlyReferences(options.getWriteOnlyReferences()); + } + return StreamSerializerResult.with(coll, entityType, this, metadata, opt.build()) + .addHead(head).addTail(tail).build(); + } catch (final IOException e) { + cachedException = + new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + throw cachedException; + } finally { + closeCircleStreamBufferOutput(outputStream, cachedException); + } + } + + @Override + public void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, + final Entity entity, final ContextURL contextURL, final ExpandOption expand, + final SelectOption select, final boolean onlyReference, final JsonGenerator json) + throws IOException, SerializerException { + serializer.writeEntity(metadata, entityType, entity, contextURL, expand, select, onlyReference, json); + } + +// @Override +// public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType, +// final Entity entity, final EntitySerializerOptions options) throws SerializerException { +// return serializer.entity(metadata, entityType, entity, options); +// } + +// protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType, +// final EntityCollection entitySet, final ExpandOption expand, final SelectOption select, +// final boolean onlyReference, final JsonGenerator json) throws IOException, +// SerializerException { +// +// json.writeStartArray(); +// json.writeEndArray(); +// + // json.writeStartArray(); +// for (final Entity entity : entitySet.getEntities()) { +// if (onlyReference) { +// json.writeStartObject(); +// json.writeStringField(Constants.JSON_ID, entity.getId().toASCIIString()); +// json.writeEndObject(); +// } else { +// serializer.writeEntity(metadata, entityType, entity, null, expand, select, false, json); +// } +// } +// json.writeEndArray(); +// } + +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f4ad8892/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java ---------------------------------------------------------------------- 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 6d7c41e..6644f1e 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 @@ -18,13 +18,20 @@ */ package org.apache.olingo.server.tecsvc.processor; +import java.util.Iterator; +import java.util.List; import java.util.Locale; +import java.util.Random; +import java.util.concurrent.TimeUnit; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Builder; 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.EntityStreamCollection; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; @@ -520,11 +527,17 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } // Serialize +// final SerializerResult serializerResult = (isReference) ? +// serializeReferenceCollection(entitySetSerialization, edmEntitySet, requestedContentType, countOption) : +// serializeEntityCollection(request, entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType, +// expand, select, countOption, id); final SerializerResult serializerResult = (isReference) ? serializeReferenceCollection(entitySetSerialization, edmEntitySet, requestedContentType, countOption) : - serializeEntityCollection(request, entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType, + serializeEntityStreamCollectionFixed(request, + entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType, expand, select, countOption, id); response.setContent(serializerResult.getContent()); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); if (pageSize != null) { @@ -533,6 +546,107 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } } + // just for demonstration + private SerializerResult serializeEntityStreamCollectionFixed(final ODataRequest request, + final EntityCollection entityCollection, final EdmEntitySet edmEntitySet, + final EdmEntityType edmEntityType, + final ContentType requestedFormat, final ExpandOption expand, final SelectOption select, + final CountOption countOption, final String id) throws ODataLibraryException { + + EntityStreamCollection streamCollection = new EntityStreamCollection() { + Iterator<Entity> entityIterator = entityCollection.getEntities().iterator(); + + @Override + public boolean hasNext() { + return entityIterator.hasNext(); + } + + @Override + public Entity nextEntity() { + Entity next = entityIterator.next(); + replacePrimitiveProperty(next, "PropertyString", generateData(28192)); +// next.getProperties().remove(1); +// next.addProperty(new Property(null, "PropertyString", ValueType.PRIMITIVE, generateData(28192))); + try { + TimeUnit.MILLISECONDS.sleep(2500); + } catch (InterruptedException e) { } + return next; + } + + @Override + public List<Entity> getEntities() { + return entityCollection.getEntities(); + } + + private void replacePrimitiveProperty(Entity entity, String name, Object data) { + List<Property> properties = entity.getProperties(); + int pos = 0; + for (Property property : properties) { + if(name.equals(property.getName())) { + properties.remove(pos); + entity.addProperty(new Property(null, name, ValueType.PRIMITIVE, data)); + break; + } + pos++; + } + } + + private String generateData(final int len) { + Random random = new Random(); + StringBuilder b = new StringBuilder(len); + for (int j = 0; j < len; j++) { + final char c = (char) ('A' + random.nextInt('Z' - 'A' + 1)); + b.append(c); + } + return b.toString(); + } + + }; + + return odata.createSerializer(requestedFormat).entityCollection( + serviceMetadata, + edmEntityType, + streamCollection, + EntityCollectionSerializerOptions.with() + .contextURL(isODataMetadataNone(requestedFormat) ? null : + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select)) + .count(countOption) + .expand(expand).select(select) + .id(id) + .build()); + } + + private SerializerResult serializeEntityStreamCollection(final ODataRequest request, + final EntityCollection entityCollection, final EdmEntitySet edmEntitySet, + final EdmEntityType edmEntityType, + final ContentType requestedFormat, final ExpandOption expand, final SelectOption select, + final CountOption countOption, final String id) throws ODataLibraryException { + + EntityStreamCollection streamCollection = new EntityStreamCollection() { + Iterator<Entity> test = entityCollection.getEntities().iterator(); + @Override + public boolean hasNext() { + return test.hasNext(); + } + + @Override + public Entity nextEntity() { + return test.next(); + } + }; + return odata.createSerializer(requestedFormat).entityCollection( + serviceMetadata, + edmEntityType, + streamCollection, + EntityCollectionSerializerOptions.with() + .contextURL(isODataMetadataNone(requestedFormat) ? null : + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select)) + .count(countOption) + .expand(expand).select(select) + .id(id) + .build()); + } + private SerializerResult serializeEntityCollection(final ODataRequest request, final EntityCollection entityCollection, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, final ContentType requestedFormat, final ExpandOption expand, final SelectOption select,
