/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.commons.streaming;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.scytl.products.ov.commons.beans.exceptions.LambdaException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.stream.Stream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;

/**
 * Helper for converting a stream of objects to a JSON array. The array is then placed in an output
 * stream which should be read back one object at a time, in order to avoid construction of the
 * array in memory.
 */
public class JsonStreamingOutput<T> implements StreamingOutput {
    private final Stream<T> objectStream;

    public JsonStreamingOutput(Stream<T> objectStream) {
        this.objectStream = objectStream;
    }

    @Override
    public void write(final OutputStream outputStream) throws IOException, WebApplicationException {
        try (final JsonGenerator jsonGenerator = new ObjectMapper().getFactory()
                .createGenerator(outputStream)) {
            // Start the array.
            jsonGenerator.writeStartArray();

            try {
                // Populate the output stream one object at a time.
                objectStream.forEach(object -> {
                    try {
                        jsonGenerator.writeObject(object);
                    } catch (IOException e) {
                        throw new LambdaException(e);
                    }
                });
            } catch (LambdaException e) {			//NOSONAR 'Either log or rethrow this exception.'
                throw (IOException) e.getCause();		
            }

            // End the JSON array.
            jsonGenerator.writeEndArray();
        }
    }
}
