/*
* Copyright 2015 Hewlett-Packard Development Company, L.P.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
*/
package com.hp.autonomy.frontend.find.hod.export.service;
import com.hp.autonomy.frontend.find.core.export.service.ExportFormat;
import com.hp.autonomy.frontend.find.core.export.service.PlatformDataExportService;
import com.hp.autonomy.frontend.find.core.export.service.PlatformDataExportStrategy;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.searchcomponents.core.config.FieldInfo;
import com.hp.autonomy.searchcomponents.hod.search.HodDocumentsService;
import com.hp.autonomy.searchcomponents.hod.search.HodQueryRequest;
import com.hp.autonomy.searchcomponents.hod.search.HodSearchResult;
import com.hp.autonomy.types.requests.Documents;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
class HodPlatformDataExportService implements PlatformDataExportService<HodQueryRequest, HodErrorException> {
private final HodDocumentsService documentsService;
private final Map<ExportFormat, PlatformDataExportStrategy> exportStrategies;
@Autowired
public HodPlatformDataExportService(final HodDocumentsService documentsService,
final PlatformDataExportStrategy[] exportStrategies) {
this.documentsService = documentsService;
this.exportStrategies = new EnumMap<>(ExportFormat.class);
for (final PlatformDataExportStrategy exportStrategy : exportStrategies) {
this.exportStrategies.put(exportStrategy.getExportFormat(), exportStrategy);
}
}
@Override
public void exportQueryResults(final OutputStream outputStream, final HodQueryRequest queryRequest, final ExportFormat exportFormat, final Collection<String> selectedFieldIds, final long totalResults) throws HodErrorException {
final PlatformDataExportStrategy exportStrategy = exportStrategies.get(exportFormat);
final List<FieldInfo<?>> fieldInfoList = exportStrategy.getFieldNames(HodMetadataNode.values(), selectedFieldIds);
final List<String> fieldIds = fieldInfoList.stream()
.map(FieldInfo::getId)
.collect(Collectors.toList());
try {
exportStrategy.writeHeader(outputStream, fieldInfoList);
for (int i = 0; i < totalResults; i += PAGINATION_SIZE) {
final HodQueryRequest paginatedQueryRequest = queryRequest.toBuilder()
.start(i + 1)
.maxResults(Math.min(i + PAGINATION_SIZE, HodDocumentsService.HOD_MAX_RESULTS))
.build();
final Documents<HodSearchResult> documents = documentsService.queryTextIndex(paginatedQueryRequest.toBuilder()
.printFields(fieldIds)
.build());
final List<Function<HodSearchResult, String>> exportMetadataFunctions = Arrays.stream(HodMetadataNode.values())
.filter(node -> selectedFieldIds.isEmpty() || selectedFieldIds.contains(node.getName()))
.map(node -> (Function<HodSearchResult, String>) hodSearchResult -> {
final Object value = node.getGetter().apply(hodSearchResult);
return value == null ? "" : value.toString();
})
.collect(Collectors.toList());
for (final HodSearchResult searchResult : documents.getDocuments()) {
final Stream<String> metadataStream = exportMetadataFunctions.stream()
.map(extractor -> extractor.apply(searchResult));
final Stream<String> nonMetadataStream = exportStrategy.getConfiguredFieldsById().values().stream()
.filter(configuredField -> selectedFieldIds.isEmpty() || selectedFieldIds.contains(configuredField.getId()))
.map(configuredField -> {
final FieldInfo<?> fieldInfo = searchResult.getFieldMap().get(configuredField.getId());
return exportStrategy.combineValues(getValuesAsStrings(fieldInfo));
});
exportStrategy.exportRecord(outputStream, Stream.concat(metadataStream, nonMetadataStream).collect(Collectors.toList()));
}
}
} catch (final IOException e) {
//noinspection ProhibitedExceptionThrown
throw new RuntimeException("Error parsing data", e);
}
}
private List<String> getValuesAsStrings(final FieldInfo<?> fieldInfo) {
return fieldInfo != null ? fieldInfo.getValues().stream()
// prevents NullPointerException if the data set contains an incorrectly formatted date
.filter(Objects::nonNull)
.map(Object::toString).collect(Collectors.toList()) : Collections.emptyList();
}
@Override
public Collection<ExportFormat> handlesFormats() {
return exportStrategies.keySet();
}
}