package org.openmrs.module.patientmatching; import org.openmrs.api.context.Context; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * Class to read the reports saved in database. If the report has too many pairs, this will divide them into pages * And will show the defined number of pages per each group */ public class DataBaseReportReader { /** * Number of matching record groups to show in a single page. * The page will display roughly twice the amount of records as this number * as page breaks are defined by the groups and not by the pairs. * This class builds a map with details of * where the pages should be divided and stores it in the session. * That map will be used in the next reads and this avoid recalculating where the pages are separated * and what should be displayed in each given page. */ private static final int GROUPS_PER_PAGE = 20; private Report report; private Set<String> includedFields; private Map<Integer,Integer> paginationMap; private int lastPage; /** * Constructor that is called when the report is first displayed. Calculate and build the mapping for the next pages * @param reportName name of the report to read */ public DataBaseReportReader(String reportName){ this(reportName, new HashMap<Integer, Integer>()); buildCache(); } /** * Constructor that is called when navigating through the pages. * @param reportName name of the report to read * @param paginationMap The mapping of records to the pages. This is calculated in the other constructor and reused * having stored in the session */ public DataBaseReportReader(String reportName, Map<Integer,Integer> paginationMap){ setReport(reportName); setIncludedFields(); this.paginationMap = paginationMap; this.lastPage = paginationMap.size() - 1; //Number of entries counting the "0th" entry } /** * build the mapping of records to the pages they should be in */ private void buildCache(){ int groupCount = 0; int recordCount = 0; int lastGroup = -1; int lastPage = 0; paginationMap.put(0, 0); //first page starts from the 0th record for(MatchingRecord record : report.getMatchingRecordSet()){ //as the set sorted, the iteration happens starting from group 0 recordCount ++; if(record.getGroupId()!=lastGroup){ //the record is from a new group groupCount ++; lastGroup = record.getGroupId(); if(groupCount % GROUPS_PER_PAGE == 0){ //start a new page lastPage++; paginationMap.put(lastPage, recordCount + 1); } } } if (!paginationMap.containsValue(recordCount + 1)){ //adds the index of the last record if not already there lastPage++; paginationMap.put(lastPage,recordCount); } this.lastPage = lastPage; } /** * Set Report name to fetch from Database * @param reportName name of the report to read */ public void setReport(String reportName) { report = Context.getService(PatientMatchingReportMetadataService.class).getReportByName(reportName); } /** * Get the last page number that the report has. * This depends on the number of groups to display and the groups identified by the report * @return */ public int getLastPage() { return lastPage; } /** * Get the indexing map of record to page * @return */ public Map<Integer,Integer> getPaginationMap() { return paginationMap; } /** * Get the header to display in the report. This contains the field specified, the strategies used, the * group and patient ids * @return */ public List<String> getHeader(){ setIncludedFields(); List<String> header = new ArrayList<String>(); header.add("Group Id"); header.add("Unique Id"); header.addAll(includedFields); header.add("Action"); return header; } /** * get the fields used by the configurations specified in the report */ private void setIncludedFields(){ includedFields = MatchingReportUtils.getAllFieldsUsed(report); } /** * Get the data of the records to display in for the given page * @param page the page number to display (1 is the first page) * @return */ public List<List<String>> fetchContent(int page) { if(page>lastPage){ page = lastPage; } if(page<=0){ page=1; } int start = paginationMap.get(page-1); //get the index for the starting and ending record int end = paginationMap.get(page); List<MatchingRecord> records = new ArrayList<MatchingRecord>(report.getMatchingRecordSet()).subList(start,end); List<List<String>> content = new ArrayList<List<String>>(); for(MatchingRecord record : records){ List<String> recordData = new ArrayList<String>(); recordData.add(record.getPatient().getVoided().toString()); recordData.add(record.getPatient().getPatientId().toString()); recordData.add(String.valueOf(record.getGroupId())); recordData.add(record.getPatient().getPatientId().toString()); Map<String,String> attribMap = new HashMap<String, String>(); for(MatchingRecordAttribute attribute: record.getMatchingRecordAttributeSet()){ attribMap.put(attribute.getFieldName(),attribute.getFieldValue()); } for(String field:includedFields){ recordData.add(attribMap.get(field)); } content.add(recordData); } return content; } }