Repository: olingo-odata4
Updated Branches:
  refs/heads/OLINGO-1066_StreamSupport [created] 9de1d310b


[OLINGO-1066] Collection stream support for primitive and complex type 
collections

Signed-off-by: mibo <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/685b19e5
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/685b19e5
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/685b19e5

Branch: refs/heads/OLINGO-1066_StreamSupport
Commit: 685b19e57225c2ffaa400457e377bb5f7ad6f35c
Parents: e41b81e
Author: Kavindu Dodanduwa <[email protected]>
Authored: Mon Jan 2 15:31:38 2017 +0530
Committer: mibo <[email protected]>
Committed: Sat Feb 18 22:39:31 2017 +0100

----------------------------------------------------------------------
 .../commons/api/data/CollectionIterator.java    |  40 ++++
 .../commons/api/data/ComplexIterator.java       |  47 ++++
 .../commons/api/data/PrimitiveIterator.java     |  44 ++++
 .../serializer/ComplexSerializerOptions.java    |  30 ++-
 .../server/api/serializer/ODataSerializer.java  |  21 ++
 .../serializer/PrimitiveSerializerOptions.java  |  21 +-
 .../server/core/CollectionWritableContent.java  |  39 ++++
 .../server/core/ComplexStreamContent.java       |  86 ++++++++
 .../core/ComplexStreamContentForJson.java       |  52 +++++
 .../server/core/ComplexStreamContentForXml.java |  52 +++++
 .../server/core/ODataWritableContent.java       |  22 +-
 .../server/core/PrimitiveStreamContent.java     |  96 ++++++++
 .../core/PrimitiveStreamContentForJson.java     |  56 +++++
 .../core/PrimitiveStreamContentForXml.java      |  56 +++++
 .../olingo/server/core/WriteErrorContext.java   |  41 ++++
 .../serializer/json/ODataJsonSerializer.java    | 149 +++++++++++++
 .../core/serializer/xml/ODataXmlSerializer.java | 130 ++++++++++-
 .../json/ODataJsonSerializerTest.java           | 179 ++++++++++++++-
 .../serializer/xml/ODataXmlSerializerTest.java  | 219 +++++++++++++++++++
 19 files changed, 1352 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/CollectionIterator.java
----------------------------------------------------------------------
diff --git 
a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/CollectionIterator.java
 
