ATEST-302
This commit is contained in:
@@ -10,13 +10,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import ch.psi.daq.query.model.ResponseFormat;
|
||||
import ch.psi.daq.query.model.impl.DAQQuery;
|
||||
import ch.psi.daq.query.model.ResponseOptions;
|
||||
|
||||
|
||||
/**
|
||||
* @author zellweger_c
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractResponseStreamWriter implements ResponseStreamWriter {
|
||||
|
||||
public static final String CONTENT_TYPE_CSV = "text/csv";
|
||||
@@ -32,24 +27,24 @@ public abstract class AbstractResponseStreamWriter implements ResponseStreamWrit
|
||||
* see http://tools.ietf.org/html/rfc2616#section-14.11 and
|
||||
* see http://tools.ietf.org/html/rfc2616#section-3.5
|
||||
*
|
||||
* @param query The query
|
||||
* @param options The options for the response
|
||||
* @param response The HttpServletResponse
|
||||
* @param contentType The content type
|
||||
* @return OutputStream The OutputStream
|
||||
* @throws Exception Something goes wrong
|
||||
*/
|
||||
protected OutputStream handleCompressionAndResponseHeaders(DAQQuery query, HttpServletResponse response,
|
||||
protected OutputStream handleCompressionAndResponseHeaders(ResponseOptions options, HttpServletResponse response,
|
||||
String contentType) throws Exception {
|
||||
OutputStream out = response.getOutputStream();
|
||||
|
||||
response.addHeader("Content-Type", contentType);
|
||||
if (query.isCompressed()) {
|
||||
String filename = "data." + query.getCompression().getFileSuffix();
|
||||
if (options.isCompressed()) {
|
||||
String filename = "data." + options.getCompression().getFileSuffix();
|
||||
response.addHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||
response.addHeader("Content-Encoding", query.getCompression().toString());
|
||||
out = query.getCompression().wrapStream(out);
|
||||
response.addHeader("Content-Encoding", options.getCompression().toString());
|
||||
out = options.getCompression().wrapStream(out);
|
||||
} else {
|
||||
String filename = "data." + (query.getResponseFormat() == ResponseFormat.CSV ? "csv" : "json");
|
||||
String filename = "data." + (options.getResponseFormat() == ResponseFormat.CSV ? "csv" : "json");
|
||||
response.addHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package ch.psi.daq.queryrest.response;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ch.psi.daq.query.model.impl.DAQQuery;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
|
||||
import ch.psi.daq.query.model.ResponseOptions;
|
||||
import ch.psi.daq.query.model.impl.BackendQuery;
|
||||
import ch.psi.daq.query.model.impl.DAQQueryElement;
|
||||
import ch.psi.daq.query.request.ChannelName;
|
||||
|
||||
public interface ResponseStreamWriter {
|
||||
|
||||
@@ -15,10 +20,11 @@ public interface ResponseStreamWriter {
|
||||
* Responding with the the contents of the stream by writing into the output stream of the
|
||||
* {@link ServletResponse}.
|
||||
*
|
||||
* @param stream Mapping from channel name to data
|
||||
* @param query concrete instance of {@link DAQQuery}
|
||||
* @param stream The results results
|
||||
* @param options The options for the response
|
||||
* @param response {@link ServletResponse} instance given by the current HTTP request
|
||||
* @throws IOException thrown if writing to the output stream fails
|
||||
* @throws Exception thrown if writing to the output stream fails
|
||||
*/
|
||||
public void respond(Stream<Entry<String, ?>> stream, DAQQuery query, HttpServletResponse response) throws Exception;
|
||||
public void respond(List<Entry<DAQQueryElement, Stream<Triple<BackendQuery, ChannelName, ?>>>> results, ResponseOptions options,
|
||||
HttpServletResponse response) throws Exception;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.annotation.Resource;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.supercsv.cellprocessor.constraint.NotNull;
|
||||
@@ -24,16 +25,19 @@ import org.supercsv.io.dozer.CsvDozerBeanWriter;
|
||||
import org.supercsv.io.dozer.ICsvDozerBeanWriter;
|
||||
import org.supercsv.prefs.CsvPreference;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
|
||||
import ch.psi.daq.domain.DataEvent;
|
||||
import ch.psi.daq.query.analyzer.QueryAnalyzer;
|
||||
import ch.psi.daq.query.model.Aggregation;
|
||||
import ch.psi.daq.query.model.Query;
|
||||
import ch.psi.daq.query.model.QueryField;
|
||||
import ch.psi.daq.query.model.impl.DAQQuery;
|
||||
import ch.psi.daq.query.model.ResponseOptions;
|
||||
import ch.psi.daq.query.model.impl.BackendQuery;
|
||||
import ch.psi.daq.query.model.impl.DAQQueryElement;
|
||||
import ch.psi.daq.query.request.ChannelName;
|
||||
import ch.psi.daq.queryrest.response.AbstractResponseStreamWriter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
|
||||
/**
|
||||
* Takes a Java 8 stream and writes it to the output stream provided by the {@link ServletResponse}
|
||||
* of the current request.
|
||||
@@ -44,53 +48,103 @@ public class CSVResponseStreamWriter extends AbstractResponseStreamWriter {
|
||||
private static final char DELIMITER_ARRAY = ',';
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CSVResponseStreamWriter.class);
|
||||
|
||||
|
||||
@Resource
|
||||
private Function<Query, QueryAnalyzer> queryAnalizerFactory;
|
||||
|
||||
@Override
|
||||
public void respond(Stream<Entry<String, ?>> stream, DAQQuery query, HttpServletResponse response) throws Exception {
|
||||
public void respond(List<Entry<DAQQueryElement, Stream<Triple<BackendQuery, ChannelName, ?>>>> results,
|
||||
ResponseOptions options,
|
||||
HttpServletResponse response) throws Exception {
|
||||
response.setCharacterEncoding(JsonEncoding.UTF8.getJavaName());
|
||||
response.setContentType(CONTENT_TYPE_CSV);
|
||||
|
||||
respondInternal(stream, query, response);
|
||||
respondInternal(results, options, response);
|
||||
}
|
||||
|
||||
private void respondInternal(Stream<Entry<String, ?>> stream, DAQQuery query, HttpServletResponse response)
|
||||
throws Exception {
|
||||
private void respondInternal(List<Entry<DAQQueryElement, Stream<Triple<BackendQuery, ChannelName, ?>>>> results,
|
||||
ResponseOptions options, HttpServletResponse response) throws Exception {
|
||||
AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
OutputStream out = handleCompressionAndResponseHeaders(options, response, CONTENT_TYPE_CSV);
|
||||
List<ICsvDozerBeanWriter> beanWriters = new ArrayList<>();
|
||||
|
||||
Set<QueryField> queryFields = query.getFields();
|
||||
List<Aggregation> aggregations = query.getAggregations();
|
||||
int aggregationsSize = (aggregations != null ? aggregations.size() : 0);
|
||||
results.forEach(entry -> {
|
||||
DAQQueryElement query = entry.getKey();
|
||||
|
||||
Set<String> fieldMapping = new LinkedHashSet<>(queryFields.size() + aggregationsSize);
|
||||
List<String> header = new ArrayList<>(queryFields.size() + aggregationsSize);
|
||||
Set<QueryField> queryFields = query.getFields();
|
||||
List<Aggregation> aggregations = query.getAggregations();
|
||||
int aggregationsSize = (aggregations != null ? aggregations.size() : 0);
|
||||
|
||||
CellProcessor[] processors = setupCellProcessors(query, fieldMapping, header);
|
||||
|
||||
OutputStream out = handleCompressionAndResponseHeaders(query, response, CONTENT_TYPE_CSV);
|
||||
ICsvDozerBeanWriter beanWriter = setupBeanWriter(fieldMapping, out);
|
||||
Set<String> fieldMapping = new LinkedHashSet<>(queryFields.size() + aggregationsSize);
|
||||
List<String> header = new ArrayList<>(queryFields.size() + aggregationsSize);
|
||||
|
||||
writeToOutput(stream, header, processors, beanWriter);
|
||||
|
||||
AtomicReference<CellProcessor[]> processorsRef = new AtomicReference<>();
|
||||
|
||||
entry.getValue()
|
||||
.sequential()
|
||||
.forEach(triple -> {
|
||||
try {
|
||||
CellProcessor[] processors = processorsRef.get();
|
||||
ICsvDozerBeanWriter beanWriter;
|
||||
|
||||
if (processors == null) {
|
||||
processors = setupCellProcessors(query, triple.getLeft(), fieldMapping, header);
|
||||
processorsRef.set(processors);
|
||||
|
||||
beanWriter = setupBeanWriter(fieldMapping, out);
|
||||
beanWriters.add(beanWriter);
|
||||
} else {
|
||||
beanWriter = beanWriters.get(beanWriters.size() - 1);
|
||||
}
|
||||
|
||||
writeToOutput(triple, processors, beanWriter, header);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not write CSV of '{}'", triple.getMiddle(), e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
});
|
||||
|
||||
if (!beanWriters.isEmpty()) {
|
||||
try {
|
||||
beanWriters.get(beanWriters.size() - 1).flush();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not flush ICsvDozerBeanWriter.", e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (ICsvDozerBeanWriter beanWriter : beanWriters) {
|
||||
try {
|
||||
beanWriter.close();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not close ICsvDozerBeanWriter.", e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (exception.get() != null) {
|
||||
throw exception.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the bean writer instance.
|
||||
* @throws Exception
|
||||
*
|
||||
*/
|
||||
private ICsvDozerBeanWriter setupBeanWriter(Set<String> fieldMapping, OutputStream out) throws Exception {
|
||||
CsvPreference preference = new CsvPreference.Builder(
|
||||
(char) CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE.getQuoteChar(),
|
||||
DELIMITER_CVS,
|
||||
CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE.getEndOfLineSymbols()).build();
|
||||
|
||||
ICsvDozerBeanWriter beanWriter = new CsvDozerBeanWriter(new OutputStreamWriter(out), preference);
|
||||
// configure the mapping from the fields to the CSV columns
|
||||
beanWriter.configureBeanMapping(DataEvent.class, fieldMapping.toArray(new String[fieldMapping.size()]));
|
||||
return beanWriter;
|
||||
}
|
||||
* Sets up the bean writer instance.
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
*/
|
||||
private ICsvDozerBeanWriter setupBeanWriter(Set<String> fieldMapping, OutputStream out) throws Exception {
|
||||
CsvPreference preference = new CsvPreference.Builder(
|
||||
(char) CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE.getQuoteChar(),
|
||||
DELIMITER_CVS,
|
||||
CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE.getEndOfLineSymbols()).build();
|
||||
|
||||
ICsvDozerBeanWriter beanWriter = new CsvDozerBeanWriter(new OutputStreamWriter(out), preference);
|
||||
// configure the mapping from the fields to the CSV columns
|
||||
beanWriter.configureBeanMapping(DataEvent.class, fieldMapping.toArray(new String[fieldMapping.size()]));
|
||||
return beanWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the array of {@link CellProcessor}s needed for later configuration of the bean writer.
|
||||
@@ -101,34 +155,36 @@ public class CSVResponseStreamWriter extends AbstractResponseStreamWriter {
|
||||
* with other processors to fully automate all of the required conversions and constraint
|
||||
* validation for a single CSV column.
|
||||
*
|
||||
* @param query The current {@link DAQQuery}
|
||||
* @param daqQuery The current {@link DAQQueryElement}
|
||||
* @param backendQuery One BackendQuery of the current {@link DAQQueryElement}
|
||||
* @return Array of {@link CellProcessor} entries
|
||||
*/
|
||||
private CellProcessor[] setupCellProcessors(DAQQuery query, Set<String> fieldMapping, List<String> header) {
|
||||
Set<QueryField> queryFields = query.getFields();
|
||||
List<Aggregation> aggregations = query.getAggregations();
|
||||
|
||||
private CellProcessor[] setupCellProcessors(DAQQueryElement daqQuery, BackendQuery backendQuery,
|
||||
Set<String> fieldMapping, List<String> header) {
|
||||
Set<QueryField> queryFields = daqQuery.getFields();
|
||||
List<Aggregation> aggregations = daqQuery.getAggregations();
|
||||
|
||||
List<CellProcessor> processorSet =
|
||||
new ArrayList<>(queryFields.size() + (aggregations != null ? aggregations.size() : 0));
|
||||
|
||||
|
||||
boolean isNewField;
|
||||
QueryAnalyzer queryAnalyzer = queryAnalizerFactory.apply(query);
|
||||
|
||||
QueryAnalyzer queryAnalyzer = queryAnalizerFactory.apply(backendQuery);
|
||||
|
||||
for (QueryField field : queryFields) {
|
||||
if(!(QueryField.value.equals(field) && queryAnalyzer.isAggregationEnabled())){
|
||||
if (!(QueryField.value.equals(field) && queryAnalyzer.isAggregationEnabled())) {
|
||||
isNewField = fieldMapping.add(field.name());
|
||||
|
||||
|
||||
if (isNewField) {
|
||||
header.add(field.name());
|
||||
processorSet.add(new ArrayProcessor(new NotNull(), DELIMITER_ARRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (aggregations != null && queryAnalyzer.isAggregationEnabled()) {
|
||||
for (Aggregation aggregation : query.getAggregations()) {
|
||||
for (Aggregation aggregation : daqQuery.getAggregations()) {
|
||||
isNewField = fieldMapping.add("value." + aggregation.name());
|
||||
|
||||
|
||||
if (isNewField) {
|
||||
header.add(aggregation.name());
|
||||
processorSet.add(new ArrayProcessor(new NotNull(), DELIMITER_ARRAY));
|
||||
@@ -139,44 +195,27 @@ public class CSVResponseStreamWriter extends AbstractResponseStreamWriter {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void writeToOutput(Stream<Entry<String, ?>> stream, List<String> header, CellProcessor[] processors,
|
||||
ICsvDozerBeanWriter beanWriter) throws IOException, Exception {
|
||||
AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
try {
|
||||
|
||||
private void writeToOutput(Triple<BackendQuery, ChannelName, ?> triple, CellProcessor[] processors,
|
||||
ICsvDozerBeanWriter beanWriter, List<String> header) throws IOException {
|
||||
if (triple.getRight() instanceof Stream) {
|
||||
beanWriter.writeComment("");
|
||||
beanWriter.writeComment("Start of " + triple.getMiddle());
|
||||
beanWriter.writeHeader(header.toArray(new String[header.size()]));
|
||||
|
||||
stream
|
||||
/* ensure elements are sequentially written */
|
||||
.sequential()
|
||||
Stream<DataEvent> eventStream = (Stream<DataEvent>) triple.getRight();
|
||||
eventStream
|
||||
.forEach(
|
||||
entry -> {
|
||||
if (entry.getValue() instanceof Stream) {
|
||||
Stream<DataEvent> eventStream = (Stream<DataEvent>) entry.getValue();
|
||||
eventStream
|
||||
.forEach(
|
||||
event -> {
|
||||
try {
|
||||
beanWriter.write(event, processors);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not write elements for '{}-{}'", event.getChannel(),
|
||||
event.getPulseId(), e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
String message = "Type '" + entry.getValue().getClass() + "' not supported.";
|
||||
LOGGER.error(message);
|
||||
exception.compareAndSet(null, new RuntimeException(message));
|
||||
}
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
beanWriter.close();
|
||||
}
|
||||
|
||||
if (exception.get() != null) {
|
||||
throw exception.get();
|
||||
event -> {
|
||||
try {
|
||||
beanWriter.write(event, processors);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not write elements for '{}-{}'", event.getChannel(),
|
||||
event.getPulseId(), e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
String message = "Type '" + triple.getRight().getClass() + "' not supported.";
|
||||
LOGGER.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ch.psi.daq.queryrest.response.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@@ -13,15 +12,11 @@ import javax.annotation.Resource;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import ch.psi.daq.query.model.Aggregation;
|
||||
import ch.psi.daq.query.model.QueryField;
|
||||
import ch.psi.daq.query.model.impl.DAQQuery;
|
||||
import ch.psi.daq.queryrest.response.AbstractResponseStreamWriter;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -30,6 +25,14 @@ import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
|
||||
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
|
||||
|
||||
import ch.psi.daq.query.model.Aggregation;
|
||||
import ch.psi.daq.query.model.QueryField;
|
||||
import ch.psi.daq.query.model.ResponseOptions;
|
||||
import ch.psi.daq.query.model.impl.BackendQuery;
|
||||
import ch.psi.daq.query.model.impl.DAQQueryElement;
|
||||
import ch.psi.daq.query.request.ChannelName;
|
||||
import ch.psi.daq.queryrest.response.AbstractResponseStreamWriter;
|
||||
|
||||
/**
|
||||
* Takes a Java 8 stream and writes it to the output stream provided by the {@link ServletResponse}
|
||||
* of the current request.
|
||||
@@ -38,7 +41,7 @@ public class JSONResponseStreamWriter extends AbstractResponseStreamWriter {
|
||||
|
||||
private static final String DATA_RESP_FIELD = "data";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JSONResponseStreamWriter.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JSONResponseStreamWriter.class);
|
||||
|
||||
@Resource
|
||||
private JsonFactory jsonFactory;
|
||||
@@ -46,19 +49,78 @@ public class JSONResponseStreamWriter extends AbstractResponseStreamWriter {
|
||||
@Resource
|
||||
private ObjectMapper mapper;
|
||||
|
||||
|
||||
@Override
|
||||
public void respond(Stream<Entry<String, ?>> stream, DAQQuery query, HttpServletResponse response) throws Exception {
|
||||
public void respond(List<Entry<DAQQueryElement, Stream<Triple<BackendQuery, ChannelName, ?>>>> results,
|
||||
ResponseOptions options, HttpServletResponse response) throws Exception {
|
||||
response.setCharacterEncoding(JsonEncoding.UTF8.getJavaName());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
Set<String> includedFields = getFields(query);
|
||||
|
||||
ObjectWriter writer = configureWriter(includedFields);
|
||||
|
||||
respondInternal(stream, response, writer, query);
|
||||
respondInternal(results, options, response);
|
||||
}
|
||||
|
||||
protected Set<String> getFields(DAQQuery query) {
|
||||
private void respondInternal(List<Entry<DAQQueryElement, Stream<Triple<BackendQuery, ChannelName, ?>>>> results,
|
||||
ResponseOptions options, HttpServletResponse response) throws Exception {
|
||||
AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
OutputStream out = handleCompressionAndResponseHeaders(options, response, CONTENT_TYPE_JSON);
|
||||
JsonGenerator generator = jsonFactory.createGenerator(out, JsonEncoding.UTF8);
|
||||
|
||||
try {
|
||||
if (results.size() > 1) {
|
||||
generator.writeStartArray();
|
||||
}
|
||||
|
||||
results
|
||||
.forEach(entryy -> {
|
||||
DAQQueryElement daqQuery = entryy.getKey();
|
||||
Set<String> includedFields = getFields(daqQuery);
|
||||
ObjectWriter writer = configureWriter(includedFields);
|
||||
|
||||
try {
|
||||
generator.writeStartArray();
|
||||
|
||||
entryy.getValue()
|
||||
/* ensure elements are sequentially written */
|
||||
.sequential()
|
||||
.forEach(
|
||||
triple -> {
|
||||
try {
|
||||
generator.writeStartObject();
|
||||
generator.writeStringField(QueryField.channel.name(), triple.getMiddle()
|
||||
.getName());
|
||||
|
||||
generator.writeFieldName(DATA_RESP_FIELD);
|
||||
writer.writeValue(generator, triple.getRight());
|
||||
|
||||
generator.writeEndObject();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not write channel name of channel '{}'", triple.getMiddle(),
|
||||
e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
});
|
||||
|
||||
generator.writeEndArray();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Exception while writing json for '{}'", daqQuery.getChannels(), e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
if (results.size() > 1) {
|
||||
generator.writeEndArray();
|
||||
}
|
||||
|
||||
generator.flush();
|
||||
generator.close();
|
||||
}
|
||||
|
||||
if (exception.get() != null) {
|
||||
throw exception.get();
|
||||
}
|
||||
}
|
||||
|
||||
protected Set<String> getFields(DAQQueryElement query) {
|
||||
Set<QueryField> queryFields = query.getFields();
|
||||
List<Aggregation> aggregations = query.getAggregations();
|
||||
|
||||
@@ -95,52 +157,4 @@ public class JSONResponseStreamWriter extends AbstractResponseStreamWriter {
|
||||
ObjectWriter writer = mapper.writer(propertyFilter);
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the outer Java stream into the output stream.
|
||||
*
|
||||
* @param stream Mapping from channel name to data
|
||||
* @param response {@link ServletResponse} instance given by the current HTTP request
|
||||
* @param writer configured writer that includes the fields the end user wants to see
|
||||
* @param query
|
||||
* @throws IOException thrown if writing to the output stream fails
|
||||
*/
|
||||
private void respondInternal(Stream<Entry<String, ?>> stream, HttpServletResponse response, ObjectWriter writer, DAQQuery query)
|
||||
throws Exception {
|
||||
|
||||
OutputStream out = handleCompressionAndResponseHeaders(query, response, CONTENT_TYPE_JSON);
|
||||
JsonGenerator generator = jsonFactory.createGenerator(out, JsonEncoding.UTF8);
|
||||
|
||||
AtomicReference<Exception> exception = new AtomicReference<>();
|
||||
try {
|
||||
generator.writeStartArray();
|
||||
stream
|
||||
/* ensure elements are sequentially written */
|
||||
.sequential()
|
||||
.forEach(
|
||||
entry -> {
|
||||
try {
|
||||
generator.writeStartObject();
|
||||
generator.writeStringField(QueryField.channel.name(), entry.getKey());
|
||||
|
||||
generator.writeFieldName(DATA_RESP_FIELD);
|
||||
writer.writeValue(generator, entry.getValue());
|
||||
|
||||
generator.writeEndObject();
|
||||
} catch (Exception e) {
|
||||
logger.error("Could not write channel name of channel '{}'", entry.getKey(), e);
|
||||
exception.compareAndSet(null, e);
|
||||
}
|
||||
});
|
||||
generator.writeEndArray();
|
||||
} finally {
|
||||
generator.flush();
|
||||
generator.close();
|
||||
}
|
||||
|
||||
if (exception.get() != null) {
|
||||
throw exception.get();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package ch.psi.daq.queryrest.response.json;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerationException;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
|
||||
// see: http://stackoverflow.com/a/15037329
|
||||
public class JsonByteArraySerializer extends StdSerializer<byte[]> {
|
||||
private static final long serialVersionUID = -5914688899857435263L;
|
||||
|
||||
public JsonByteArraySerializer() {
|
||||
super(byte[].class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(byte[] bytes, JsonGenerator jgen, SerializerProvider provider) throws IOException,
|
||||
JsonGenerationException {
|
||||
jgen.writeStartArray();
|
||||
|
||||
for (byte b : bytes) {
|
||||
// stackoverflow example used a mask -> ?
|
||||
jgen.writeNumber(b);
|
||||
}
|
||||
|
||||
jgen.writeEndArray();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package ch.psi.daq.queryrest.response.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerationException;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
|
||||
public class JsonStreamSerializer extends StdSerializer<Stream<?>>{
|
||||
private static final long serialVersionUID = 4695859735299703478L;
|
||||
|
||||
public JsonStreamSerializer() {
|
||||
super(Stream.class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Stream<?> stream, JsonGenerator jgen, SerializerProvider provider) throws IOException,
|
||||
JsonGenerationException {
|
||||
provider.findValueSerializer(Iterator.class, null).serialize(stream.iterator(), jgen, provider);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user