Skip to content

Commit

Permalink
[Fix partially kbss-cvut/record-manager-ui#36] Implement paging reque…
Browse files Browse the repository at this point in the history
…st parameters support for excel export
  • Loading branch information
kostobog committed Jul 10, 2024
1 parent 0b985cd commit d05e5dc
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
public class PatientRecordDao extends OwlKeySupportingDao<PatientRecord> {

public static final String FIND_ALL_RAW_PATIENT_RECORDS = "find-raw-records.sparql";
public static final String RAW_RECORDS_FILTER_CLAUSE_PATTERN = "###FILTER_CLAUSES###";
public static final String RECORDS_CLAUSE_TEMPLATE_VAR = "###RECORD_CLAUSE###";

public PatientRecordDao(EntityManager em) {
super(PatientRecord.class, em);
Expand Down Expand Up @@ -243,17 +243,40 @@ private <T> Page<T> findRecords(RecordFilterParams filters, Pageable pageSpec, C
return new PageImpl<>(records, pageSpec, totalCount);
}

public List<RawRecord> findAllRecordsRaw(RecordFilterParams filters){
public Page<RawRecord> findAllRecordsRaw(RecordFilterParams filters, Pageable pageSpec){
final Map<String, Object> queryParams = new HashMap<>();
final String filterClauseExtension = mapParamsToQuery(filters, queryParams);
final String queryString = Utils.loadQuery(FIND_ALL_RAW_PATIENT_RECORDS)
.replaceAll(RAW_RECORDS_FILTER_CLAUSE_PATTERN, filterClauseExtension);
Query query = em.createNativeQuery(queryString, RawRecord.class.getSimpleName());
final String whereClause = constructWhereClause(filters, queryParams);

final String queryStringNoPaging = Utils.loadQuery(FIND_ALL_RAW_PATIENT_RECORDS)
.replaceFirst(RECORDS_CLAUSE_TEMPLATE_VAR, whereClause);
final String queryString = queryStringNoPaging + (pageSpec.isPaged()
? resolveOrderBy(pageSpec.getSortOr(RecordSort.defaultSort()))
: ""
);

Query query = em.createNativeQuery(queryString, RawRecord.class.getSimpleName());
queryParams.forEach(query::setParameter);
return query.getResultList();

if (pageSpec.isPaged()) {
query.setFirstResult((int) pageSpec.getOffset());
query.setMaxResults(pageSpec.getPageSize());
}
setQueryParameters(query, queryParams);
List<RawRecord> result = query.getResultList();
Integer totalCount = result.size();
if(pageSpec.isPaged()){
TypedQuery<Integer> countQuery = em.createNativeQuery(
"SELECT (COUNT(?r) as ?cnt) WHERE {%s}".formatted(whereClause),
Integer.class);

setQueryParameters(countQuery, queryParams);
totalCount = countQuery.getSingleResult();
}

return new PageImpl<>(result, pageSpec, totalCount);
}

private void setQueryParameters(TypedQuery<?> query, Map<String, Object> queryParams) {
private void setQueryParameters(Query query, Map<String, Object> queryParams) {
query.setParameter("type", typeUri)
.setParameter("hasPhase", URI.create(Vocabulary.s_p_has_phase))
.setParameter("hasFormTemplate", URI.create(Vocabulary.s_p_has_form_template))
Expand Down
16 changes: 12 additions & 4 deletions src/main/java/cz/cvut/kbss/study/rest/PatientRecordController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import cz.cvut.kbss.study.exception.NotFoundException;
import cz.cvut.kbss.study.model.PatientRecord;
import cz.cvut.kbss.study.model.RecordPhase;
import cz.cvut.kbss.study.model.export.RawRecord;
import cz.cvut.kbss.study.persistence.dao.util.RecordFilterParams;
import cz.cvut.kbss.study.rest.event.PaginatedResultRetrievedEvent;
import cz.cvut.kbss.study.rest.exception.BadRequestException;
import cz.cvut.kbss.study.rest.util.RecordFilterMapper;
import cz.cvut.kbss.study.rest.util.RestUtils;
import cz.cvut.kbss.study.security.SecurityConstants;
import cz.cvut.kbss.study.service.ExcelRecordConverter;
import cz.cvut.kbss.study.service.PatientRecordService;
import cz.cvut.kbss.study.util.Constants;
import jakarta.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -38,10 +40,12 @@ public class PatientRecordController extends BaseController {
private final PatientRecordService recordService;

private final ApplicationEventPublisher eventPublisher;
private final ExcelRecordConverter excelRecordConverter;

public PatientRecordController(PatientRecordService recordService, ApplicationEventPublisher eventPublisher) {
public PatientRecordController(PatientRecordService recordService, ApplicationEventPublisher eventPublisher, ExcelRecordConverter excelRecordConverter) {
this.recordService = recordService;
this.eventPublisher = eventPublisher;
this.excelRecordConverter = excelRecordConverter;
}

@PreAuthorize("hasRole('" + SecurityConstants.ROLE_ADMIN + "') or @securityUtils.isMemberOfInstitution(#institutionKey)")
Expand Down Expand Up @@ -75,7 +79,7 @@ public ResponseEntity<?> exportRecords(
.removeQualityValue();

return switch (exportType.toString()){
case Constants.MEDIA_TYPE_EXCEL -> exportRecordsExcel(params, response);
case Constants.MEDIA_TYPE_EXCEL -> exportRecordsExcel(params, uriBuilder, response);
case MediaType.APPLICATION_JSON_VALUE -> exportRecordsAsJson(params, uriBuilder, response);
default -> throw new IllegalArgumentException("Unsupported export type: " + exportType);
};
Expand All @@ -92,13 +96,17 @@ protected ResponseEntity<List<PatientRecord>> exportRecordsAsJson(
.body(result.getContent());
}

public ResponseEntity<InputStreamResource> exportRecordsExcel(MultiValueMap<String, String> params, HttpServletResponse response){
public ResponseEntity<InputStreamResource> exportRecordsExcel(MultiValueMap<String, String> params,
UriComponentsBuilder uriBuilder, HttpServletResponse response){
RecordFilterParams filterParams = new RecordFilterParams();
filterParams.setMinModifiedDate(null);
filterParams.setMaxModifiedDate(null);
RecordFilterMapper.constructRecordFilter(filterParams, params);

InputStream stream = recordService.exportRecords(filterParams);
Page<RawRecord> result = recordService.exportRecords(filterParams, RestUtils.resolvePaging(params));

InputStream stream = excelRecordConverter.convert(result.getContent());
eventPublisher.publishEvent(new PaginatedResultRetrievedEvent(this, uriBuilder, response, result));
ContentDisposition contentDisposition = ContentDisposition.attachment().filename("export.xlsx").build();
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(Constants.MEDIA_TYPE_EXCEL))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import cz.cvut.kbss.study.model.export.Path;
import cz.cvut.kbss.study.model.export.RawRecord;
import cz.cvut.kbss.study.persistence.dao.CodeListValuesDao;
import cz.cvut.kbss.study.persistence.dao.PatientRecordDao;
import cz.cvut.kbss.study.persistence.dao.util.RecordFilterParams;
import cz.cvut.kbss.study.util.Utils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
Expand All @@ -22,20 +20,18 @@
import java.util.stream.Stream;

@Service
public class ExcelRecordExporter {
public class ExcelRecordConverter {

private final PatientRecordDao patientRecordDao;
private final CodeListValuesDao codeListValuesDao;

public ExcelRecordExporter(PatientRecordDao patientRecordDao, CodeListValuesDao codeListValuesDao) {
this.patientRecordDao = patientRecordDao;
public ExcelRecordConverter(CodeListValuesDao codeListValuesDao) {
this.codeListValuesDao = codeListValuesDao;
}

public InputStream exportRecords(RecordFilterParams filters){
public InputStream convert(List<RawRecord> rawRecords){
try {
XSSFWorkbook workbook = new XSSFWorkbook(Utils.class.getClassLoader().getResourceAsStream("templates/record-export-template.xlsx"));
List<ExportRecord> exportRecords = findExportRecords(filters);
List<ExportRecord> exportRecords = findExportRecordsData(rawRecords);
addDataToExcel(workbook, exportRecords);
ByteArrayOutputStream output = new ByteArrayOutputStream();
workbook.write(output);
Expand All @@ -45,8 +41,7 @@ public InputStream exportRecords(RecordFilterParams filters){
}
}

private List<ExportRecord> findExportRecords(RecordFilterParams filters){
List<RawRecord> rawRecords = patientRecordDao.findAllRecordsRaw(filters);
private List<ExportRecord> findExportRecordsData(List<RawRecord> rawRecords){
Map<URI, String> translatorMap = new HashMap<>();
List<Path> paths = codeListValuesDao.getBroaderPath(rawRecords.stream().map(r -> r.getAc_comp()).collect(Collectors.toSet()));
Set<URI> uris = rawRecords.stream().flatMap(r -> Stream.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import cz.cvut.kbss.study.dto.RecordImportResult;
import cz.cvut.kbss.study.model.PatientRecord;
import cz.cvut.kbss.study.model.RecordPhase;
import cz.cvut.kbss.study.model.export.RawRecord;
import cz.cvut.kbss.study.persistence.dao.util.RecordFilterParams;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.io.InputStream;
import java.util.List;

public interface PatientRecordService extends BaseService<PatientRecord> {
Expand Down Expand Up @@ -79,5 +79,11 @@ public interface PatientRecordService extends BaseService<PatientRecord> {
*/
RecordImportResult importRecords(List<PatientRecord> records, RecordPhase targetPhase);

InputStream exportRecords(RecordFilterParams filters);
/**
*
* @param filters Record filtering criteria
* @param pageSpec Specification of page and sorting to retrieve
* @return List of matching records
*/
Page<RawRecord> exportRecords(RecordFilterParams filters, Pageable pageSpec);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import cz.cvut.kbss.study.model.PatientRecord;
import cz.cvut.kbss.study.model.RecordPhase;
import cz.cvut.kbss.study.model.User;
import cz.cvut.kbss.study.model.export.RawRecord;
import cz.cvut.kbss.study.persistence.dao.OwlKeySupportingDao;
import cz.cvut.kbss.study.persistence.dao.PatientRecordDao;
import cz.cvut.kbss.study.persistence.dao.util.RecordFilterParams;
import cz.cvut.kbss.study.service.ExcelRecordExporter;
import cz.cvut.kbss.study.service.PatientRecordService;
import cz.cvut.kbss.study.service.UserService;
import cz.cvut.kbss.study.service.security.SecurityUtils;
Expand All @@ -21,7 +21,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;
Expand All @@ -38,14 +37,14 @@ public class RepositoryPatientRecordService extends KeySupportingRepositoryServi
private final SecurityUtils securityUtils;

private final UserService userService;
private final ExcelRecordExporter excelRecordExporter;
private final PatientRecordDao patientRecordDao;

public RepositoryPatientRecordService(PatientRecordDao recordDao, SecurityUtils securityUtils,
UserService userService, ExcelRecordExporter excelRecordExporter) {
UserService userService, PatientRecordDao patientRecordDao) {
this.recordDao = recordDao;
this.securityUtils = securityUtils;
this.userService = userService;
this.excelRecordExporter = excelRecordExporter;
this.patientRecordDao = patientRecordDao;
}

@Override
Expand Down Expand Up @@ -131,7 +130,7 @@ public RecordImportResult importRecords(List<PatientRecord> records, RecordPhase
}

@Override
public InputStream exportRecords(RecordFilterParams filters) {
return excelRecordExporter.exportRecords(filters);
public Page<RawRecord> exportRecords(RecordFilterParams filters, Pageable pageSpec){
return patientRecordDao.findAllRecordsRaw(filters, pageSpec);
}
}
Loading

0 comments on commit d05e5dc

Please sign in to comment.