b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/CollectionIterator.java
new file mode 100644
index 0000000..d0e6715
--- /dev/null
+++ 
b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/CollectionIterator.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class CollectionIterator<T> implements Iterator<T>, 
Iterable<T> {
+
+  private List<Operation> operations = new ArrayList<Operation>();
+
+  public List<Operation> getOperations() {
+    return operations;
+  }
+
+  public abstract boolean hasNext();
+
+  public abstract T next();
+
+  public Iterator<T> iterator() {
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ComplexIterator.java
----------------------------------------------------------------------
diff --git 
a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ComplexIterator.java
 
b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ComplexIterator.java
new file mode 100644
index 0000000..f065b9b
--- /dev/null
+++ 
b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ComplexIterator.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+import org.apache.olingo.commons.api.ex.ODataNotSupportedException;
+
+public abstract class ComplexIterator extends CollectionIterator<ComplexValue> 
{
+
+  /**
+   * String representation of type (can be null)
+   */
+  private final String type;
+
+  public ComplexIterator() {
+    this.type = null;
+  }
+
+  public ComplexIterator(final String type) {
+    this.type = type;
+  }
+
+  public String getType() {
+    return type;
+  }
+
+  public void remove() {
+    //"Remove is not supported for iteration over Collection of Complex 
values."
+    throw new ODataNotSupportedException("Complex Iterator does not support 
remove()");
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/PrimitiveIterator.java
----------------------------------------------------------------------
diff --git 
a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/PrimitiveIterator.java
 
b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/PrimitiveIterator.java
new file mode 100644
index 0000000..ee50401
--- /dev/null
+++ 
b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/PrimitiveIterator.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+import org.apache.olingo.commons.api.ex.ODataNotSupportedException;
+
+public abstract class PrimitiveIterator<T> extends CollectionIterator<T> {
+
+  private final String name;
+
+  protected PrimitiveIterator(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Get name of property.
+   *
+   * @return name of property
+   */
+  public String getName() {
+    return name;
+  }
+
+  public void remove() {
+    //"Remove is not supported for iteration over Collection of Primitives."
+    throw new ODataNotSupportedException("Property Iterator does not support 
remove()");
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ComplexSerializerOptions.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ComplexSerializerOptions.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ComplexSerializerOptions.java
index 179c4d4..3eed831 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ComplexSerializerOptions.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ComplexSerializerOptions.java
@@ -19,6 +19,7 @@
 package org.apache.olingo.server.api.serializer;
 
 import org.apache.olingo.commons.api.data.ContextURL;
+import org.apache.olingo.server.api.ODataContentWriteErrorCallback;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
 
@@ -29,6 +30,7 @@ public class ComplexSerializerOptions {
   private ExpandOption expand;
   private SelectOption select;
   private String xml10InvalidCharReplacement;
+  private ODataContentWriteErrorCallback odataContentWriteErrorCallback;
 
   /** Gets the {@link ContextURL}. */
   public ContextURL getContextURL() {
@@ -45,6 +47,18 @@ public class ComplexSerializerOptions {
     return select;
   }
 
+  /**
+   * Gets the callback which is used in case of an exception during
+   * write of the content (in case the content will be written/streamed
+   * in the future)
+   *
+   * @return callback which is used in case of an exception during
+   * write of the content
+   */
+  public ODataContentWriteErrorCallback getODataContentWriteErrorCallback() {
+    return odataContentWriteErrorCallback;
+  }
+
   /** Gets the replacement string for unicode characters, that is not allowed 
in XML 1.0 */
   public String xml10InvalidCharReplacement() {
     return xml10InvalidCharReplacement;
@@ -88,8 +102,20 @@ public class ComplexSerializerOptions {
     public Builder xml10InvalidCharReplacement(final String replacement) {
       options.xml10InvalidCharReplacement = replacement;
       return this;
-    } 
-    
+    }
+
+    /**
+     * Set the callback which is used in case of an exception during
+     * write of the content.
+     *
+     * @param ODataContentWriteErrorCallback the callback
+     * @return the builder
+     */
+    public Builder writeContentErrorCallback(ODataContentWriteErrorCallback 
ODataContentWriteErrorCallback) {
+      options.odataContentWriteErrorCallback = ODataContentWriteErrorCallback;
+      return this;
+    }
+
     /** Builds the OData serializer options. */
     public ComplexSerializerOptions build() {
       return options;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
index 4f6974d..890f375 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
@@ -19,10 +19,12 @@
 package org.apache.olingo.server.api.serializer;
 
 import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ComplexIterator;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.AbstractEntityCollection;
 import org.apache.olingo.commons.api.data.EntityIterator;
 import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
@@ -116,6 +118,16 @@ public interface ODataSerializer {
       PrimitiveSerializerOptions options) throws SerializerException;
 
   /**
+   * Writes streamed primitive-collection data into OutputStream.
+   * @param metadata metadata for the service
+   * @param type     the {@link EdmEntityType}
+   * @param iterator the data of the complex collection
+   * @param options  options for the serializer
+   */
+  SerializerStreamResult primitiveCollectionStreamed(ServiceMetadata metadata, 
EdmPrimitiveType type,
+      PrimitiveIterator iterator, PrimitiveSerializerOptions options) throws 
SerializerException;
+
+  /**
    * Writes data of a collection of complex-type instances into an InputStream.
    * @param metadata metadata for the service
    * @param type complex type
@@ -124,6 +136,15 @@ public interface ODataSerializer {
    */
   SerializerResult complexCollection(ServiceMetadata metadata, EdmComplexType 
type, Property property,
       ComplexSerializerOptions options) throws SerializerException;
+   /**
+    * Writes streamed complex-collection data into OutputStream.
+    * @param metadata metadata for the service
+    * @param type     the {@link EdmEntityType}
+    * @param iterator the data of the complex collection
+    * @param options  options for the serializer
+    */
+   SerializerStreamResult complexCollectionStreamed(ServiceMetadata metadata, 
EdmComplexType type,
+       ComplexIterator iterator, ComplexSerializerOptions options) throws 
SerializerException;
 
   /**
    * Writes a single entity reference into an InputStream.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/PrimitiveSerializerOptions.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/PrimitiveSerializerOptions.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/PrimitiveSerializerOptions.java
index 61a3160..5b3ad0d 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/PrimitiveSerializerOptions.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/PrimitiveSerializerOptions.java
@@ -20,6 +20,7 @@ package org.apache.olingo.server.api.serializer;
 
 import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.server.api.ODataContentWriteErrorCallback;
 
 /** Options for the OData serializer. */
 public final class PrimitiveSerializerOptions {
@@ -31,6 +32,7 @@ public final class PrimitiveSerializerOptions {
   private Integer scale;
   private Boolean isUnicode;
   private String xml10InvalidCharReplacement;
+  private ODataContentWriteErrorCallback odataContentWriteErrorCallback;
 
   /** Gets the {@link ContextURL}. */
   public ContextURL getContextURL() {
@@ -68,6 +70,18 @@ public final class PrimitiveSerializerOptions {
   }  
   
 
+  /**
+   * Gets the callback which is used in case of an exception during
+   * write of the content (in case the content will be written/streamed
+   * in the future)
+   * @return callback which is used in case of an exception during
+   * write of the content
+   *
+   */
+  public ODataContentWriteErrorCallback getODataContentWriteErrorCallback() {
+    return odataContentWriteErrorCallback;
+  }
+
   private PrimitiveSerializerOptions() {}
 
   /** Initializes the options builder. */
@@ -135,7 +149,12 @@ public final class PrimitiveSerializerOptions {
       options.xml10InvalidCharReplacement = replacement;
       return this;
     } 
-    
+
+    public Builder writeContentErrorCallback(ODataContentWriteErrorCallback 
ODataContentWriteErrorCallback) {
+      options.odataContentWriteErrorCallback = ODataContentWriteErrorCallback;
+      return this;
+    }
+
     /** Builds the OData serializer options. */
     public PrimitiveSerializerOptions build() {
       return options;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/CollectionWritableContent.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/CollectionWritableContent.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/CollectionWritableContent.java
new file mode 100644
index 0000000..27bb061
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/CollectionWritableContent.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import java.io.OutputStream;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+
+import org.apache.olingo.server.api.ODataContent;
+
+public abstract class CollectionWritableContent implements ODataContent {
+
+  protected abstract void writeCollection(OutputStream out);
+
+  public void write(OutputStream stream) {
+    write(Channels.newChannel(stream));
+  }
+
+  @Override
+  public void write(WritableByteChannel writeChannel) {
+    writeCollection(Channels.newOutputStream(writeChannel));
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContent.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContent.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContent.java
new file mode 100644
index 0000000..9496420
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContent.java
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+import java.io.OutputStream;
+import java.nio.channels.Channels;
+
+import org.apache.olingo.commons.api.data.ComplexIterator;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.server.api.ODataContentWriteErrorCallback;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
+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.xml.ODataXmlSerializer;
+
+public abstract class ComplexStreamContent extends CollectionWritableContent {
+  protected ComplexIterator iterator;
+  protected ServiceMetadata metadata;
+  protected EdmComplexType complexType;
+  protected ComplexSerializerOptions options;
+
+  protected ComplexStreamContent(ComplexIterator iterator, ServiceMetadata 
metadata, EdmComplexType
+          complexType, ComplexSerializerOptions options) {
+    this.iterator = iterator;
+    this.complexType = complexType;
+    this.metadata = metadata;
+    this.options = options;
+  }
+
+  protected abstract void writeComplex(OutputStream outputStream) throws 
SerializerException;
+
+  @Override
+  protected void writeCollection(OutputStream out) {
+    try {
+      writeComplex(out);
+    } catch (SerializerException e) {
+      final ODataContentWriteErrorCallback errorCallback = 
options.getODataContentWriteErrorCallback();
+      if (errorCallback != null) {
+        final WriteErrorContext errorContext = new WriteErrorContext(e);
+        errorCallback.handleError(errorContext, Channels.newChannel(out));
+      }
+    }
+  }
+
+  public static SerializerStreamResult ComplexWritableForJson(ComplexIterator 
iterator, EdmComplexType edmComplexType,
+          ODataJsonSerializer jsonSerializer, ServiceMetadata serviceMetadata,
+          ComplexSerializerOptions options) {
+    return SerializerStreamResultImpl.with()
+            .content(new ComplexStreamContentForJson(iterator,
+                                                     edmComplexType,
+                                                     jsonSerializer,
+                                                     serviceMetadata,
+                                                     options)).build();
+  }
+
+  public static SerializerStreamResult ComplexWritableForXml(ComplexIterator 
iterator, EdmComplexType
+          edmComplexType,
+          ODataXmlSerializer xmlSerializer, ServiceMetadata serviceMetadata,
+          ComplexSerializerOptions options) {
+    return SerializerStreamResultImpl.with()
+            .content(new ComplexStreamContentForXml(iterator,
+                                                    edmComplexType,
+                                                    xmlSerializer,
+                                                    serviceMetadata,
+                                                    options)).build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForJson.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForJson.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForJson.java
new file mode 100644
index 0000000..1a6a262
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForJson.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.olingo.commons.api.data.ComplexIterator;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
+
+class ComplexStreamContentForJson extends ComplexStreamContent {
+  private final ODataJsonSerializer jsonSerializer;
+
+  protected ComplexStreamContentForJson(ComplexIterator iterator, 
EdmComplexType edmComplexType,
+          ODataJsonSerializer jsonSerializer, ServiceMetadata serviceMetadata,
+          ComplexSerializerOptions options) {
+    super(iterator, serviceMetadata, edmComplexType, options);
+
+    this.jsonSerializer = jsonSerializer;
+  }
+
+  @Override
+  protected void writeComplex(OutputStream outputStream) throws 
SerializerException {
+    try {
+      jsonSerializer.complexCollectionIntoStream(metadata, complexType, 
iterator, options, outputStream);
+      outputStream.flush();
+    } catch (final IOException e) {
+      throw new ODataRuntimeException("Failed complex serialization", e);
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForXml.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForXml.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForXml.java
new file mode 100644
index 0000000..a6aec37
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ComplexStreamContentForXml.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.olingo.commons.api.data.ComplexIterator;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializer;
+
+class ComplexStreamContentForXml extends ComplexStreamContent {
+  private final ODataXmlSerializer xmlSerializer;
+
+  protected ComplexStreamContentForXml(ComplexIterator iterator, 
EdmComplexType edmComplexType,
+          ODataXmlSerializer xmlSerializer, ServiceMetadata serviceMetadata,
+          ComplexSerializerOptions options) {
+    super(iterator, serviceMetadata, edmComplexType, options);
+
+    this.xmlSerializer = xmlSerializer;
+  }
+
+  @Override
+  protected void writeComplex(OutputStream outputStream) throws 
SerializerException {
+    try {
+      xmlSerializer.complexCollectionIntoStream(metadata, complexType, 
iterator, options, outputStream);
+      outputStream.flush();
+    } catch (final IOException e) {
+      throw new ODataRuntimeException("Failed complex serialization", e);
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/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 8f6b213..9986a0f 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,8 @@ 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.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;
@@ -141,24 +139,6 @@ public class ODataWritableContent implements ODataContent {
     return new ODataWritableContentBuilder(iterator, entityType, serializer, 
metadata, options);
   }
 
-  public static class WriteErrorContext implements 
ODataContentWriteErrorContext {
-    private ODataLibraryException exception;
-
-    public WriteErrorContext(ODataLibraryException exception) {
-      this.exception = exception;
-    }
-
-    @Override
-    public Exception getException() {
-      return exception;
-    }
-
-    @Override
-    public ODataLibraryException getODataLibraryException() {
-      return exception;
-    }
-  }
-
   public static class ODataWritableContentBuilder {
     private ODataSerializer serializer;
     private EntityIterator entities;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContent.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContent.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContent.java
new file mode 100644
index 0000000..1a90b92
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContent.java
@@ -0,0 +1,96 @@
+/*
+ * 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;
+
+import java.io.OutputStream;
+import java.nio.channels.Channels;
+
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.server.api.ODataContentWriteErrorCallback;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
+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.xml.ODataXmlSerializer;
+
+public abstract class PrimitiveStreamContent extends CollectionWritableContent 
{
+  protected PrimitiveIterator iterator;
+  protected ServiceMetadata metadata;
+  protected EdmPrimitiveType primitiveType;
+  protected PrimitiveSerializerOptions options;
+
+  protected PrimitiveStreamContent(
+          PrimitiveIterator iterator,
+          ServiceMetadata metadata,
+          EdmPrimitiveType primitiveType,
+          PrimitiveSerializerOptions options) {
+    this.iterator = iterator;
+    this.primitiveType = primitiveType;
+    this.metadata = metadata;
+    this.options = options;
+  }
+
+  protected abstract void writePrimitive(OutputStream out) throws 
SerializerException;
+
+  @Override
+  protected void writeCollection(OutputStream out) {
+    try {
+      writePrimitive(out);
+    } catch (SerializerException e) {
+      final ODataContentWriteErrorCallback errorCallback = 
options.getODataContentWriteErrorCallback();
+      if (errorCallback != null) {
+        final WriteErrorContext errorContext = new WriteErrorContext(e);
+        errorCallback.handleError(errorContext, Channels.newChannel(out));
+      }
+    }
+  }
+
+  public static SerializerStreamResult PrimitiveStreamContentForJson(
+          PrimitiveIterator iterator,
+          EdmPrimitiveType primitiveType,
+          ODataJsonSerializer jsonSerializer,
+          ServiceMetadata serviceMetadata,
+          PrimitiveSerializerOptions options) {
+
+    return SerializerStreamResultImpl.with()
+            .content(new PrimitiveStreamContentForJson(iterator,
+                                                       primitiveType,
+                                                       jsonSerializer,
+                                                       serviceMetadata,
+                                                       options)).build();
+  }
+
+  public static SerializerStreamResult PrimitiveStreamContentForXml(
+          PrimitiveIterator iterator,
+          EdmPrimitiveType primitiveType,
+          ODataXmlSerializer xmlSerializer,
+          ServiceMetadata serviceMetadata,
+          PrimitiveSerializerOptions options) {
+
+    return SerializerStreamResultImpl.with()
+            .content(new PrimitiveStreamContentForXml(iterator,
+                                                      primitiveType,
+                                                      xmlSerializer,
+                                                      serviceMetadata,
+                                                      options)).build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForJson.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForJson.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForJson.java
new file mode 100644
index 0000000..789efaf
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForJson.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
+
+class PrimitiveStreamContentForJson extends PrimitiveStreamContent {
+  private final ODataJsonSerializer jsonSerializer;
+
+  protected PrimitiveStreamContentForJson(
+          PrimitiveIterator iterator,
+          EdmPrimitiveType primitiveType,
+          ODataJsonSerializer jsonSerializer,
+          ServiceMetadata serviceMetadata,
+          PrimitiveSerializerOptions options) {
+
+    super(iterator, serviceMetadata, primitiveType, options);
+
+    this.jsonSerializer = jsonSerializer;
+  }
+
+  @Override
+  protected void writePrimitive(OutputStream outputStream) throws 
SerializerException {
+    try {
+      jsonSerializer.primitiveCollectionIntoStream(metadata, primitiveType, 
iterator, options, outputStream);
+      outputStream.flush();
+    } catch (final IOException e) {
+      throw new ODataRuntimeException("Failed complex serialization", e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForXml.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForXml.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForXml.java
new file mode 100644
index 0000000..675290b
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PrimitiveStreamContentForXml.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializer;
+
+class PrimitiveStreamContentForXml extends PrimitiveStreamContent {
+  private final ODataXmlSerializer xmlSerializer;
+
+  protected PrimitiveStreamContentForXml(
+          PrimitiveIterator iterator,
+          EdmPrimitiveType primitiveType,
+          ODataXmlSerializer xmlSerializer,
+          ServiceMetadata serviceMetadata,
+          PrimitiveSerializerOptions options) {
+
+    super(iterator, serviceMetadata, primitiveType, options);
+
+    this.xmlSerializer = xmlSerializer;
+  }
+
+  @Override
+  protected void writePrimitive(OutputStream outputStream) throws 
SerializerException {
+    try {
+      xmlSerializer.primitiveCollectionIntoStream(metadata, primitiveType, 
iterator, options, outputStream);
+      outputStream.flush();
+    } catch (final IOException e) {
+      throw new ODataRuntimeException("Failed complex serialization", e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/WriteErrorContext.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/WriteErrorContext.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/WriteErrorContext.java
new file mode 100644
index 0000000..5c74a48
--- /dev/null
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/WriteErrorContext.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import org.apache.olingo.server.api.ODataContentWriteErrorContext;
+import org.apache.olingo.server.api.ODataLibraryException;
+
+public class WriteErrorContext implements ODataContentWriteErrorContext {
+
+  private final ODataLibraryException exception;
+
+  public WriteErrorContext(ODataLibraryException exception) {
+    this.exception = exception;
+  }
+
+  @Override
+  public Exception getException() {
+    return exception;
+  }
+
+  @Override
+  public ODataLibraryException getODataLibraryException() {
+    return exception;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/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 0cf307f..ffdc6e6 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
@@ -29,6 +29,7 @@ import java.util.Set;
 
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.AbstractEntityCollection;
+import org.apache.olingo.commons.api.data.ComplexIterator;
 import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.Entity;
@@ -36,6 +37,7 @@ import org.apache.olingo.commons.api.data.EntityIterator;
 import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.Linked;
 import org.apache.olingo.commons.api.data.Operation;
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
@@ -77,7 +79,9 @@ 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.SelectOption;
+import org.apache.olingo.server.core.ComplexStreamContent;
 import org.apache.olingo.server.core.ODataWritableContent;
+import org.apache.olingo.server.core.PrimitiveStreamContent;
 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;
@@ -743,6 +747,31 @@ public class ODataJsonSerializer extends 
AbstractODataSerializer {
     json.writeEndArray();
   }
 
+  private void writePrimitiveCollectionStreamed(
+          final EdmPrimitiveType type,
+          final PrimitiveIterator property,
+          final Boolean isNullable,
+          final Integer maxLength,
+          final Integer precision,
+          final Integer scale,
+          final Boolean isUnicode,
+          final JsonGenerator json)
+          throws IOException, SerializerException {
+
+    json.writeStartArray();
+    for (Object value : property) {
+      try {
+        writePrimitiveValue(property.getName(), type, value, isNullable,
+                            maxLength, precision, scale, isUnicode, json);
+      } catch (EdmPrimitiveTypeException e) {
+        throw new SerializerException("Wrong value for property!", e,
+                                      
SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
+                                      property.getName());
+      }
+    }
+    json.writeEndArray();
+  }
+
   private void writeComplexCollection(final ServiceMetadata metadata, final 
EdmComplexType type,
       final Property property,
       final Set<List<String>> selectedPaths, final JsonGenerator json)
@@ -767,6 +796,27 @@ public class ODataJsonSerializer extends 
AbstractODataSerializer {
     json.writeEndArray();
   }
 
+  private void writeComplexCollectionStream(
+          final ServiceMetadata metadata,
+          final EdmComplexType type,
+          final ComplexIterator iterator,
+          final Set<List<String>> selectedPaths,
+          final JsonGenerator json)
+          throws IOException, SerializerException {
+
+    json.writeStartArray();
+    for (ComplexValue property : iterator) {
+      json.writeStartObject();
+      if (isODataMetadataFull) {
+        json.writeStringField(Constants.JSON_TYPE, "#" +
+                type.getFullQualifiedName().getFullQualifiedNameAsString());
+      }
+      writeComplexValue(metadata, type, property.getValue(), selectedPaths, 
json);
+      json.writeEndObject();
+    }
+    json.writeEndArray();
+  }
+
   private void writePrimitive(final EdmPrimitiveType type, final Property 
property,
       final Boolean isNullable, final Integer maxLength, final Integer 
precision, final Integer scale,
       final Boolean isUnicode, final JsonGenerator json)
@@ -1068,6 +1118,57 @@ public class ODataJsonSerializer extends 
AbstractODataSerializer {
   }
 
   @Override
+  public SerializerStreamResult primitiveCollectionStreamed(
+          ServiceMetadata metadata,
+          EdmPrimitiveType type,
+          PrimitiveIterator iterator,
+          PrimitiveSerializerOptions options)
+          throws SerializerException {
+
+    return PrimitiveStreamContent.PrimitiveStreamContentForJson(iterator, 
type, this, metadata, options);
+  }
+
+  public void primitiveCollectionIntoStream(
+          final ServiceMetadata metadata,
+          final EdmPrimitiveType type,
+          final PrimitiveIterator iterator,
+          final PrimitiveSerializerOptions options,
+          final OutputStream outputStream)
+          throws SerializerException {
+
+    SerializerException cachedException = null;
+    try {
+      final ContextURL contextURL = checkContextURL(options == null ? null : 
options.getContextURL());
+
+      JsonGenerator json = new JsonFactory().createGenerator(outputStream);
+      json.writeStartObject();
+      writeContextURL(contextURL, json);
+      writeMetadataETag(metadata, json);
+      if (isODataMetadataFull) {
+        json.writeStringField(Constants.JSON_TYPE, "#Collection(" + 
type.getFullQualifiedName().getName() + ")");
+      }
+      writeOperations(iterator.getOperations(), json);
+      json.writeFieldName(Constants.VALUE);
+      writePrimitiveCollectionStreamed(type, iterator,
+                                       options == null ? null : 
options.isNullable(),
+                                       options == null ? null : 
options.getMaxLength(),
+                                       options == null ? null : 
options.getPrecision(),
+                                       options == null ? null : 
options.getScale(),
+                                       options == null ? null : 
options.isUnicode(), json);
+      json.writeEndObject();
+
+      json.close();
+      outputStream.close();
+    } catch (final IOException e) {
+      cachedException =
+              new SerializerException(IO_EXCEPTION_TEXT, e, 
SerializerException.MessageKeys.IO_EXCEPTION);
+      throw cachedException;
+    } finally {
+      closeCircleStreamBufferOutput(outputStream, cachedException);
+    }
+  }
+
+  @Override
   public SerializerResult complexCollection(final ServiceMetadata metadata, 
final EdmComplexType type,
       final Property property, final ComplexSerializerOptions options) throws 
SerializerException {
     OutputStream outputStream = null;
@@ -1102,6 +1203,54 @@ public class ODataJsonSerializer extends 
AbstractODataSerializer {
   }
 
   @Override
+  public SerializerStreamResult complexCollectionStreamed(
+          ServiceMetadata metadata,
+          EdmComplexType type,
+          ComplexIterator iterator,
+          ComplexSerializerOptions options)
+          throws SerializerException {
+
+    return ComplexStreamContent.ComplexWritableForJson(iterator, type, this, 
metadata, options);
+  }
+
+  public void complexCollectionIntoStream(
+          final ServiceMetadata metadata,
+          final EdmComplexType type,
+          final ComplexIterator iterator,
+          final ComplexSerializerOptions options,
+          final OutputStream outputStream)
+          throws SerializerException {
+
+    SerializerException cachedException = null;
+    try {
+      final ContextURL contextURL = checkContextURL(options == null ? null : 
options.getContextURL());
+
+      JsonGenerator json = new JsonFactory().createGenerator(outputStream);
+      json.writeStartObject();
+      writeContextURL(contextURL, json);
+      writeMetadataETag(metadata, json);
+      if (isODataMetadataFull) {
+        json.writeStringField(Constants.JSON_TYPE,
+                              "#Collection(" + 
type.getFullQualifiedName().getFullQualifiedNameAsString() + ")");
+      }
+      writeOperations(iterator.getOperations(), json);
+      json.writeFieldName(Constants.VALUE);
+      writeComplexCollectionStream(metadata, type, iterator, null, json);
+      json.writeEndObject();
+
+      json.close();
+      outputStream.close();
+
+    } catch (final IOException e) {
+      cachedException =
+              new SerializerException(IO_EXCEPTION_TEXT, e, 
SerializerException.MessageKeys.IO_EXCEPTION);
+      throw cachedException;
+    } finally {
+      closeCircleStreamBufferOutput(outputStream, cachedException);
+    }
+  }
+
+  @Override
   public SerializerResult reference(final ServiceMetadata metadata, final 
EdmEntitySet edmEntitySet,
       final Entity entity, final ReferenceSerializerOptions options) throws 
SerializerException {
     OutputStream outputStream = null;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
index c7ea2e2..b52545f 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
@@ -31,16 +31,18 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 
 import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.AbstractEntityCollection;
+import org.apache.olingo.commons.api.data.ComplexIterator;
 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.AbstractEntityCollection;
 import org.apache.olingo.commons.api.data.EntityIterator;
 import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.Linked;
 import org.apache.olingo.commons.api.data.Operation;
 import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
@@ -72,7 +74,9 @@ 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.SelectOption;
+import org.apache.olingo.server.core.ComplexStreamContent;
 import org.apache.olingo.server.core.ODataWritableContent;
+import org.apache.olingo.server.core.PrimitiveStreamContent;
 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;
@@ -873,6 +877,7 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
         writeComplexValue(metadata, resolvedType, 
property.asComplex().getValue(),
            selectedPaths, xml10InvalidCharReplacement, writer);
   }
+
   private void writePrimitiveCollection(final EdmPrimitiveType type, final 
Property property,
       final Boolean isNullable, final Integer maxLength, final Integer 
precision, final Integer scale,
       final Boolean isUnicode, final String xml10InvalidCharReplacement,
@@ -896,6 +901,34 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
     }
   }
 
+  private void writePrimitiveCollectionStreamed(final EdmPrimitiveType type, 
final PrimitiveIterator iterator,
+          final Boolean isNullable, final Integer maxLength, final Integer 
precision, final Integer scale,
+          final Boolean isUnicode, final String xml10InvalidCharReplacement,
+          final XMLStreamWriter writer) throws XMLStreamException, 
EdmPrimitiveTypeException, SerializerException {
+    for (Object value : iterator) {
+      writer.writeStartElement(METADATA, Constants.ELEM_ELEMENT, NS_METADATA);
+      writePrimitiveValue(type, value, isNullable, maxLength, precision,
+                          scale, isUnicode, xml10InvalidCharReplacement, 
writer);
+
+      writer.writeEndElement();
+    }
+  }
+
+  private void writeComplexCollectionStream(final ServiceMetadata metadata,
+          final EdmComplexType type, final ComplexIterator iterator, final 
Set<List<String>> selectedPaths,
+          final String xml10InvalidCharReplacement, final XMLStreamWriter 
writer)
+          throws XMLStreamException, SerializerException {
+    for (ComplexValue value : iterator) {
+      writer.writeStartElement(METADATA, Constants.ELEM_ELEMENT, NS_METADATA);
+      if (derivedComplexType(type, iterator.getType()) != null) {
+        writer.writeAttribute(METADATA, NS_METADATA, Constants.ATTR_TYPE, 
iterator.getType());
+      }
+      writeComplexValue(metadata, type, value.getValue(), selectedPaths,
+                        xml10InvalidCharReplacement, writer);
+      writer.writeEndElement();
+    }
+  }
+
   private void writeComplexCollection(final ServiceMetadata metadata,
       final EdmComplexType type, final Property property, final 
Set<List<String>> selectedPaths,
       final String xml10InvalidCharReplacement, final XMLStreamWriter writer)
@@ -1146,6 +1179,61 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
   }
 
   @Override
+  public SerializerStreamResult primitiveCollectionStreamed(ServiceMetadata 
metadata, EdmPrimitiveType type,
+          PrimitiveIterator iterator, PrimitiveSerializerOptions options) 
throws SerializerException {
+    return PrimitiveStreamContent.PrimitiveStreamContentForXml(iterator, type, 
this, metadata, options);
+  }
+
+  public void primitiveCollectionIntoStream(final ServiceMetadata metadata, 
final EdmPrimitiveType type,
+          final PrimitiveIterator iterator, final PrimitiveSerializerOptions 
options, final OutputStream outputStream)
+          throws SerializerException {
+    final ContextURL contextURL = checkContextURL(options == null ? null : 
options.getContextURL());
+
+    SerializerException cachedException = null;
+    try {
+      XMLStreamWriter writer = 
XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, 
DEFAULT_CHARSET);
+
+      writer.writeStartDocument(DEFAULT_CHARSET, "1.0");
+      writer.writeStartElement(METADATA, Constants.VALUE, NS_METADATA);
+      writer.writeNamespace(METADATA, NS_METADATA);
+      if (contextURL != null) {
+        writer.writeAttribute(METADATA, NS_METADATA, Constants.CONTEXT,
+                              
ContextURLBuilder.create(contextURL).toASCIIString());
+      }
+      writeMetadataETag(metadata, writer);
+      writer.writeAttribute(METADATA, NS_METADATA, Constants.ATTR_TYPE, 
"#Collection(" + type.getName() + ")");
+      writePrimitiveCollectionStreamed(type, iterator,
+                                       options == null ? null : 
options.isNullable(),
+                                       options == null ? null : 
options.getMaxLength(),
+                                       options == null ? null : 
options.getPrecision(),
+                                       options == null ? null : 
options.getScale(),
+                                       options == null ? null : 
options.isUnicode(),
+                                       options == null ? null : 
options.xml10InvalidCharReplacement(),
+                                       writer);
+      writer.writeEndElement();
+      writer.writeEndDocument();
+      writer.flush();
+      writer.close();
+      outputStream.close();
+    } catch (final XMLStreamException e) {
+      cachedException = new SerializerException(IO_EXCEPTION_TEXT, e,
+                                                
SerializerException.MessageKeys.IO_EXCEPTION);
+      throw cachedException;
+    } catch (final EdmPrimitiveTypeException e) {
+      cachedException = new SerializerException("Wrong value for property!", e,
+                                                
SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
+                                                iterator.getName());
+      throw cachedException;
+    } catch (IOException e) {
+      cachedException =
+              new SerializerException(IO_EXCEPTION_TEXT, e, 
SerializerException.MessageKeys.IO_EXCEPTION);
+      throw cachedException;
+    } finally {
+      closeCircleStreamBufferOutput(outputStream, cachedException);
+    }
+  }
+
+  @Override
   public SerializerResult complexCollection(final ServiceMetadata metadata, 
final EdmComplexType type,
       final Property property, final ComplexSerializerOptions options) throws 
SerializerException {
     final ContextURL contextURL = checkContextURL(options == null ? null : 
options.getContextURL());
@@ -1186,6 +1274,46 @@ public class ODataXmlSerializer extends 
AbstractODataSerializer {
   }
 
   @Override
+  public SerializerStreamResult complexCollectionStreamed(ServiceMetadata 
metadata, EdmComplexType type,
+          ComplexIterator iterator, ComplexSerializerOptions options) throws 
SerializerException {
+    return ComplexStreamContent.ComplexWritableForXml(iterator, type, this, 
metadata, options);
+  }
+
+  public void complexCollectionIntoStream(final ServiceMetadata metadata, 
final EdmComplexType type,
+          final ComplexIterator iterator, final ComplexSerializerOptions 
options, final OutputStream outputStream)
+          throws SerializerException {
+    final ContextURL contextURL = checkContextURL(options == null ? null : 
options.getContextURL());
+    SerializerException cachedException = null;
+    try {
+      XMLStreamWriter writer = 
XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, 
DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, "1.0");
+      writer.writeStartElement(METADATA, Constants.VALUE, NS_METADATA);
+      writer.writeNamespace(METADATA, NS_METADATA);
+      writer.writeNamespace(DATA, NS_DATA);
+      writer.writeAttribute(METADATA, NS_METADATA, Constants.ATTR_TYPE, 
collectionType(type));
+      writer.writeAttribute(METADATA, NS_METADATA, Constants.CONTEXT,
+                            
ContextURLBuilder.create(contextURL).toASCIIString());
+      writeMetadataETag(metadata, writer);
+      writeComplexCollectionStream(metadata, type, iterator, null, 
options.xml10InvalidCharReplacement(), writer);
+      writer.writeEndElement();
+      writer.writeEndDocument();
+      writer.flush();
+      writer.close();
+      outputStream.close();
+    } catch (final XMLStreamException e) {
+      cachedException =
+              new SerializerException(IO_EXCEPTION_TEXT, e, 
SerializerException.MessageKeys.IO_EXCEPTION);
+      throw cachedException;
+    } catch (IOException e) {
+      cachedException =
+              new SerializerException(IO_EXCEPTION_TEXT, e, 
SerializerException.MessageKeys.IO_EXCEPTION);
+      throw cachedException;
+    } finally {
+      closeCircleStreamBufferOutput(outputStream, cachedException);
+    }
+  }
+
+  @Override
   public SerializerResult reference(final ServiceMetadata metadata, final 
EdmEntitySet edmEntitySet,
       final Entity entity, final ReferenceSerializerOptions options) throws 
SerializerException {
     return entityReference(entity, options);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
index cf29d5f..98371f6 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
@@ -33,6 +33,7 @@ import java.util.List;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.olingo.commons.api.data.ComplexIterator;
 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;
@@ -40,6 +41,7 @@ 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.PrimitiveIterator;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
@@ -49,15 +51,15 @@ 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.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.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.edmx.EdmxReference;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.server.api.OData;
@@ -74,6 +76,7 @@ import 
org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOpti
 import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.serializer.SerializerResult;
+import org.apache.olingo.server.api.serializer.SerializerStreamResult;
 import org.apache.olingo.server.api.uri.UriHelper;
 import org.apache.olingo.server.api.uri.queryoption.CountOption;
 import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
@@ -1540,6 +1543,92 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void primitiveCollectionStreamed() 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 Iterator<?> primitiveIterator = property.asCollection().iterator();
+
+    final PrimitiveIterator valueProvider = new 
PrimitiveIterator(property.getName()) {
+      @Override
+      public boolean hasNext() {
+        return primitiveIterator.hasNext();
+      }
+
+      @Override
+      public Object next() {
+        return primitiveIterator.next();
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult = 
serializerNoMetadata.primitiveCollectionStreamed(
+            metadata,
+            (EdmPrimitiveType) edmProperty.getType(),
+            valueProvider,
+            null);
+
+    final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(bout);
+
+    final String resultString = new String(bout.toByteArray(), "UTF-8");
+
+    Assert.assertEquals("{\"value\":[\"[email protected]\","
+                                + 
"\"[email protected]\",\"[email protected]\"]}",
+                        resultString);
+  }
+
+  @Test
+  public void primitiveCollectionStreamedWithError() 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 Iterator<?> primitiveIterator = property.asCollection().iterator();
+
+    // Note - We combine returning null value with serialization option of 
nullable to throw the error
+    final PrimitiveIterator valueProvider = new 
PrimitiveIterator(property.getName()) {
+      @Override
+      public boolean hasNext() {
+        return primitiveIterator.hasNext();
+      }
+
+      @Override
+      public Object next() {
+        return null;
+      }
+    };
+
+    final ODataContentWriteErrorCallback errorCallback = new 
ODataContentWriteErrorCallback() {
+      @Override
+      public void handleError(ODataContentWriteErrorContext context, 
WritableByteChannel channel) {
+        try {
+          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.");
+        }
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult = 
serializerNoMetadata.primitiveCollectionStreamed(
+            metadata,
+            (EdmPrimitiveType) edmProperty.getType(),
+            valueProvider,
+            PrimitiveSerializerOptions.with()
+                    .writeContentErrorCallback(errorCallback)
+                    .nullable(false)
+                    .build());
+
+    final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(bout);
+
+    final String resultString = new String(bout.toByteArray(), "UTF-8");
+    Assert.assertEquals("ERROR : WRONG_PROPERTY_VALUE", resultString);
+  }
+
+  @Test
   public void complexProperty() throws Exception {
     final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESMixPrimCollComp");
     final EdmProperty edmProperty = (EdmProperty) 
edmEntitySet.getEntityType().getProperty("PropertyComp");
@@ -1610,6 +1699,90 @@ public class ODataJsonSerializerTest {
   }
 
   @Test
+  public void complexCollectionStreamed() 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 Iterator<?> complexIterator = property.asCollection().iterator();
+
+    final ComplexIterator valueProvider = new ComplexIterator() {
+      @Override
+      public boolean hasNext() {
+        return complexIterator.hasNext();
+      }
+
+      @Override
+      public ComplexValue next() {
+        return (ComplexValue) complexIterator.next();
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult = 
serializerNoMetadata.complexCollectionStreamed(
+            metadata,
+            (EdmComplexType) edmProperty.getType(),
+            valueProvider,
+            null);
+
+    final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(bout);
+
+    final String resultString = new String(bout.toByteArray(), "UTF-8");
+
+    
Assert.assertEquals("{\"value\":[{\"PropertyInt16\":123,\"PropertyString\":\"TEST
 1\"},"
+        + "{\"PropertyInt16\":456," + "\"PropertyString\":\"TEST 2\"},"
+        + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}",
+        resultString);
+  }
+
+  @Test
+  public void complexCollectionStreamedWithError() 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 Iterator<?> complexIterator = property.asCollection().iterator();
+
+    final ComplexIterator valueProvider = new ComplexIterator() {
+      @Override
+      public boolean hasNext() {
+        return complexIterator.hasNext();
+      }
+
+      @Override
+      public ComplexValue next() {
+        return new ComplexValue();
+      }
+    };
+
+    final ODataContentWriteErrorCallback errorCallback = new 
ODataContentWriteErrorCallback() {
+      @Override
+      public void handleError(ODataContentWriteErrorContext context, 
WritableByteChannel channel) {
+        try {
+          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.");
+        }
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult =
+            serializerNoMetadata.complexCollectionStreamed(
+                    metadata,
+                    (EdmComplexType) edmProperty.getType(),
+                    valueProvider,
+                    
ComplexSerializerOptions.with().writeContentErrorCallback(errorCallback).build());
+
+    final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(bout);
+
+    final String resultString = new String(bout.toByteArray(), "UTF-8");
+    Assert.assertEquals("ERROR : MISSING_PROPERTY", resultString);
+  }
+
+  @Test
   public void complexCollectionPropertyNoMetadata() throws Exception {
     final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESMixPrimCollComp");
     final EdmProperty edmProperty = (EdmProperty) 
edmEntitySet.getEntityType().getProperty("CollPropertyComp");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/685b19e5/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
index 7eae959..c8ee640 100644
--- 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
+++ 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializerTest.java
@@ -21,20 +21,26 @@ package org.apache.olingo.server.core.serializer.xml;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
+import java.util.Iterator;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.ComplexIterator;
 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.Property;
+import org.apache.olingo.commons.api.data.PrimitiveIterator;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntityContainer;
@@ -45,6 +51,8 @@ import org.apache.olingo.commons.api.edm.EdmProperty;
 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.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;
@@ -55,6 +63,7 @@ import 
org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOpti
 import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
 import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.serializer.SerializerResult;
+import org.apache.olingo.server.api.serializer.SerializerStreamResult;
 import org.apache.olingo.server.api.uri.UriHelper;
 import org.apache.olingo.server.api.uri.queryoption.CountOption;
 import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
@@ -2189,6 +2198,106 @@ public class ODataXmlSerializerTest {
   }
 
   @Test
+  public void primitiveCollectionStreamed() 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 Iterator<?> primitiveIterator = property.asCollection().iterator();
+
+    final PrimitiveIterator valueProvider = new 
PrimitiveIterator(property.getName()) {
+      @Override
+      public boolean hasNext() {
+        return primitiveIterator.hasNext();
+      }
+
+      @Override
+      public Object next() {
+        return primitiveIterator.next();
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult = 
serializer.primitiveCollectionStreamed(
+            metadata,
+            (EdmPrimitiveType) edmProperty.getType(),
+            valueProvider,
+            PrimitiveSerializerOptions.with()
+                    .contextURL(ContextURL.with()
+                         
.entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName())
+                         .build())
+                    .build());
+
+    final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(bout);
+
+    final String resultString = new String(bout.toByteArray(), "UTF-8");
+
+    String expected = "<?xml version='1.0' encoding='UTF-8'?>"
+            + "<m:value 
xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"; "
+            + "m:context=\"$metadata#ESCollAllPrim(1)/CollPropertyString\" "
+            + "m:metadata-etag=\"metadataETag\"  
m:type=\"#Collection(String)\">"
+            + "<m:element>[email protected]</m:element>"
+            + "<m:element>[email protected]</m:element>"
+            + "<m:element>[email protected]</m:element>"
+            + "</m:value>";
+    checkXMLEqual(expected, resultString);
+  }
+
+  @Test
+  public void primitiveCollectionStreamedWithError() 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 Iterator<?> primitiveIterator = property.asCollection().iterator();
+
+    // Note - We combine returning null value with serialization option of 
nullable to throw the error
+    final PrimitiveIterator valueProvider = new 
PrimitiveIterator(property.getName()) {
+      @Override
+      public boolean hasNext() {
+        return primitiveIterator.hasNext();
+      }
+
+      @Override
+      public Object next() {
+        return null;
+      }
+    };
+
+    final ODataContentWriteErrorCallback errorCallback = new 
ODataContentWriteErrorCallback() {
+      @Override
+      public void handleError(ODataContentWriteErrorContext context, 
WritableByteChannel channel) {
+        try {
+          final String msgKey = 
context.getODataLibraryException().getMessageKey().getKey();
+          final String toChannel = "ERROR : " + msgKey;
+          channel.write(ByteBuffer.wrap(toChannel.getBytes()));
+        } catch (IOException e) {
+          throw new RuntimeException("Error in error.");
+        }
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult =
+            serializer.primitiveCollectionStreamed(
+                    metadata,
+                    (EdmPrimitiveType) edmProperty.getType(),
+                    valueProvider,
+                    PrimitiveSerializerOptions.with()
+                            .contextURL(ContextURL.with()
+                                  
.entitySet(edmEntitySet).keyPath("1").navOrPropertyPath(edmProperty.getName())
+                                  .build())
+                            .writeContentErrorCallback(errorCallback)
+                            .nullable(false)
+                            .build());
+
+    final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(bout);
+
+    final String resultString = new String(bout.toByteArray(), "UTF-8");
+    Assert.assertEquals("ERROR : WRONG_PROPERTY_VALUE", resultString);
+  }
+
+  @Test
   public void complexProperty() throws Exception {
     final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESMixPrimCollComp");
     final EdmProperty edmProperty = (EdmProperty) 
edmEntitySet.getEntityType().getProperty("PropertyComp");
@@ -2249,6 +2358,116 @@ public class ODataXmlSerializerTest {
   }
 
   @Test
+  public void complexCollectionStreamed() 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 Iterator<?> complexIterator = property.asCollection().iterator();
+
+    final ComplexIterator valueProvider = new ComplexIterator() {
+      @Override
+      public boolean hasNext() {
+        return complexIterator.hasNext();
+      }
+
+      @Override
+      public ComplexValue next() {
+        return (ComplexValue) complexIterator.next();
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult = 
serializer.complexCollectionStreamed(
+            metadata,
+            (EdmComplexType) edmProperty.getType(),
+            valueProvider,
+            ComplexSerializerOptions.with()
+                .contextURL(ContextURL.with()
+                    
.entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName())
+                    .build())
+                .build()
+    );
+
+    final ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(byteArrayOutputStream);
+
+    final String resultString = new 
String(byteArrayOutputStream.toByteArray(), "UTF-8");
+
+    String expected = "<?xml version='1.0' encoding='UTF-8'?>\n"
+        + "<m:value 
xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"\n"; +
+        "  xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\"; "
+        + "m:type=\"#Collection(olingo.odata.test1.CTTwoPrim)\"\n" +
+        "  
m:context=\"$metadata#ESMixPrimCollComp(32767)/CollPropertyComp\"\n" +
+        "  m:metadata-etag=\"metadataETag\">\n" +
+        "  <m:element>\n" +
+        "    <d:PropertyInt16 m:type=\"Int16\">123</d:PropertyInt16>\n" +
+        "    <d:PropertyString>TEST 1</d:PropertyString>\n" +
+        "  </m:element>\n" +
+        "  <m:element>\n" +
+        "    <d:PropertyInt16 m:type=\"Int16\">456</d:PropertyInt16>\n" +
+        "    <d:PropertyString>TEST 2</d:PropertyString>\n" +
+        "  </m:element>\n" +
+        "  <m:element>\n" +
+        "    <d:PropertyInt16 m:type=\"Int16\">789</d:PropertyInt16>\n" +
+        "    <d:PropertyString>TEST 3</d:PropertyString>\n" +
+        "  </m:element>\n" +
+        "</m:value>";
+    checkXMLEqual(expected, resultString);
+  }
+
+  @Test
+  public void complexCollectionStreamedWithError() 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 Iterator<?> complexIterator = property.asCollection().iterator();
+
+    final ComplexIterator valueProvider = new ComplexIterator() {
+      @Override
+      public boolean hasNext() {
+        return complexIterator.hasNext();
+      }
+
+      @Override
+      public ComplexValue next() {
+        return new ComplexValue();
+      }
+    };
+
+    final ODataContentWriteErrorCallback errorCallback = new 
ODataContentWriteErrorCallback() {
+      @Override
+      public void handleError(ODataContentWriteErrorContext context, 
WritableByteChannel channel) {
+        try {
+          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.");
+        }
+      }
+    };
+
+    final SerializerStreamResult serializerStreamResult =
+        serializer.complexCollectionStreamed(
+            metadata,
+            (EdmComplexType) edmProperty.getType(),
+            valueProvider,
+            ComplexSerializerOptions.with()
+                .contextURL(ContextURL.with()
+                     
.entitySet(edmEntitySet).keyPath("32767").navOrPropertyPath(edmProperty.getName())
+                     .build())
+                .writeContentErrorCallback(errorCallback)
+                .build());
+
+    final ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+    serializerStreamResult.getODataContent().write(byteArrayOutputStream);
+
+    final String resultString = new 
String(byteArrayOutputStream.toByteArray(), "UTF-8");
+    Assert.assertEquals("ERROR : MISSING_PROPERTY", resultString);
+  }
+
+  @Test
   public void entityReference() throws Exception {
     final EdmEntitySet edmEntitySet = 
entityContainer.getEntitySet("ESAllPrim");
     final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);

Reply via email to