[OlINGO-832] Clean up and basic IT test
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/09fd6d9b Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/09fd6d9b Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/09fd6d9b Branch: refs/heads/master Commit: 09fd6d9b48dd0b833176dbe0b2864c5065b99ee0 Parents: 4aa1277 Author: Michael Bolz <[email protected]> Authored: Fri Feb 19 21:57:31 2016 +0100 Committer: Michael Bolz <[email protected]> Committed: Fri Feb 19 21:57:31 2016 +0100 ---------------------------------------------------------------------- .../fit/tecsvc/http/BasicStreamITCase.java | 66 ++++++ .../server/api/WriteContentErrorCallback.java | 5 + .../server/api/WriteContentErrorContext.java | 4 +- .../server/core/ODataWritableContent.java | 235 +++++-------------- .../serializer/SerializerStreamResultImpl.java | 19 -- .../core/serializer/xml/ODataXmlSerializer.java | 62 ++++- .../processor/TechnicalEntityProcessor.java | 52 +++- 7 files changed, 247 insertions(+), 196 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..1903d13 --- /dev/null +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicStreamITCase.java @@ -0,0 +1,66 @@ +/* + * 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.fit.tecsvc.http; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.net.HttpURLConnection; +import java.net.URL; + +import org.apache.commons.io.IOUtils; +import org.apache.olingo.client.api.ODataClient; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpMethod; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.fit.AbstractBaseTestITCase; +import org.apache.olingo.fit.tecsvc.TecSvcConst; +import org.junit.Test; + +public class BasicStreamITCase extends AbstractBaseTestITCase { + + private static final String SERVICE_URI = TecSvcConst.BASE_URI + "/"; + + @Test + public void streamAllPrim() throws Exception { + URL url = new URL(SERVICE_URI + "ESAllPrim?$format=json"); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(HttpMethod.GET.name()); + connection.setRequestProperty("odata.streaming", "true"); + connection.connect(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode()); + assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE))); + + final String content = IOUtils.toString(connection.getInputStream()); + + assertTrue(content.contains("\"PropertyString\":\"First Resource - positive values->streamed\"")); + assertTrue(content.contains("\"PropertyString\":\"Second Resource - negative values->streamed\"")); + assertTrue(content.contains("\"PropertyString\":\"->streamed\"")); + } + + + @Override + protected ODataClient getClient() { + return null; + } + +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java index abc500a..3132876 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java @@ -18,8 +18,13 @@ */ package org.apache.olingo.server.api; +import java.io.OutputStream; import java.nio.channels.WritableByteChannel; +/** + * The WriteContentErrorCallback is called when during the {@link ODataContent#write(OutputStream)} + * or the {@link ODataContent#write(WritableByteChannel)} an error occurs. + */ public interface WriteContentErrorCallback { void handleError(WriteContentErrorContext context, WritableByteChannel channel); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java index d773df1..837c184 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java @@ -18,8 +18,10 @@ */ package org.apache.olingo.server.api; +/** + * The WriteContentErrorErrorContext is the parameter for the WriteContentErrorCallback. + */ public interface WriteContentErrorContext { Exception getException(); ODataLibraryException getODataLibraryException(); -// Object getParameter(String name); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java ---------------------------------------------------------------------- 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 904a6d0..7a7c142 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 @@ -20,15 +20,9 @@ package org.apache.olingo.server.core; import java.io.IOException; import java.io.OutputStream; -import java.nio.ByteBuffer; import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; -import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityIterator; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.ex.ODataRuntimeException; @@ -38,82 +32,60 @@ import org.apache.olingo.server.api.ServiceMetadata; import org.apache.olingo.server.api.WriteContentErrorCallback; import org.apache.olingo.server.api.WriteContentErrorContext; import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.serializer.SerializerStreamResult; import org.apache.olingo.server.core.serializer.SerializerStreamResultImpl; import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer; -import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; +import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializer; public class ODataWritableContent implements ODataContent { - private StreamChannel channel; - - private static class StreamChannel implements ReadableByteChannel { - private static final Charset DEFAULT = Charset.forName("UTF-8"); - private ByteBuffer head; - private ByteBuffer tail; - private ODataJsonSerializer jsonSerializer; - private EntityIterator coll; - private ServiceMetadata metadata; - private EdmEntityType entityType; - private EntityCollectionSerializerOptions options; - - public StreamChannel(EntityIterator coll, EdmEntityType entityType, String head, - ODataJsonSerializer jsonSerializer, ServiceMetadata metadata, - EntityCollectionSerializerOptions options, String tail) { - this.coll = coll; + private StreamContent streamContent; + + private static abstract class StreamContent { + protected ODataSerializer serializer; + protected EntityIterator iterator; + protected ServiceMetadata metadata; + protected EdmEntityType entityType; + protected EntityCollectionSerializerOptions options; + + public StreamContent(EntityIterator iterator, EdmEntityType entityType, + ODataSerializer serializer, ServiceMetadata metadata, + EntityCollectionSerializerOptions options) { + this.iterator = iterator; this.entityType = entityType; - this.head = head == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(head.getBytes(DEFAULT)); - this.jsonSerializer = jsonSerializer; + this.serializer = serializer; this.metadata = metadata; this.options = options; - this.tail = tail == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(tail.getBytes(DEFAULT)); } -// public boolean write(OutputStream out) throws IOException { -// if(head.hasRemaining()) { -// out.write(head.array()); -// head.flip(); -// return true; -// } -// if (coll.hasNext()) { -// try { -// writeEntity(coll.next(), out); -// if(coll.hasNext()) { -// out.write(",".getBytes(DEFAULT)); -// } -// return true; -// } catch (SerializerException e) { -// final WriteContentErrorCallback errorCallback = options.getWriteContentErrorCallback(); -// if(errorCallback != null) { -// final ErrorContext errorContext = new ErrorContext(e).setParameter("Sample", "Some exception happened."); -// errorCallback.handleError(errorContext, Channels.newChannel(out)); -// } -// } -// } else if(tail.hasRemaining()) { -// out.write(tail.array()); -// tail.flip(); -// return true; -// } -// return false; -// } + protected abstract void writeEntity(EntityIterator entity, OutputStream outputStream) throws SerializerException; public void write(OutputStream out) { try { - writeEntity(coll, out); + writeEntity(iterator, out); } catch (SerializerException e) { final WriteContentErrorCallback errorCallback = options.getWriteContentErrorCallback(); if(errorCallback != null) { - final ErrorContext errorContext = new ErrorContext(e).setParameter("Sample", "Some exception happened."); + final ErrorContext errorContext = new ErrorContext(e); errorCallback.handleError(errorContext, Channels.newChannel(out)); } } } + } + + private static class StreamContentForJson extends StreamContent { + private ODataJsonSerializer jsonSerializer; + public StreamContentForJson(EntityIterator iterator, EdmEntityType entityType, + ODataJsonSerializer jsonSerializer, ServiceMetadata metadata, + EntityCollectionSerializerOptions options) { + super(iterator, entityType, jsonSerializer, metadata, options); - private void writeEntity(EntityIterator entity, OutputStream outputStream) throws SerializerException { + this.jsonSerializer = jsonSerializer; + } + + protected void writeEntity(EntityIterator entity, OutputStream outputStream) throws SerializerException { try { jsonSerializer.entityCollectionIntoStream(metadata, entityType, entity, options, outputStream); outputStream.flush(); @@ -121,97 +93,32 @@ public class ODataWritableContent implements ODataContent { throw new ODataRuntimeException("Failed entity serialization"); } } + } - @Override - public int read(ByteBuffer dest) throws IOException { - ByteBuffer buffer = getCurrentBuffer(); - if (buffer != null && buffer.hasRemaining()) { - int r = buffer.remaining(); - if(r <= dest.remaining()) { - dest.put(buffer); - } else { - r = dest.remaining(); - byte[] buf = new byte[dest.remaining()]; - buffer.get(buf); - dest.put(buf); - } - return r; - } - return -1; - } + private static class StreamContentForXml extends StreamContent { + private ODataXmlSerializer xmlSerializer; - ByteBuffer currentBuffer; + public StreamContentForXml(EntityIterator iterator, EdmEntityType entityType, + ODataXmlSerializer xmlSerializer, ServiceMetadata metadata, + EntityCollectionSerializerOptions options) { + super(iterator, entityType, xmlSerializer, metadata, options); - private ByteBuffer getCurrentBuffer() { - if(currentBuffer == null) { - currentBuffer = head; - } - if(!currentBuffer.hasRemaining()) { - if (coll.hasNext()) { - try { - // FIXME: mibo_160108: Inefficient buffer handling, replace - currentBuffer = serEntity(coll.next()); - if(coll.hasNext()) { - ByteBuffer b = ByteBuffer.allocate(currentBuffer.position() + 1); - currentBuffer.flip(); - b.put(currentBuffer).put(",".getBytes(DEFAULT)); - currentBuffer = b; - } - currentBuffer.flip(); - } catch (SerializerException e) { - return getCurrentBuffer(); - } - } else if(tail.hasRemaining()) { - currentBuffer = tail; - } else { - return null; - } - } - return currentBuffer; + this.xmlSerializer = xmlSerializer; } - private ByteBuffer serEntity(Entity entity) throws SerializerException { + protected void writeEntity(EntityIterator entity, OutputStream outputStream) 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.getBuffer(); + xmlSerializer.entityCollectionIntoStream(metadata, entityType, entity, options, outputStream); + outputStream.flush(); } catch (final IOException e) { - return ByteBuffer.wrap(("ERROR" + e.getMessage()).getBytes()); + throw new ODataRuntimeException("Failed entity serialization"); } } - - - @Override - public boolean isOpen() { - return false; - } - - @Override - public void close() throws IOException { - - } - } - - public ReadableByteChannel getChannel() { - return this.channel; - } - - public boolean isWriteSupported() { - return true; } @Override public void write(WritableByteChannel writeChannel) { - this.channel.write(Channels.newOutputStream(writeChannel)); + this.streamContent.write(Channels.newOutputStream(writeChannel)); } @Override @@ -219,20 +126,18 @@ public class ODataWritableContent implements ODataContent { write(Channels.newChannel(stream)); } - private ODataWritableContent(StreamChannel channel) { - this.channel = channel; + private ODataWritableContent(StreamContent streamContent) { + this.streamContent = streamContent; } - public static ODataWritableContentBuilder with(EntityIterator coll, EdmEntityType entityType, - ODataJsonSerializer jsonSerializer, - ServiceMetadata metadata, EntityCollectionSerializerOptions options) { - return new ODataWritableContentBuilder(coll, entityType, jsonSerializer, metadata, options); + public static ODataWritableContentBuilder with(EntityIterator iterator, EdmEntityType entityType, + ODataSerializer serializer, ServiceMetadata metadata, + EntityCollectionSerializerOptions options) { + return new ODataWritableContentBuilder(iterator, entityType, serializer, metadata, options); } public static class ErrorContext implements WriteContentErrorContext { private ODataLibraryException exception; - final private Map<String, Object> parameters = new HashMap<String, Object>(); - public ErrorContext(ODataLibraryException exception) { this.exception = exception; } @@ -245,50 +150,36 @@ public class ODataWritableContent implements ODataContent { public ODataLibraryException getODataLibraryException() { return exception; } - - public ErrorContext setParameter(String name, Object value) { - parameters.put(name, value); - return this; - } - -// @Override - public Object getParameter(String name) { - return parameters.get(name); - } } public static class ODataWritableContentBuilder { - private ODataJsonSerializer jsonSerializer; + private ODataSerializer serializer; private EntityIterator entities; private ServiceMetadata metadata; private EdmEntityType entityType; private EntityCollectionSerializerOptions options; - private String head; - private String tail; public ODataWritableContentBuilder(EntityIterator entities, EdmEntityType entityType, - ODataJsonSerializer jsonSerializer, + ODataSerializer serializer, ServiceMetadata metadata, EntityCollectionSerializerOptions options) { this.entities = entities; this.entityType = entityType; - this.jsonSerializer = jsonSerializer; + this.serializer = serializer; this.metadata = metadata; this.options = options; } - public ODataWritableContentBuilder addHead(String head) { - this.head = head; - return this; - } - - public ODataWritableContentBuilder addTail(String tail) { - this.tail = tail; - return this; - } - public ODataContent buildContent() { - StreamChannel input = new StreamChannel(entities, entityType, head, jsonSerializer, metadata, options, tail); - return new ODataWritableContent(input); + if(serializer instanceof ODataJsonSerializer) { + StreamContent input = new StreamContentForJson(entities, entityType, + (ODataJsonSerializer) serializer, metadata, options); + return new ODataWritableContent(input); + } else if(serializer instanceof ODataXmlSerializer) { + StreamContentForXml input = new StreamContentForXml(entities, entityType, + (ODataXmlSerializer) serializer, metadata, options); + return new ODataWritableContent(input); + } + throw new ODataRuntimeException("No suitable serializer found"); } public SerializerStreamResult build() { return SerializerStreamResultImpl.with().content(buildContent()).build(); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/SerializerStreamResultImpl.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/SerializerStreamResultImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/SerializerStreamResultImpl.java index 14fab97..a7c0efc 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/SerializerStreamResultImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/SerializerStreamResultImpl.java @@ -18,14 +18,10 @@ */ package org.apache.olingo.server.core.serializer; -import java.io.InputStream; - import org.apache.olingo.server.api.ODataContent; -import org.apache.olingo.server.api.serializer.SerializerResult; import org.apache.olingo.server.api.serializer.SerializerStreamResult; public class SerializerStreamResultImpl implements SerializerStreamResult { - private InputStream content; private ODataContent oDataContent; @Override @@ -33,21 +29,6 @@ public class SerializerStreamResultImpl implements SerializerStreamResult { return oDataContent; } - // @Override -// public ReadableByteChannel getChannel() { -// return Channels.newChannel(getContent()); -// } -// -// @Override -// public void write(WritableByteChannel channel) { -// ResultHelper.copy(Channels.newChannel(content), channel); -// } -// -// @Override -// public boolean isWriteSupported() { -// return false; -// } - public static SerializerResultBuilder with() { return new SerializerResultBuilder(); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java index a42e3df..2fa16ea 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java @@ -70,6 +70,7 @@ import org.apache.olingo.server.api.serializer.SerializerStreamResult; import org.apache.olingo.server.api.uri.queryoption.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.ODataWritableContent; import org.apache.olingo.server.core.serializer.AbstractODataSerializer; import org.apache.olingo.server.core.serializer.SerializerResultImpl; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; @@ -282,10 +283,67 @@ public class ODataXmlSerializer extends AbstractODataSerializer { } } + public void entityCollectionIntoStream(ServiceMetadata metadata, EdmEntityType entityType, EntityIterator entitySet, + EntityCollectionSerializerOptions options, OutputStream outputStream) throws SerializerException { + + final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL()); +// if (options != null && options.getWriteOnlyReferences()) { +// ReferenceCollectionSerializerOptions rso = ReferenceCollectionSerializerOptions.with() +// .contextURL(contextURL).build(); +// return entityReferenceCollection(entitySet, rso); +// } + + SerializerException cachedException = null; + try { + CircleStreamBuffer buffer = new CircleStreamBuffer(); + outputStream = buffer.getOutputStream(); + XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, DEFAULT_CHARSET); + writer.writeStartDocument(DEFAULT_CHARSET, "1.0"); + writer.writeStartElement(ATOM, Constants.ATOM_ELEM_FEED, NS_ATOM); + writer.writeNamespace(ATOM, NS_ATOM); + writer.writeNamespace(METADATA, NS_METADATA); + writer.writeNamespace(DATA, NS_DATA); + + writer.writeAttribute(METADATA, NS_METADATA, Constants.CONTEXT, + ContextURLBuilder.create(contextURL).toASCIIString()); + writeMetadataETag(metadata, writer); + + if (options != null && options.getId() != null) { + writer.writeStartElement(ATOM, Constants.ATOM_ELEM_ID, NS_ATOM); + writer.writeCharacters(options.getId()); + writer.writeEndElement(); + } + + if (options != null && options.getCount() != null && options.getCount().getValue() + && entitySet.getCount() != null) { + writeCount(entitySet, writer); + } + if (entitySet.getNext() != null) { + writeNextLink(entitySet, writer); + } + + if (options == null) { + writeEntitySet(metadata, entityType, entitySet, null, null, null, writer); + } else { + writeEntitySet(metadata, entityType, entitySet, + options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer); + } + + writer.writeEndElement(); + writer.writeEndDocument(); + + writer.flush(); + } catch (final XMLStreamException e) { + cachedException = + new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION); + throw cachedException; + } + } + @Override public SerializerStreamResult entityCollectionStreamed(ServiceMetadata metadata, EdmEntityType entityType, EntityIterator entities, EntityCollectionSerializerOptions options) throws SerializerException { - throw new ODataRuntimeException("entityCollectionStreamed for XML not supported (yet)"); + return ODataWritableContent.with(entities, entityType, this, metadata, options).build(); } @Override @@ -1163,5 +1221,5 @@ public class ODataXmlSerializer extends AbstractODataSerializer { return value; } return result.toString(); - } + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/09fd6d9b/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 28989d6..850867e 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 @@ -19,6 +19,7 @@ package org.apache.olingo.server.tecsvc.processor; import java.util.Iterator; +import java.util.List; import java.util.Locale; import org.apache.olingo.commons.api.data.ContextURL; @@ -27,6 +28,8 @@ 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.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; @@ -526,13 +529,19 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final SerializerResult serializerResult = serializeReferenceCollection(entitySetSerialization, edmEntitySet, requestedContentType, countOption); response.setContent(serializerResult.getContent()); - } else { + } else if(isOdataStreaming(request)) { final SerializerStreamResult serializerResult = serializeEntityCollectionStreamed(request, entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType, expand, select, countOption, id); response.setODataContent(serializerResult.getODataContent()); + } else { + final SerializerResult serializerResult = + serializeEntityCollection(request, + entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType, + expand, select, countOption, id); + response.setContent(serializerResult.getContent()); } // @@ -544,6 +553,29 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } } + private boolean isOdataStreaming(ODataRequest request) { + String odataStreaming = request.getHeader("odata.streaming"); + return Boolean.parseBoolean(odataStreaming); + } + + private SerializerResult serializeEntityCollection(final ODataRequest request, final EntityCollection + entityCollection, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, + final ContentType requestedFormat, final ExpandOption expand, final SelectOption select, + final CountOption countOption, String id) throws ODataLibraryException { + + return odata.createSerializer(requestedFormat).entityCollection( + serviceMetadata, + edmEntityType, + entityCollection, + EntityCollectionSerializerOptions.with() + .contextURL(isODataMetadataNone(requestedFormat) ? null : + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select)) + .count(countOption) + .expand(expand).select(select) + .id(id) + .build()); + } + // serialise as streamed collection private SerializerStreamResult serializeEntityCollectionStreamed(final ODataRequest request, final EntityCollection entityCollection, final EdmEntitySet edmEntitySet, @@ -561,7 +593,23 @@ public class TechnicalEntityProcessor extends TechnicalProcessor @Override public Entity next() { - return entityIterator.next(); + return addToPrimitiveProperty(entityIterator.next(), "PropertyString", "->streamed"); + } + + private Entity addToPrimitiveProperty(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); + final String old = property.getValue().toString(); + String newValue = (old == null ? "": old) + data.toString(); + entity.addProperty(new Property(null, name, ValueType.PRIMITIVE, newValue)); + break; + } + pos++; + } + return entity; } };
