Option to define mapping aggregations.

This commit is contained in:
Fabian Märki
2018-10-30 09:28:34 +01:00
parent 206bc63879
commit 980ddc2098
4 changed files with 217 additions and 27 deletions
@@ -311,6 +311,8 @@ public class CSVResponseStreamWriter implements ResponseStreamWriter, Applicatio
final List<Aggregation> aggregations =
daqQuery.getAggregation() != null ? daqQuery.getAggregation().getAggregations() : null;
final List<Extrema> extrema = daqQuery.getAggregation() != null ? daqQuery.getAggregation().getExtrema() : null;
final List<Aggregation> mappingAggregations =
daqQuery.getMapping() != null ? daqQuery.getMapping().getAggregations() : null;
final BackendQueryAnalyzer queryAnalyzer = queryAnalizerFactory.apply(backendQuery);
@@ -323,30 +325,38 @@ public class CSVResponseStreamWriter implements ResponseStreamWriter, Applicatio
// in case Mapping maps several events to the same bin -> values will be aggregated into
// BinnedValueCombinedDataEvent or BinnedIndexCombinedDataEvent
final Collection<Aggregation> locAggregations;
if (aggregations != null) {
locAggregations = aggregations;
} else {
locAggregations =
context.getBean(QueryRestConfig.BEAN_NAME_DEFAULT_EVENT_RESPONSE_AGGREGATIONS, Set.class);
}
final Stringifier statsStringifier;
if (locAggregations.size() == 1) {
// if only one aggregation is active, write only this value
// -> makes it compatible with scalar/array layout
statsStringifier = new AggregationStringifyer(locAggregations.iterator().next(), EMPTY_VALUE);
} else {
final Map<String, Stringifier> aggregationsStringifiers = new LinkedHashMap<>(locAggregations.size());
for (final Aggregation aggregation : locAggregations) {
aggregationsStringifiers.put(aggregation.name(),
new AggregationStringifyer(aggregation, EMPTY_VALUE));
Collection<Aggregation> locMappingAggregations = null;
if (aggregations == null) {
// only when general aggregations is disabled
// -> otherwise values will already be globally aggregated
locMappingAggregations = mappingAggregations;
if (locMappingAggregations == null) {
// use default -> should there be an extra field
locMappingAggregations =
context.getBean(QueryRestConfig.BEAN_NAME_DEFAULT_EVENT_RESPONSE_AGGREGATIONS, Set.class);
}
statsStringifier = new ObjectStringifier(aggregationsStringifiers);
}
final Map<Class<?>, Stringifier> stringifiers = new HashMap<>(2);
stringifiers.put(StorelessStatistics.class, statsStringifier);
stringifiers.put(StorelessStatistics[].class, statsStringifier);
Map<Class<?>, Stringifier> stringifiers = null;
if (locMappingAggregations != null) {
final Stringifier statsStringifier;
if (locMappingAggregations.size() == 1) {
// if only one aggregation is active, write only this value
// -> makes it compatible with scalar/array layout
statsStringifier = new AggregationStringifyer(locMappingAggregations.iterator().next(), EMPTY_VALUE);
} else {
final Map<String, Stringifier> aggregationsStringifiers =
new LinkedHashMap<>(locMappingAggregations.size());
for (final Aggregation aggregation : locMappingAggregations) {
aggregationsStringifiers.put(aggregation.name(),
new AggregationStringifyer(aggregation, EMPTY_VALUE));
}
statsStringifier = new ObjectStringifier(aggregationsStringifiers);
}
stringifiers = new HashMap<>(2);
stringifiers.put(StorelessStatistics.class, statsStringifier);
stringifiers.put(StorelessStatistics[].class, statsStringifier);
}
header.add(buf.toString());
accessors.add(Pair.of(
channelName,
@@ -222,12 +222,13 @@ public class DAQQueriesResponseFormatter
final Mapping mapping = daqQuery.getMappingOrDefault(DEFAULT_MAPPING);
final Padder<ChannelName, DataEvent> padder = mapping.getIncomplete().getPadder(backendQuery);
ToLongFunction<DataEvent> alignmentProvider = Alignment.getAlignmentProvider(daqQuery.getMapping().getAlignment(), binningStrategy);
ToLongFunction<DataEvent> alignmentProvider =
Alignment.getAlignmentProvider(daqQuery.getMapping().getAlignment(), binningStrategy);
if (binningStrategy == null) {
binningStrategy = Alignment.getBinningStrategy(daqQuery.getMapping().getAlignment(), requestRange);
}
}
BiFunction<DataEvent, DataEvent, DataEvent> valueCombiner = null;
if(binningStrategy != null){
if (binningStrategy != null) {
binningStrategy.setRequestRange(requestRange);
valueCombiner = new BinnedValueCombiner(binningStrategy);
}
@@ -327,8 +328,12 @@ public class DAQQueriesResponseFormatter
private static Set<String> getEventFields(final DAQQueryElement query, final boolean removeIdentifiers) {
final Set<? extends QueryField> eventFields = query.getEventFields();
final List<Aggregation> aggregations =
List<Aggregation> aggregations =
query.getAggregation() != null ? query.getAggregation().getAggregations() : null;
if (aggregations == null && query.getMapping() != null) {
// global aggregation has precedence
aggregations = query.getMapping().getAggregations();
}
final List<Extrema> extrema = query.getAggregation() != null ? query.getAggregation().getExtrema() : null;
final Set<String> includedFields =
@@ -346,6 +346,178 @@ public class CSVQueryRestControllerTest extends AbstractDaqRestTest implements A
reader.close();
csvParser.close();
}
request = new DAQQuery(
new RequestRangePulseId(
0,
2),
channels);
request.setResponse(new CSVHTTPResponse());
request.setEventFields(eventFields);
request.setMapping(new Mapping());
request.getMapping().setAggregations(Arrays.asList(Aggregation.count, Aggregation.mean));
content = mapper.writeValueAsString(request);
System.out.println(content);
result = this.mockMvc
.perform(MockMvcRequestBuilders
.post(DomainConfig.PATH_QUERY)
.contentType(MediaType.APPLICATION_JSON)
.content(content))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
response = result.getResponse().getContentAsString();
System.out.println("Response: " + response);
csvFormat = CSVFormat.EXCEL.withDelimiter(CSVResponseStreamWriter.DELIMITER_CVS);
reader = new StringReader(response);
csvParser = new CSVParser(reader, csvFormat);
try {
long pulse = 0;
int totalEventRows = 3;
List<CSVRecord> records = csvParser.getRecords();
assertEquals(totalEventRows + 1, records.size());
CSVRecord record = records.remove(0);
assertEquals(eventFields.size() * channels.size(), record.size());
int column = 0;
for (String channel : channels) {
for (EventField eventField : eventFields) {
assertEquals(channel + CSVResponseStreamWriter.DELIMITER_CHANNELNAME_FIELDNAME + eventField.name(),
record.get(column++));
}
}
for (int row = 0; row < totalEventRows; ++row) {
record = records.get(row);
assertEquals(eventFields.size() * channels.size(), record.size());
column = 0;
for (String channel : channels) {
if (channelSeq.get(channel).contains(pulse)) {
assertEquals(channel, record.get(column++));
assertEquals("" + pulse, record.get(column++));
assertEquals("" + TestTimeUtils.getTimeFromPulseId(pulse).getMillis(), record.get(column++));
if (channel.toLowerCase().contains("waveform")) {
if (pulse != 1) {
assertEquals("[" + pulse + "," + pulse + ",2,3,4,5,6,7]", record.get(column++));
} else {
assertEquals(
"[{count:2.0 mean:1.0},{count:2.0 mean:1.0},{count:2.0 mean:2.0},{count:2.0 mean:3.0},{count:2.0 mean:4.0},{count:2.0 mean:5.0},{count:2.0 mean:6.0},{count:2.0 mean:7.0}]",
record.get(column++));
}
} else {
if (pulse != 1) {
assertEquals("" + pulse, record.get(column++));
} else {
assertEquals("{count:2.0 mean:1.0}", record.get(column++));
}
}
} else {
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
}
}
++pulse;
}
} finally {
reader.close();
csvParser.close();
}
request = new DAQQuery(
new RequestRangePulseId(
0,
2),
channels);
request.setResponse(new CSVHTTPResponse());
request.setEventFields(eventFields);
request.setMapping(new Mapping());
request.getMapping().setAggregations(Arrays.asList(Aggregation.mean));
content = mapper.writeValueAsString(request);
System.out.println(content);
result = this.mockMvc
.perform(MockMvcRequestBuilders
.post(DomainConfig.PATH_QUERY)
.contentType(MediaType.APPLICATION_JSON)
.content(content))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
response = result.getResponse().getContentAsString();
System.out.println("Response: " + response);
csvFormat = CSVFormat.EXCEL.withDelimiter(CSVResponseStreamWriter.DELIMITER_CVS);
reader = new StringReader(response);
csvParser = new CSVParser(reader, csvFormat);
try {
long pulse = 0;
int totalEventRows = 3;
List<CSVRecord> records = csvParser.getRecords();
assertEquals(totalEventRows + 1, records.size());
CSVRecord record = records.remove(0);
assertEquals(eventFields.size() * channels.size(), record.size());
int column = 0;
for (String channel : channels) {
for (EventField eventField : eventFields) {
assertEquals(channel + CSVResponseStreamWriter.DELIMITER_CHANNELNAME_FIELDNAME + eventField.name(),
record.get(column++));
}
}
for (int row = 0; row < totalEventRows; ++row) {
record = records.get(row);
assertEquals(eventFields.size() * channels.size(), record.size());
column = 0;
for (String channel : channels) {
if (channelSeq.get(channel).contains(pulse)) {
assertEquals(channel, record.get(column++));
assertEquals("" + pulse, record.get(column++));
assertEquals("" + TestTimeUtils.getTimeFromPulseId(pulse).getMillis(), record.get(column++));
if (channel.toLowerCase().contains("waveform")) {
if (pulse != 1) {
assertEquals("[" + pulse + "," + pulse + ",2,3,4,5,6,7]", record.get(column++));
} else {
assertEquals(
"[1.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0]",
record.get(column++));
}
} else {
if (pulse != 1) {
assertEquals("" + pulse, record.get(column++));
} else {
assertEquals("1.0", record.get(column++));
}
}
} else {
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
assertEquals(CSVResponseStreamWriter.EMPTY_VALUE, record.get(column++));
}
}
++pulse;
}
} finally {
reader.close();
csvParser.close();
}
}
@Test