diff --git a/package/docker/bahmni-reports/Dockerfile b/package/docker/bahmni-reports/Dockerfile index 6a426b0e..19b181f9 100644 --- a/package/docker/bahmni-reports/Dockerfile +++ b/package/docker/bahmni-reports/Dockerfile @@ -4,7 +4,7 @@ ENV SERVER_PORT=8051 ENV BASE_DIR=/var/run/bahmni-reports ENV CONTEXT_PATH=/bahmnireports ENV WAR_DIRECTORY=/var/run/bahmni-reports/bahmni-reports -ENV SERVER_OPTS="-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m" +ENV SERVER_OPTS="-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m -Dsun.net.client.defaultConnectTimeout=600000 -Dsun.net.client.defaultReadTimeout=600000" ENV DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=8003,server=y,suspend=n" RUN mkdir -p /var/log/bahmni-reports diff --git a/pom.xml b/pom.xml index cc5326a7..96428f34 100644 --- a/pom.xml +++ b/pom.xml @@ -133,6 +133,10 @@ xml-apis xml-apis + + org.apache.commons + commons-lang3 + @@ -140,6 +144,11 @@ dynamicreports-adhoc ${dynamicreports.version} + + org.apache.commons + commons-lang3 + 3.8.1 + net.sourceforge.dynamicreports dynamicreports-googlecharts diff --git a/src/main/java/org/bahmni/reports/extensions/ResultSetExtension.java b/src/main/java/org/bahmni/reports/extensions/ResultSetExtension.java new file mode 100644 index 00000000..a815d9ba --- /dev/null +++ b/src/main/java/org/bahmni/reports/extensions/ResultSetExtension.java @@ -0,0 +1,20 @@ +package org.bahmni.reports.extensions; + +import net.sf.dynamicreports.jasper.builder.JasperReportBuilder; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collection; +import java.util.Map; + +public interface ResultSetExtension { + static final String EMPTY_STRING = ""; + + void enrich(Collection> collection, JasperReportBuilder jasperReport) throws Exception; + + default void enrichRow(Map rowMap, String columnName, String columnValue) { + if(StringUtils.isBlank(columnValue)){ + columnValue = EMPTY_STRING; + } + rowMap.put(columnName, (T) columnValue); + } +} diff --git a/src/main/java/org/bahmni/reports/model/Constants.java b/src/main/java/org/bahmni/reports/model/Constants.java index 7aa63a24..9b4ef1ff 100644 --- a/src/main/java/org/bahmni/reports/model/Constants.java +++ b/src/main/java/org/bahmni/reports/model/Constants.java @@ -8,5 +8,6 @@ public class Constants { public static final String OBSERVAIONFORMS = "forms"; public static final String LABORDERS = "labOrders"; public static final String FORM_BUILDER_FORMS = "formBuilder"; - public static final String FHIR_TS_LOOKUP_DIAGNOSIS = "fhirTSLookupDiagnosis"; + public static final String FHIR_TS_LOOKUP_DIAGNOSIS_COUNT = "fhirTSLookupDiagnosisCount"; + public static final String FHIR_TS_LOOKUP_DIAGNOSIS_LINE = "fhirTSLookupDiagnosisLine"; } diff --git a/src/main/java/org/bahmni/reports/model/Report.java b/src/main/java/org/bahmni/reports/model/Report.java index f6b2a2bb..1fef6f02 100644 --- a/src/main/java/org/bahmni/reports/model/Report.java +++ b/src/main/java/org/bahmni/reports/model/Report.java @@ -56,7 +56,8 @@ @JsonSubTypes.Type(value = MartConcatenatedReport.class, name = "MartConcatenated"), @JsonSubTypes.Type(value = GenericLabOrderReport.class, name = LABORDERS), @JsonSubTypes.Type(value = ObservationFormReport.class, name = FORM_BUILDER_FORMS), - @JsonSubTypes.Type(value = TSIntegrationDiagnosisReport.class, name = FHIR_TS_LOOKUP_DIAGNOSIS) + @JsonSubTypes.Type(value = TSIntegrationDiagnosisCountReport.class, name = FHIR_TS_LOOKUP_DIAGNOSIS_COUNT), + @JsonSubTypes.Type(value = TSIntegrationDiagnosisLineReport.class, name = FHIR_TS_LOOKUP_DIAGNOSIS_LINE) }) public abstract class Report { diff --git a/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisCountReportConfig.java b/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisCountReportConfig.java new file mode 100644 index 00000000..d4377a63 --- /dev/null +++ b/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisCountReportConfig.java @@ -0,0 +1,17 @@ +package org.bahmni.reports.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class TSIntegrationDiagnosisCountReportConfig extends TSIntegrationDiagnosisReportConfig implements Config { + private Boolean displayGenderGroup; + + public Boolean isDisplayGenderGroup() { + return displayGenderGroup; + } + + public void setDisplayGenderGroup(Boolean displayGenderGroup) { + this.displayGenderGroup = displayGenderGroup; + } +} \ No newline at end of file diff --git a/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisLineReportConfig.java b/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisLineReportConfig.java new file mode 100644 index 00000000..27766280 --- /dev/null +++ b/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisLineReportConfig.java @@ -0,0 +1,37 @@ +package org.bahmni.reports.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.List; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class TSIntegrationDiagnosisLineReportConfig extends TSIntegrationDiagnosisReportConfig implements Config { + private List patientAttributes; + private List patientAddresses; + private List extensions; + + public List getPatientAttributes() { + return patientAttributes; + } + + public void setPatientAttributes(List patientAttributes) { + this.patientAttributes = patientAttributes; + } + + public List getPatientAddresses() { + return patientAddresses; + } + + public void setPatientAddresses(List patientAddresses) { + this.patientAddresses = patientAddresses; + } + + public List getExtensions() { + return extensions; + } + + public void setExtensions(List extensions) { + this.extensions = extensions; + } +} \ No newline at end of file diff --git a/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisReportConfig.java b/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisReportConfig.java index ad0b1df0..163df643 100644 --- a/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisReportConfig.java +++ b/src/main/java/org/bahmni/reports/model/TSIntegrationDiagnosisReportConfig.java @@ -2,15 +2,13 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - @JsonIgnoreProperties(ignoreUnknown = true) -public class TSIntegrationDiagnosisReportConfig implements Config { +public class TSIntegrationDiagnosisReportConfig { private String tsConceptSource; private String conceptNameDisplayFormat; private String terminologyParentCode; private String terminologyColumnName; private Boolean displayTerminologyCode; - private Boolean displayGenderGroup; public String getTsConceptSource() { return tsConceptSource; @@ -52,11 +50,5 @@ public void setTerminologyColumnName(String terminologyColumnName) { this.terminologyColumnName = terminologyColumnName; } - public Boolean isDisplayGenderGroup() { - return displayGenderGroup; - } - public void setDisplayGenderGroup(Boolean displayGenderGroup) { - this.displayGenderGroup = displayGenderGroup; - } -} \ No newline at end of file +} diff --git a/src/main/java/org/bahmni/reports/report/TSHttpClient.java b/src/main/java/org/bahmni/reports/report/TSHttpClient.java new file mode 100644 index 00000000..fced9409 --- /dev/null +++ b/src/main/java/org/bahmni/reports/report/TSHttpClient.java @@ -0,0 +1,24 @@ +package org.bahmni.reports.report; + +import org.apache.http.config.Registry; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bahmni.reports.BahmniReportsConfiguration; +import org.bahmni.reports.BahmniReportsProperties; +import org.bahmni.webclients.HttpClient; + +public interface TSHttpClient { + Logger logger = LogManager.getLogger(TSHttpClient.class); + final String TS_PROPERTIES_FILENAME = "terminology-service-config.properties"; + final String TERMINOLOGY_SERVER_ENDPOINT_PROP = "terminologyServer.endpoint"; + + default HttpClient getHttpClient(BahmniReportsProperties bahmniReportsProperties) { + BahmniReportsConfiguration bahmniReportsConfiguration = new BahmniReportsConfiguration(bahmniReportsProperties); + SSLConnectionSocketFactory allTrustSSLSocketFactory = bahmniReportsConfiguration.allTrustSSLSocketFactory(); + Registry schemeRegistry = bahmniReportsConfiguration.schemeRegistry(allTrustSSLSocketFactory); + HttpClient httpClient = bahmniReportsConfiguration.httpClient(schemeRegistry); + return httpClient; + } +} diff --git a/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisCountReport.java b/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisCountReport.java new file mode 100644 index 00000000..f394b48e --- /dev/null +++ b/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisCountReport.java @@ -0,0 +1,23 @@ +package org.bahmni.reports.report; + + +import org.bahmni.reports.BahmniReportsProperties; +import org.bahmni.reports.model.Report; +import org.bahmni.reports.model.TSIntegrationDiagnosisCountReportConfig; +import org.bahmni.reports.template.BaseReportTemplate; +import org.bahmni.reports.template.TSIntegrationDiagnosisCountReportTemplate; +import org.bahmni.reports.util.PropertyUtil; +import org.bahmni.webclients.HttpClient; + +import java.util.Properties; + +public class TSIntegrationDiagnosisCountReport extends Report implements TSHttpClient { + + @Override + public BaseReportTemplate getTemplate(BahmniReportsProperties bahmniReportsProperties) { + HttpClient httpClient = getHttpClient(bahmniReportsProperties); + Properties tsProperties = PropertyUtil.loadProperties(TS_PROPERTIES_FILENAME); + String tsEndpointTemplate = bahmniReportsProperties.getOpenmrsRootUrl() + tsProperties.getProperty(TERMINOLOGY_SERVER_ENDPOINT_PROP); + return new TSIntegrationDiagnosisCountReportTemplate(httpClient, tsProperties, tsEndpointTemplate); + } +} diff --git a/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisLineReport.java b/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisLineReport.java new file mode 100644 index 00000000..0b7c5700 --- /dev/null +++ b/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisLineReport.java @@ -0,0 +1,24 @@ +package org.bahmni.reports.report; + + +import org.bahmni.reports.BahmniReportsProperties; +import org.bahmni.reports.model.Report; +import org.bahmni.reports.model.TSIntegrationDiagnosisLineReportConfig; +import org.bahmni.reports.template.BaseReportTemplate; +import org.bahmni.reports.template.TSIntegrationDiagnosisLineReportTemplate; +import org.bahmni.reports.util.PropertyUtil; +import org.bahmni.webclients.HttpClient; + + +import java.util.Properties; + +public class TSIntegrationDiagnosisLineReport extends Report implements TSHttpClient { + @Override + public BaseReportTemplate getTemplate(BahmniReportsProperties bahmniReportsProperties) { + HttpClient httpClient = getHttpClient(bahmniReportsProperties); + Properties tsProperties = PropertyUtil.loadProperties(TS_PROPERTIES_FILENAME); + String tsEndpointTemplate = bahmniReportsProperties.getOpenmrsRootUrl() + tsProperties.getProperty(TERMINOLOGY_SERVER_ENDPOINT_PROP); + return new TSIntegrationDiagnosisLineReportTemplate(httpClient, tsProperties, tsEndpointTemplate); + } + +} diff --git a/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisReport.java b/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisReport.java deleted file mode 100644 index 37568478..00000000 --- a/src/main/java/org/bahmni/reports/report/TSIntegrationDiagnosisReport.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.bahmni.reports.report; - -import org.apache.http.config.Registry; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.bahmni.reports.BahmniReportsConfiguration; -import org.bahmni.reports.BahmniReportsProperties; -import org.bahmni.reports.model.Report; -import org.bahmni.reports.model.TSIntegrationDiagnosisReportConfig; -import org.bahmni.reports.template.BaseReportTemplate; -import org.bahmni.reports.template.TSIntegrationDiagnosisReportTemplate; -import org.bahmni.webclients.HttpClient; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -public class TSIntegrationDiagnosisReport extends Report { - private static final Logger logger = LogManager.getLogger(TSIntegrationDiagnosisReport.class); - private static final String TS_PROPERTIES_FILENAME = "terminology-service-config.properties"; - - @Override - public BaseReportTemplate getTemplate(BahmniReportsProperties bahmniReportsProperties) { - HttpClient httpClient = getHttpClient(bahmniReportsProperties); - Properties tsProperties = getTSProperties(); - String tsEndpointTemplate = bahmniReportsProperties.getOpenmrsRootUrl() + tsProperties.getProperty("ts.endpoint"); - return new TSIntegrationDiagnosisReportTemplate(httpClient, tsProperties, tsEndpointTemplate); - } - - private static HttpClient getHttpClient(BahmniReportsProperties bahmniReportsProperties) { - BahmniReportsConfiguration bahmniReportsConfiguration = new BahmniReportsConfiguration(bahmniReportsProperties); - SSLConnectionSocketFactory allTrustSSLSocketFactory = bahmniReportsConfiguration.allTrustSSLSocketFactory(); - Registry schemeRegistry = bahmniReportsConfiguration.schemeRegistry(allTrustSSLSocketFactory); - HttpClient httpClient = bahmniReportsConfiguration.httpClient(schemeRegistry); - return httpClient; - } - - private Properties getTSProperties() { - try { - InputStream in = this.getClass().getClassLoader().getResourceAsStream(TS_PROPERTIES_FILENAME); - Properties p = new Properties(); - p.load(in); - return p; - } catch (IOException e) { - logger.error("Could not load terminology service properties from: " + TS_PROPERTIES_FILENAME, e); - throw new RuntimeException(); - } - } - -} diff --git a/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisReportTemplate.java b/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisCountReportTemplate.java similarity index 59% rename from src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisReportTemplate.java rename to src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisCountReportTemplate.java index 752462bb..bbe56612 100644 --- a/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisReportTemplate.java +++ b/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisCountReportTemplate.java @@ -1,7 +1,5 @@ package org.bahmni.reports.template; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import net.sf.dynamicreports.jasper.builder.JasperReportBuilder; import net.sf.dynamicreports.report.builder.column.TextColumnBuilder; import net.sf.dynamicreports.report.builder.style.StyleBuilder; @@ -10,24 +8,15 @@ import net.sf.dynamicreports.report.constant.PageType; import net.sf.dynamicreports.report.constant.WhenNoDataType; import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.bahmni.reports.model.Report; -import org.bahmni.reports.model.TSIntegrationDiagnosisReportConfig; -import org.bahmni.reports.model.TSPageObject; +import org.bahmni.reports.model.TSIntegrationDiagnosisCountReportConfig; import org.bahmni.reports.model.UsingDatasource; import org.bahmni.reports.report.BahmniReportBuilder; import org.bahmni.reports.util.CommonComponents; import org.bahmni.webclients.HttpClient; import org.stringtemplate.v4.ST; -import java.io.IOException; -import java.net.URI; import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.MessageFormat; import java.util.List; import java.util.Properties; @@ -37,9 +26,7 @@ @UsingDatasource("openmrs") -public class TSIntegrationDiagnosisReportTemplate extends BaseReportTemplate { - public static final String CREATE_SQL_TEMPLATE = "create temporary table {0}(code varchar(100) not null)"; - public static final String INSERT_SQL_TEMPLATE = "insert into {0} values (?)"; +public class TSIntegrationDiagnosisCountReportTemplate extends BaseReportTemplate implements TSIntegrationDiagnosisService { public static final String DIAGNOSIS_COLUMN_NAME = "Diagnosis"; public static final String TERMINOLOGY_COLUMN_NAME = "Terminology Code"; public static final String FEMALE_COLUMN_NAME = "Female"; @@ -48,16 +35,13 @@ public class TSIntegrationDiagnosisReportTemplate extends BaseReportTemplate report, String startDate, String endDate, List resources, PageType pageType) { + public BahmniReportBuilder build(Connection connection, JasperReportBuilder jasperReport, Report report, String startDate, String endDate, List resources, PageType pageType) { String tempTableName = "tmpCodes_" + System.nanoTime(); - loadTempTable(connection, tempTableName, report.getConfig().getTerminologyParentCode()); + loadTempTable(connection, tempTableName, report.getConfig().getTerminologyParentCode(), tsProperties, descendantsUrlTemplate, httpClient); String sql = getFileContent("sql/tsIntegrationDiagnosisCount.sql"); CommonComponents.addTo(jasperReport, report, pageType); @@ -91,7 +75,7 @@ public BahmniReportBuilder build(Connection connection, JasperReportBuilder jasp jasperReport.addColumn(rowCount); StyleBuilder subtotalStyle = stl.style().bold().setHorizontalAlignment(HorizontalAlignment.RIGHT); AggregationSubtotalBuilder totalCount = sbt.sum(rowCount) - .setLabel(TOTAL_LABEL_NAME) + .setLabel(TOTAL_COLUMN_NAME) .setLabelStyle(subtotalStyle); String formattedSql = getFormattedSql(sql, report.getConfig().getTsConceptSource(), report.getConfig().getConceptNameDisplayFormat(), startDate, endDate, tempTableName); jasperReport.setShowColumnTitle(true).setWhenNoDataType(WhenNoDataType.ALL_SECTIONS_NO_DETAIL).subtotalsAtSummary(totalCount).setDataSource(formattedSql, connection); @@ -99,48 +83,6 @@ public BahmniReportBuilder build(Connection connection, JasperReportBuilder jasp return new BahmniReportBuilder(jasperReport); } - private void loadTempTable(Connection connection, String tempTableName, String parentCode) { - int offset = 0; - int pageSize = getDefaultPageSize(); - try { - String createSqlStmt = MessageFormat.format(CREATE_SQL_TEMPLATE, tempTableName); - String insertSqlStmt = MessageFormat.format(INSERT_SQL_TEMPLATE, tempTableName); - Statement statement = connection.createStatement(); - statement.execute(createSqlStmt); - PreparedStatement pstmtInsert = connection.prepareStatement(insertSqlStmt); - - TSPageObject pageObject = null; - do { - try { - pageObject = fetchDescendantsByPagination(parentCode, pageSize, offset, "en"); - } catch (IOException e) { - throw new RuntimeException(); - } - List codes = pageObject.getCodes(); - for (int batchcount = 0; batchcount < codes.size(); batchcount++) { - pstmtInsert.setString(1, codes.get(batchcount)); - pstmtInsert.addBatch(); - } - pstmtInsert.executeBatch(); - offset += pageSize; - } while (offset < pageObject.getTotal()); - } catch (SQLException e) { - logger.error("Error occured while making database call to " + tempTableName + " table"); - throw new RuntimeException(); - } - } - - private TSPageObject fetchDescendantsByPagination(String terminologyCode, int pageSize, int offset, String localeLanguage) throws IOException { - String url = MessageFormat.format(descendantsUrlTemplate, terminologyCode, pageSize, offset, localeLanguage); - String responseStr = httpClient.get(URI.create(url)); - ObjectMapper mapper = new ObjectMapper(); - try { - return mapper.readValue(responseStr, TSPageObject.class); - } catch (JsonProcessingException e) { - throw new RuntimeException(); - } - } - private String getFormattedSql(String templateSql, String conceptSourceCode, String conceptNameDisplayFormat, String startDate, String endDate, String tempTableName) { ST sqlTemplate = new ST(templateSql, '#', '#'); @@ -153,13 +95,4 @@ private String getFormattedSql(String templateSql, String conceptSourceCode, Str } - public int getDefaultPageSize() { - String pageSize = System.getenv("REPORTS_TS_PAGE_SIZE"); - if (pageSize == null) pageSize = tsProperties.getProperty("ts.defaultPageSize"); - if (pageSize != null) { - return Integer.parseInt(pageSize); - } - return TS_DIAGNOSIS_LOOKUP_DEFAULT_PAGE_SIZE; - } - } diff --git a/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisLineReportTemplate.java b/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisLineReportTemplate.java new file mode 100644 index 00000000..23a9e052 --- /dev/null +++ b/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisLineReportTemplate.java @@ -0,0 +1,140 @@ +package org.bahmni.reports.template; + +import net.sf.dynamicreports.jasper.builder.JasperReportBuilder; +import net.sf.dynamicreports.report.constant.HorizontalAlignment; +import net.sf.dynamicreports.report.constant.PageType; +import net.sf.dynamicreports.report.constant.WhenNoDataType; +import net.sf.jasperreports.engine.data.JRMapCollectionDataSource; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bahmni.reports.extensions.ResultSetExtension; +import org.bahmni.reports.model.Report; +import org.bahmni.reports.model.TSIntegrationDiagnosisLineReportConfig; +import org.bahmni.reports.model.UsingDatasource; +import org.bahmni.reports.report.BahmniReportBuilder; +import org.bahmni.reports.util.CommonComponents; +import org.bahmni.reports.util.PatientAttributesHelper; +import org.bahmni.reports.util.SqlUtil; +import org.bahmni.webclients.HttpClient; +import org.quartz.impl.jdbcjobstore.InvalidConfigurationException; +import org.stringtemplate.v4.ST; + +import java.lang.reflect.Constructor; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +import static net.sf.dynamicreports.report.builder.DynamicReports.col; +import static net.sf.dynamicreports.report.builder.DynamicReports.type; +import static org.bahmni.reports.template.Templates.columnStyle; +import static org.bahmni.reports.util.FileReaderUtil.getFileContent; + + +@UsingDatasource("openmrs") +public class TSIntegrationDiagnosisLineReportTemplate extends BaseReportTemplate implements TSIntegrationDiagnosisService { + public static final String DIAGNOSIS_COLUMN_NAME = "Diagnosis"; + public static final String TERMINOLOGY_COLUMN_NAME = "Terminology Code"; + public static final String PATIENT_ID_COLUMN_NAME = "Patient Id"; + public static final String PATIENT_NAME_COLUMN_NAME = "Patient Name"; + public static final String PATIENT_DATE_OF_BIRTH_COLUMN_NAME = "Date of Birth"; + public static final String GENDER_COLUMN_NAME = "Gender"; + public static final String DATE_AND_TIME_COLUMN_NAME = "Date & Time of Diagnosis"; + public static final String SHORT_DISPLAY_FORMAT = "SHORT"; + public static final String FULLY_SPECIFIED_DISPLAY_FORMAT = "FULLY_SPECIFIED"; + private static final Logger logger = LogManager.getLogger(TSIntegrationDiagnosisLineReportTemplate.class); + private HttpClient httpClient; + private Properties tsProperties; + private String descendantsUrlTemplate; + + public TSIntegrationDiagnosisLineReportTemplate(HttpClient httpClient, Properties tsProperties, String descendantsUrlTemplate) { + super(); + this.httpClient = httpClient; + this.tsProperties = tsProperties; + this.descendantsUrlTemplate = descendantsUrlTemplate; + } + + public void setDescendantsUrlTemplate(String descendantsUrlTemplate) { + this.descendantsUrlTemplate = descendantsUrlTemplate; + } + + @Override + public BahmniReportBuilder build(Connection connection, JasperReportBuilder jasperReport, Report report, String startDate, String endDate, List resources, PageType pageType) throws SQLException, InvalidConfigurationException { + String tempTableName = "tmpCodes_" + System.nanoTime(); + loadTempTable(connection, tempTableName, report.getConfig().getTerminologyParentCode(), tsProperties, descendantsUrlTemplate, httpClient); + String sql = getFileContent("sql/tsIntegrationDiagnosisLineReport.sql"); + + CommonComponents.addTo(jasperReport, report, pageType); + jasperReport.addColumn(col.column(PATIENT_ID_COLUMN_NAME, PATIENT_ID_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + jasperReport.addColumn(col.column(PATIENT_NAME_COLUMN_NAME, PATIENT_NAME_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + jasperReport.addColumn(col.column(GENDER_COLUMN_NAME, GENDER_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + createAndAddPatientAttributeColumns(jasperReport, report.getConfig()); + createAndAddPatientAddressColumns(jasperReport, report.getConfig()); + jasperReport.addColumn(col.column(PATIENT_DATE_OF_BIRTH_COLUMN_NAME, PATIENT_DATE_OF_BIRTH_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + jasperReport.addColumn(col.column(DIAGNOSIS_COLUMN_NAME, DIAGNOSIS_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + if (report.getConfig().isDisplayTerminologyCode()) { + String terminologyConfigColumnName = report.getConfig().getTerminologyColumnName(); + String terminologyColumnName = StringUtils.isNotBlank(terminologyConfigColumnName) ? terminologyConfigColumnName : TERMINOLOGY_COLUMN_NAME; + jasperReport.addColumn(col.column(terminologyColumnName, TERMINOLOGY_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + } + jasperReport.addColumn(col.column(DATE_AND_TIME_COLUMN_NAME, DATE_AND_TIME_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + ResultSet resultSet = getResultSet(sql, report.getConfig().getTsConceptSource(), startDate, endDate, tempTableName, report.getConfig(), connection); + + List extensions = report.getConfig().getExtensions(); + if (extensions == null || extensions.isEmpty()) { + jasperReport.setDataSource(resultSet); + } else { + Collection> collection = convertResultSetToCollection(resultSet); + extensions.forEach(extensionClassStr -> enrichUsingReflection(extensionClassStr, collection, jasperReport)); + jasperReport.setDataSource(new JRMapCollectionDataSource(collection)); + } + jasperReport.setShowColumnTitle(true).setWhenNoDataType(WhenNoDataType.ALL_SECTIONS_NO_DETAIL); + return new BahmniReportBuilder(jasperReport); + } + + private void enrichUsingReflection(String extensionClassStr, Collection> collection, JasperReportBuilder jasperReport) { + try { + Class extensionClass = Class.forName(extensionClassStr); + Constructor constructor = extensionClass.getDeclaredConstructor(); + constructor.setAccessible(true); + ResultSetExtension extension = (ResultSetExtension) constructor.newInstance(); + extension.enrich(collection, jasperReport); + } catch (Exception e) { + logger.error(String.format("Error caused during reflection in enrichUsingReflection method: %s", e.getMessage())); + throw new RuntimeException(e); + } + } + + public List> convertResultSetToCollection(ResultSet resultSet) throws SQLException { + List> resulSetListOfMap = new ArrayList<>(); + if (resultSet != null) { + int columnCount = resultSet.getMetaData().getColumnCount(); + while (resultSet.next()) { + Map resulSetMap = new HashMap<>(); + for (int colNextIndex = 1; colNextIndex <= columnCount; colNextIndex++) { + resulSetMap.put(resultSet.getMetaData().getColumnLabel(colNextIndex), resultSet.getString(colNextIndex)); + } + resulSetListOfMap.add(resulSetMap); + } + } + return resulSetListOfMap; + } + + + private ResultSet getResultSet(String templateSql, String conceptSourceCode, String startDate, String endDate, String tempTableName, TSIntegrationDiagnosisLineReportConfig config, Connection connection) throws SQLException, InvalidConfigurationException { + ST sqlTemplate = new ST(templateSql, '#', '#'); + sqlTemplate.add("conceptSourceCode", conceptSourceCode); + sqlTemplate.add("startDate", startDate); + sqlTemplate.add("endDate", endDate); + sqlTemplate.add("tempTable", tempTableName); + PatientAttributesHelper patientAttributesHelper = new PatientAttributesHelper(config.getPatientAttributes()); + sqlTemplate.add("patientAttributesFromClause", patientAttributesHelper.getFromClause()); + sqlTemplate.add("patientAttributeSql", patientAttributesHelper.getSql()); + sqlTemplate.add("patientAddresses", constructPatientAddressesToDisplay(config)); + sqlTemplate.add("conceptNameDisplayFormat", "shortNamePreferred".equals(config.getConceptNameDisplayFormat()) ? SHORT_DISPLAY_FORMAT : FULLY_SPECIFIED_DISPLAY_FORMAT); + return SqlUtil.executeSqlWithStoredProc(connection, sqlTemplate.render()); + } + + +} diff --git a/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisService.java b/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisService.java new file mode 100644 index 00000000..9cc4afa3 --- /dev/null +++ b/src/main/java/org/bahmni/reports/template/TSIntegrationDiagnosisService.java @@ -0,0 +1,116 @@ +package org.bahmni.reports.template; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import net.sf.dynamicreports.jasper.builder.JasperReportBuilder; +import net.sf.dynamicreports.report.builder.column.TextColumnBuilder; +import net.sf.dynamicreports.report.constant.HorizontalAlignment; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bahmni.reports.model.TSIntegrationDiagnosisLineReportConfig; +import org.bahmni.reports.model.TSPageObject; +import org.bahmni.webclients.HttpClient; + +import java.io.IOException; +import java.net.URI; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import static net.sf.dynamicreports.report.builder.DynamicReports.col; +import static net.sf.dynamicreports.report.builder.DynamicReports.type; +import static org.bahmni.reports.template.Templates.columnStyle; + +public interface TSIntegrationDiagnosisService { + final static String CREATE_SQL_TEMPLATE = "create temporary table {0}(code varchar(100) not null)"; + final static String INSERT_SQL_TEMPLATE = "insert into {0} values (?)"; + final static int TS_DIAGNOSIS_LOOKUP_DEFAULT_PAGE_SIZE = 20; + Logger logger = LogManager.getLogger(TSIntegrationDiagnosisService.class); + + static List getPatientAttributes(TSIntegrationDiagnosisLineReportConfig config) { + return config.getPatientAttributes() != null ? config.getPatientAttributes() : new ArrayList<>(); + } + + static List getPatientAddresses(TSIntegrationDiagnosisLineReportConfig config) { + return config.getPatientAddresses() != null ? config.getPatientAddresses() : new ArrayList<>(); + } + + + default void loadTempTable(Connection connection, String tempTableName, String parentCode, Properties tsProperties, String descendantsUrlTemplate, HttpClient httpClient) { + int offset = 0; + int pageSize = getDefaultPageSize(tsProperties); + try { + String createSqlStmt = MessageFormat.format(CREATE_SQL_TEMPLATE, tempTableName); + String insertSqlStmt = MessageFormat.format(INSERT_SQL_TEMPLATE, tempTableName); + Statement statement = connection.createStatement(); + statement.execute(createSqlStmt); + try (PreparedStatement pstmtInsert = connection.prepareStatement(insertSqlStmt)) { + TSPageObject pageObject = null; + do { + pageObject = fetchDescendantsByPagination(parentCode, pageSize, offset, "en", httpClient, descendantsUrlTemplate); + List codes = pageObject.getCodes(); + for (int batchcount = 0; batchcount < codes.size(); batchcount++) { + pstmtInsert.setString(1, codes.get(batchcount)); + pstmtInsert.addBatch(); + } + pstmtInsert.executeBatch(); + offset += pageSize; + } while (offset < pageObject.getTotal()); + } + } catch (SQLException | IOException e) { + logger.error("Error occurred while making database call to " + tempTableName + " table"); + throw new RuntimeException(e); + } + } + + default TSPageObject fetchDescendantsByPagination(String terminologyCode, int pageSize, int offset, String localeLanguage, HttpClient httpClient, String descendantsUrlTemplate) throws IOException { + String url = MessageFormat.format(descendantsUrlTemplate, terminologyCode, pageSize, offset, localeLanguage); + String responseStr = httpClient.get(URI.create(url)); + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(responseStr, TSPageObject.class); + } catch (JsonProcessingException e) { + logger.error("Error occurred while converting response to page object in fetchDescendantsByPagination"); + throw new RuntimeException(e); + } + } + + default int getDefaultPageSize(Properties tsProperties) { + String pageSize = System.getenv("REPORTS_TS_PAGE_SIZE"); + if (pageSize == null) pageSize = tsProperties.getProperty("terminologyServer.defaultPageSize"); + if (pageSize != null) { + return Integer.parseInt(pageSize); + } + return TS_DIAGNOSIS_LOOKUP_DEFAULT_PAGE_SIZE; + } + + default void createAndAddPatientAddressColumns(JasperReportBuilder jasperReport, TSIntegrationDiagnosisLineReportConfig config) { + for (String address : getPatientAddresses(config)) { + TextColumnBuilder column = col.column(address, address, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER); + jasperReport.addColumn(column); + } + } + + default void createAndAddPatientAttributeColumns(JasperReportBuilder jasperReport, TSIntegrationDiagnosisLineReportConfig config) { + for (String patientAttribute : getPatientAttributes(config)) { + TextColumnBuilder column = col.column(patientAttribute, patientAttribute, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER); + jasperReport.addColumn(column); + } + } + + default String constructPatientAddressesToDisplay(TSIntegrationDiagnosisLineReportConfig config) { + List patientAddresses = getPatientAddresses(config); + StringBuilder stringBuilder = new StringBuilder(); + if (patientAddresses != null) { + for (String address : patientAddresses) { + stringBuilder.append("paddress").append(".").append(address).append(", "); + } + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/org/bahmni/reports/util/FileReaderUtil.java b/src/main/java/org/bahmni/reports/util/FileReaderUtil.java index b5fe4f11..e543b2ff 100644 --- a/src/main/java/org/bahmni/reports/util/FileReaderUtil.java +++ b/src/main/java/org/bahmni/reports/util/FileReaderUtil.java @@ -2,44 +2,27 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.bahmni.reports.template.Templates; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; +import java.util.stream.Collectors; public class FileReaderUtil { private static final Logger logger = LogManager.getLogger(FileReaderUtil.class); - public static String getFileContent(final String fileName) { - - BufferedReader br = null; + public static String getFileContent(String relativePath) { + Path path = null; try { - br = new BufferedReader(new InputStreamReader(Templates.class.getClassLoader().getResourceAsStream(fileName))); - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - - while (line != null) { - sb.append(line); - sb.append(System.lineSeparator()); - line = br.readLine(); - } - - return sb.toString(); - } catch (IOException e) { - logger.error("File {} not found {}", fileName, e); - } finally { - try { - br.close(); - } catch (Exception e) { - e.printStackTrace(); - } + path = Paths.get(FileReaderUtil.class.getClassLoader().getResource(relativePath).toURI()); + return Files.lines(path, StandardCharsets.UTF_8).collect(Collectors.joining("\n")); + } catch (IOException | URISyntaxException e) { + logger.error("Error reading file at location {} - {}", relativePath, e); + throw new RuntimeException(e); } - return null; - } public static String getFileContent(String filePath, boolean isAbsolutePath) { @@ -49,7 +32,7 @@ public static String getFileContent(String filePath, boolean isAbsolutePath) { try { return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8); } catch (IOException e) { - logger.error("File at location {} not found {}", filePath , e); + logger.error("File at location {} not found {}", filePath, e); } return null; } diff --git a/src/main/java/org/bahmni/reports/util/PropertyUtil.java b/src/main/java/org/bahmni/reports/util/PropertyUtil.java new file mode 100644 index 00000000..98301fec --- /dev/null +++ b/src/main/java/org/bahmni/reports/util/PropertyUtil.java @@ -0,0 +1,23 @@ +package org.bahmni.reports.util; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class PropertyUtil { + static Logger logger = LogManager.getLogger(PropertyUtil.class); + + public static Properties loadProperties(String propertiesFileName) { + try (InputStream in = PropertyUtil.class.getClassLoader().getResourceAsStream(propertiesFileName)) { + Properties p = new Properties(); + p.load(in); + return p; + } catch (IOException e) { + logger.error("Could not load properties from: " + propertiesFileName, e); + throw new RuntimeException(e); + } + } +} diff --git a/src/main/resources/sql/tsIntegrationDiagnosisCount.sql b/src/main/resources/sql/tsIntegrationDiagnosisCount.sql index 1e7cdcc2..5c5ae2cc 100644 --- a/src/main/resources/sql/tsIntegrationDiagnosisCount.sql +++ b/src/main/resources/sql/tsIntegrationDiagnosisCount.sql @@ -110,7 +110,7 @@ from from concept_reference_source where - name like '#conceptSourceCode#' + hl7_code like '#conceptSourceCode#' ) INNER JOIN #tempTable# tmp on tmp.code = crt.code group by diff --git a/src/main/resources/sql/tsIntegrationDiagnosisLineReport.sql b/src/main/resources/sql/tsIntegrationDiagnosisLineReport.sql new file mode 100644 index 00000000..c1dab5e7 --- /dev/null +++ b/src/main/resources/sql/tsIntegrationDiagnosisLineReport.sql @@ -0,0 +1,93 @@ +SET @sql = NULL; +SET @patientAttributesFromClause = '#patientAttributesFromClause#'; +SET @patientAddressesSql = '#patientAddresses#'; +SET @patientAddressJoinSql = ' LEFT OUTER JOIN person_address paddress ON p.person_id = paddress.person_id AND paddress.voided is false '; +SET @patientAttributeJoinSql = ' LEFT JOIN ( + #patientAttributeSql# + ) personattribute on personattribute.person_id = p.person_id '; + +SET @sql = CONCAT(' +SELECT + DISTINCT + IF(extraIdentifier.identifier IS NULL OR extraIdentifier.identifier = "", + primaryIdentifier.identifier, extraIdentifier.identifier) AS "Patient Id", + concat(pn.given_name, " ", ifnull(pn.family_name, "")) AS "Patient Name", + p.gender AS "Gender", ', + IF(@patientAttributesFromClause = '', '', CONCAT(@patientAttributesFromClause, ',')),' + ',IF(@patientAddressesSql = '', '', CONCAT(@patientAddressesSql, '')),' + ', + 'p.birthdate AS "Date of Birth", + cn.name AS "Diagnosis", + crt.code AS "Terminology Code", + DATE_FORMAT(CONVERT_TZ( + diagnosisObs.obs_datetime, + "+00:00", "+5:30" + ), "%d-%b-%Y %H:%i") AS "Date & Time of Diagnosis" +FROM patient pt + JOIN person p ON p.person_id = pt.patient_id AND p.voided is FALSE + JOIN person_name pn ON pn.person_id = p.person_id AND pn.voided is FALSE + JOIN (SELECT pri.patient_id, pri.identifier + FROM patient_identifier pri + JOIN patient_identifier_type pit ON pri.identifier_type = pit.patient_identifier_type_id AND pit.retired is FALSE + JOIN global_property gp ON gp.property="bahmni.primaryIdentifierType" AND INSTR (gp.property_value, pit.uuid)) primaryIdentifier + ON pt.patient_id = primaryIdentifier.patient_id + LEFT OUTER JOIN (SELECT ei.patient_id, ei.identifier + FROM patient_identifier ei + JOIN patient_identifier_type pit ON ei.identifier_type = pit.patient_identifier_type_id AND pit.retired is FALSE + JOIN global_property gp ON gp.property="bahmni.extratientIdentifierTypes" AND INSTR (gp.property_value, pit.uuid)) extraIdentifier + ON pt.patient_id = extraIdentifier.patient_id ',' + ',IF(@patientAttributesFromClause = '', '', @patientAttributeJoinSql),' + ',IF(@patientAddressesSql = '', '', @patientAddressJoinSql),' + JOIN (SELECT diagnosis.value_coded, diagnosis.person_id, + diagnosis.obs_datetime from obs AS diagnosis + JOIN concept_view AS cv + ON cv.concept_id = diagnosis.value_coded AND cv.concept_class_name = "Diagnosis" AND + cast(CONVERT_TZ( + diagnosis.obs_datetime, + "+00:00", "+5:30" + ) AS DATE) BETWEEN "#startDate#" AND "#endDate#" AND diagnosis.voided = 0 + AND diagnosis.obs_group_id IN ( + SELECT DISTINCT certaintyObs.obs_id from ( + SELECT DISTINCT parent.obs_id + FROM obs AS parent + JOIN concept_view pcv ON pcv.concept_id = parent.concept_id AND + pcv.concept_full_name = "Visit Diagnoses" + LEFT JOIN obs AS child + ON child.obs_group_id = parent.obs_id + AND child.voided IS FALSE + JOIN concept_name AS certainty + ON certainty.concept_id = child.value_coded AND + (certainty.name = "Confirmed" || certainty.name = "Presumed") AND + certainty.concept_name_type = "FULLY_SPECIFIED" + WHERE parent.voided IS FALSE) AS certaintyObs + ) + UNION + SELECT patient_conditions.condition_coded AS value_coded, + patient_conditions.patient_id AS person_id, + patient_conditions.date_created AS obs_datetime + FROM conditions patient_conditions + WHERE patient_conditions.clinical_status = "ACTIVE" + AND cast(CONVERT_TZ( + patient_conditions.date_created, + "+00:00", "+5:30" + ) AS DATE) BETWEEN "#startDate#" AND "#endDate#" AND voided = FALSE +) as diagnosisObs on diagnosisObs.person_id = p.person_id + JOIN concept_set cs on cs.concept_id = diagnosisObs.value_coded + JOIN concept_name cn on cn.concept_id = cs.concept_id AND diagnosisObs.value_coded + AND cn.concept_name_type = "#conceptNameDisplayFormat#" AND cn.locale = "en" AND cn.voided = false + INNER JOIN concept_reference_map crm on crm.concept_id = cn.concept_id + INNER JOIN concept_reference_term crt on crt.concept_reference_term_id = crm.concept_reference_term_id + AND crt.concept_source_id = ( + select + concept_source_id + from + concept_reference_source + where + hl7_code like "#conceptSourceCode#" + ) + INNER JOIN #tempTable# tmp on tmp.code = crt.code +ORDER BY diagnosisObs.obs_datetime DESC', ';'); + +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; \ No newline at end of file diff --git a/src/main/resources/terminology-service-config.properties b/src/main/resources/terminology-service-config.properties index c25a6540..b80abad2 100644 --- a/src/main/resources/terminology-service-config.properties +++ b/src/main/resources/terminology-service-config.properties @@ -1,2 +1,2 @@ -ts.defaultPageSize=10000 -ts.endpoint=/terminologyServices/searchTerminologyCodes?code={0}&size={1,number,#}&offset={2,number,#}&locale={3} \ No newline at end of file +terminologyServer.defaultPageSize=10000 +terminologyServer.endpoint=/terminologyServices/searchTerminologyCodes?code={0}&size={1,number,#}&offset={2,number,#}&locale={3} \ No newline at end of file diff --git a/src/test/java/org/bahmni/reports/extensions/sample/SampleResultSetExtension.java b/src/test/java/org/bahmni/reports/extensions/sample/SampleResultSetExtension.java new file mode 100644 index 00000000..60d9226f --- /dev/null +++ b/src/test/java/org/bahmni/reports/extensions/sample/SampleResultSetExtension.java @@ -0,0 +1,25 @@ +package org.bahmni.reports.extensions.sample; + +import net.sf.dynamicreports.jasper.builder.JasperReportBuilder; +import net.sf.dynamicreports.report.constant.HorizontalAlignment; +import org.bahmni.reports.extensions.ResultSetExtension; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.Map; +import java.util.Random; + +import static net.sf.dynamicreports.report.builder.DynamicReports.col; +import static net.sf.dynamicreports.report.builder.DynamicReports.type; +import static org.bahmni.reports.template.Templates.columnStyle; + +public class SampleResultSetExtension implements ResultSetExtension { + public static final String SAMPLE_COLUMN_NAME = "Sample Column"; + + public void enrich(Collection> collection, JasperReportBuilder jasperReport) throws SQLException { + for (Map rowMap : collection) { + enrichRow(rowMap, SAMPLE_COLUMN_NAME, String.valueOf(new Random().nextInt())); + } + jasperReport.addColumn(col.column(SAMPLE_COLUMN_NAME, SAMPLE_COLUMN_NAME, type.stringType()).setStyle(columnStyle).setHorizontalAlignment(HorizontalAlignment.CENTER)); + } +} \ No newline at end of file diff --git a/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisReportTest.java b/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisCountReportTest.java similarity index 73% rename from src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisReportTest.java rename to src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisCountReportTest.java index cb756fa5..a206c48d 100644 --- a/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisReportTest.java +++ b/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisCountReportTest.java @@ -4,8 +4,9 @@ import net.sf.dynamicreports.report.constant.PageType; import org.bahmni.reports.BahmniReportsProperties; import org.bahmni.reports.model.Report; -import org.bahmni.reports.model.TSIntegrationDiagnosisReportConfig; -import org.bahmni.reports.template.TSIntegrationDiagnosisReportTemplate; +import org.bahmni.reports.model.TSIntegrationDiagnosisCountReportConfig; +import org.bahmni.reports.template.TSIntegrationDiagnosisCountReportTemplate; +import org.bahmni.reports.util.FileReaderUtil; import org.bahmni.webclients.HttpClient; import org.junit.Before; import org.junit.Test; @@ -16,31 +17,23 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.modules.junit4.PowerMockRunner; -import java.io.IOException; import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Statement; import java.util.Properties; -import java.util.stream.Collectors; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import static org.mockito.Mockito.verify; @PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"}) @RunWith(PowerMockRunner.class) -public class TSIntegrationDiagnosisReportTest { +public class TSIntegrationDiagnosisCountReportTest { @InjectMocks - TSIntegrationDiagnosisReportTemplate tsIntegrationDiagnosisReportTemplate; + TSIntegrationDiagnosisCountReportTemplate tsIntegrationDiagnosisCountReportTemplate; @Mock - Report mockReport; + Report mockReport; @Mock private HttpClient mockHttpClient; @Mock @@ -58,15 +51,15 @@ public class TSIntegrationDiagnosisReportTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - tsIntegrationDiagnosisReportTemplate.setDescendantsUrlTemplate("dummyUrlTemplate"); + tsIntegrationDiagnosisCountReportTemplate.setDescendantsUrlTemplate("dummyUrlTemplate"); } @Test - public void shouldFetchTSDiagnosisReportTemplateWhenTSDiagnosisReportTypeIsInvoked() { - TSIntegrationDiagnosisReportConfig tsIntegrationDiagnosisReportConfig = new TSIntegrationDiagnosisReportConfig(); - TSIntegrationDiagnosisReport tsIntegrationDiagnosisReport = new TSIntegrationDiagnosisReport(); - tsIntegrationDiagnosisReport.setConfig(tsIntegrationDiagnosisReportConfig); - assertTrue(tsIntegrationDiagnosisReport.getTemplate(new BahmniReportsProperties()).getClass().isAssignableFrom(TSIntegrationDiagnosisReportTemplate.class)); + public void shouldFetchTSDiagnosisCountReportTemplateWhenTSDiagnosisCountReportTypeIsInvoked() { + TSIntegrationDiagnosisCountReportConfig tsIntegrationDiagnosisCountReportConfig = new TSIntegrationDiagnosisCountReportConfig(); + TSIntegrationDiagnosisCountReport tsIntegrationDiagnosisCountReport = new TSIntegrationDiagnosisCountReport(); + tsIntegrationDiagnosisCountReport.setConfig(tsIntegrationDiagnosisCountReportConfig); + assertTrue(tsIntegrationDiagnosisCountReport.getTemplate(new BahmniReportsProperties()).getClass().isAssignableFrom(TSIntegrationDiagnosisCountReportTemplate.class)); } @Test @@ -76,7 +69,7 @@ public void shouldProcessTerminologyDescendantsWithPagination() throws Exception when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(true, true, false)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(true, true, false)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -88,7 +81,7 @@ public void shouldProcessTerminologyDescendantsWithPagination() throws Exception when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); //Two Descendant Codes verify(mockPreparedStatement, times(2)).setString(eq(1), anyString()); @@ -104,7 +97,7 @@ public void shouldIncludeBothTerminologyCodeAndGenderGroupColumnsInJasperReport( when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(true, true, false)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(true, true, false)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -116,7 +109,7 @@ public void shouldIncludeBothTerminologyCodeAndGenderGroupColumnsInJasperReport( when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); verify(mockJasperReport, times(7)).addColumn(any()); } @@ -128,7 +121,7 @@ public void shouldIncludeTerminologyCodeAndExcludeGenderGroupColumnsInJasperRepo when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(true, false, false)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(true, false, false)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -140,7 +133,7 @@ public void shouldIncludeTerminologyCodeAndExcludeGenderGroupColumnsInJasperRepo when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); verify(mockJasperReport, times(3)).addColumn(any()); } @@ -152,7 +145,7 @@ public void shouldExcludeTerminologyCodeAndIncludeGenderGroupColumnsInJasperRepo when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(false, true, false)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(false, true, false)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -164,7 +157,7 @@ public void shouldExcludeTerminologyCodeAndIncludeGenderGroupColumnsInJasperRepo when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); verify(mockJasperReport, times(6)).addColumn(any()); } @@ -176,7 +169,7 @@ public void shouldExcludeBothTerminologyCodeAndGenderGroupColumnsInJasperReport( when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(false, false, false)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(false, false, false)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -188,7 +181,7 @@ public void shouldExcludeBothTerminologyCodeAndGenderGroupColumnsInJasperReport( when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); verify(mockJasperReport, times(2)).addColumn(any()); } @@ -200,7 +193,7 @@ public void shouldDisplayShortWhenConceptNameDisplayFormatEqualsShortNamePreferr when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(false, false, true)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(false, false, true)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -212,7 +205,7 @@ public void shouldDisplayShortWhenConceptNameDisplayFormatEqualsShortNamePreferr when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); verify(mockJasperReport, times(1)).setDataSource(contains("AND cn.concept_name_type = 'SHORT'"), any()); } @@ -223,7 +216,7 @@ public void shouldDisplayFullySpecifiedWhenConceptNameDisplayFormatNotEqualsShor when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockReport.getName()).thenReturn("dummyReport"); - when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisReportConfig(false, false, false)); + when(mockReport.getConfig()).thenReturn(getMockTerminologyDiagnosisCountReportConfig(false, false, false)); when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); @@ -235,27 +228,22 @@ public void shouldDisplayFullySpecifiedWhenConceptNameDisplayFormatNotEqualsShor when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); - tsIntegrationDiagnosisReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + tsIntegrationDiagnosisCountReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); verify(mockJasperReport, times(1)).setDataSource(contains("AND cn.concept_name_type = 'FULLY_SPECIFIED'"), any()); } - private TSIntegrationDiagnosisReportConfig getMockTerminologyDiagnosisReportConfig(boolean displayTerminologyCodeFlag, boolean displayGenderFlag, boolean shortNamePreferredFlag) { - TSIntegrationDiagnosisReportConfig tsIntegrationDiagnosisReportConfig = new TSIntegrationDiagnosisReportConfig(); - tsIntegrationDiagnosisReportConfig.setDisplayTerminologyCode(displayTerminologyCodeFlag); - tsIntegrationDiagnosisReportConfig.setDisplayGenderGroup(displayGenderFlag); - tsIntegrationDiagnosisReportConfig.setTerminologyParentCode("dummyCode"); + private TSIntegrationDiagnosisCountReportConfig getMockTerminologyDiagnosisCountReportConfig(boolean displayTerminologyCodeFlag, boolean displayGenderFlag, boolean shortNamePreferredFlag) { + TSIntegrationDiagnosisCountReportConfig tsIntegrationDiagnosisCountReportConfig = new TSIntegrationDiagnosisCountReportConfig(); + tsIntegrationDiagnosisCountReportConfig.setDisplayTerminologyCode(displayTerminologyCodeFlag); + tsIntegrationDiagnosisCountReportConfig.setDisplayGenderGroup(displayGenderFlag); + tsIntegrationDiagnosisCountReportConfig.setTerminologyParentCode("dummyCode"); if (shortNamePreferredFlag) - tsIntegrationDiagnosisReportConfig.setConceptNameDisplayFormat("shortNamePreferred"); - return tsIntegrationDiagnosisReportConfig; + tsIntegrationDiagnosisCountReportConfig.setConceptNameDisplayFormat("shortNamePreferred"); + return tsIntegrationDiagnosisCountReportConfig; } - private String getMockTerminologyDescendants() throws URISyntaxException, IOException { - return readFileAsStr("ts/descendantCodes.json"); + private String getMockTerminologyDescendants() { + return FileReaderUtil.getFileContent("terminologyServices/descendantCodes.json"); } - private String readFileAsStr(String relativePath) throws URISyntaxException, IOException { - Path path = Paths.get(getClass().getClassLoader() - .getResource(relativePath).toURI()); - return Files.lines(path, StandardCharsets.UTF_8).collect(Collectors.joining("\n")); - } } \ No newline at end of file diff --git a/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisLineReportTest.java b/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisLineReportTest.java new file mode 100644 index 00000000..d8252735 --- /dev/null +++ b/src/test/java/org/bahmni/reports/report/TSIntegrationDiagnosisLineReportTest.java @@ -0,0 +1,295 @@ +package org.bahmni.reports.report; + +import net.sf.dynamicreports.jasper.builder.JasperReportBuilder; +import net.sf.dynamicreports.report.constant.PageType; +import org.bahmni.reports.BahmniReportsProperties; +import org.bahmni.reports.model.Report; +import org.bahmni.reports.model.TSIntegrationDiagnosisLineReportConfig; +import org.bahmni.reports.template.TSIntegrationDiagnosisLineReportTemplate; +import org.bahmni.reports.util.FileReaderUtil; +import org.bahmni.reports.util.SqlUtil; +import org.bahmni.webclients.HttpClient; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.net.URI; +import java.sql.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.verifyStatic; + +@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*", "javax.script.*"}) +@RunWith(PowerMockRunner.class) +@PrepareForTest(SqlUtil.class) +public class TSIntegrationDiagnosisLineReportTest { + + @InjectMocks + TSIntegrationDiagnosisLineReportTemplate tsIntegrationDiagnosisLineReportTemplate; + @Mock + Report mockReport; + @Mock + private HttpClient mockHttpClient; + @Mock + private Connection mockConnection; + @Mock + private Statement mockStatement; + @Mock + private PreparedStatement mockPreparedStatement; + @Mock + private JasperReportBuilder mockJasperReport; + + @Mock + private ResultSet mockResultSet; + + @Mock + private ResultSetMetaData mockResultSetMetaData; + + @Mock + private Properties mockTsProperties; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + PowerMockito.mockStatic(SqlUtil.class); + tsIntegrationDiagnosisLineReportTemplate.setDescendantsUrlTemplate("dummyUrlTemplate"); + } + + @Test + public void shouldFetchTSDiagnosisLineReportTemplateWhenTSDiagnosisLineReportTypeIsInvoked() { + TSIntegrationDiagnosisLineReportConfig tsIntegrationDiagnosisLineReportConfig = new TSIntegrationDiagnosisLineReportConfig(); + TSIntegrationDiagnosisLineReport tsIntegrationDiagnosisLineReport = new TSIntegrationDiagnosisLineReport(); + tsIntegrationDiagnosisLineReport.setConfig(tsIntegrationDiagnosisLineReportConfig); + assertTrue(tsIntegrationDiagnosisLineReport.getTemplate(new BahmniReportsProperties()).getClass().isAssignableFrom(TSIntegrationDiagnosisLineReportTemplate.class)); + } + + @Test + public void shouldIncludeTerminologyCodeColumnInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(true, false, false); + when(mockReport.getConfig()).thenReturn(addPatientAttributesToConfig(reportConfig, true)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource(anyString(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + + verify(mockJasperReport, times(7)).addColumn(any()); + } + + @Test + public void shouldExcludeTerminologyCodeColumnInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(false, false, false); + when(mockReport.getConfig()).thenReturn(addPatientAttributesToConfig(reportConfig, true)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource(anyString(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + + verify(mockJasperReport, times(6)).addColumn(any()); + } + + @Test + public void shouldIncludePatientAttributeColumnsInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(false, false, false); + when(mockReport.getConfig()).thenReturn(addPatientAttributesToConfig(reportConfig, false)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource((ResultSet) any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + + verify(mockJasperReport, times(9)).addColumn(any()); + } + + @Test + public void shouldIncludePatientAddressColumnsInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(false, false, false); + addPatientAttributesToConfig(reportConfig, true); + when(mockReport.getConfig()).thenReturn(addPatientAddressesToConfig(reportConfig)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource(anyString(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + + verify(mockJasperReport, times(8)).addColumn(any()); + } + + @Test + public void shouldDisplayShortWhenConceptNameDisplayFormatEqualsShortNamePreferredInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(false, true, false); + addPatientAttributesToConfig(reportConfig, true); + when(mockReport.getConfig()).thenReturn(addPatientAddressesToConfig(reportConfig)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource(anyString(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + verifyStatic(SqlUtil.class, times(1)); + SqlUtil.executeSqlWithStoredProc(any(), contains("AND cn.concept_name_type = \"SHORT\" AND cn.locale = \"en\" AND cn.voided = false")); + } + + @Test + public void shouldDisplayFullySpecifiedWhenConceptNameDisplayFormatNotEqualsShortNamePreferredInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(false, false, false); + addPatientAttributesToConfig(reportConfig, true); + when(mockReport.getConfig()).thenReturn(addPatientAddressesToConfig(reportConfig)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource(anyString(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + verifyStatic(SqlUtil.class, times(1)); + SqlUtil.executeSqlWithStoredProc(any(), contains("AND cn.concept_name_type = \"FULLY_SPECIFIED\" AND cn.locale = \"en\" AND cn.voided = false")); + } + + @Test + public void shouldIncludeIcd10TerminologyCodeColumnInJasperReport() throws Exception { + when(mockTsProperties.getProperty("ts.defaultPageSize")).thenReturn("10000"); + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + + when(mockReport.getName()).thenReturn("dummyReport"); + TSIntegrationDiagnosisLineReportConfig reportConfig = getMockTerminologyDiagnosisLineReportConfig(true, false, true); + when(mockReport.getConfig()).thenReturn(addPatientAttributesToConfig(reportConfig, true)); + + when(mockJasperReport.setPageFormat(any(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.setReportName(anyString())).thenReturn(mockJasperReport); + when(mockJasperReport.setTemplate(any())).thenReturn(mockJasperReport); + when(mockJasperReport.setShowColumnTitle(anyBoolean())).thenReturn(mockJasperReport); + when(mockJasperReport.setWhenNoDataType(any())).thenReturn(mockJasperReport); + when(SqlUtil.executeSqlWithStoredProc(any(), anyString())).thenReturn(mockResultSet); + when(mockJasperReport.setDataSource(anyString(), any())).thenReturn(mockJasperReport); + when(mockJasperReport.subtotalsAtSummary(any())).thenReturn(mockJasperReport); + + when(mockHttpClient.get(any(URI.class))).thenReturn(getMockTerminologyDescendants()); + + when(mockResultSet.getMetaData()).thenReturn(mockResultSetMetaData); + when(mockResultSetMetaData.getColumnCount()).thenReturn(-1); + when(mockResultSet.next()).thenReturn(false); + + tsIntegrationDiagnosisLineReportTemplate.build(mockConnection, mockJasperReport, mockReport, "dummyStartDate", "dummyEndDate", null, PageType.A4); + + verify(mockJasperReport, times(8)).addColumn(any()); + } + + private TSIntegrationDiagnosisLineReportConfig getMockTerminologyDiagnosisLineReportConfig(boolean displayTerminologyCodeFlag, boolean shortNamePreferredFlag, boolean icd10ExtensionFlag) { + TSIntegrationDiagnosisLineReportConfig tsIntegrationDiagnosisLineReportConfig = new TSIntegrationDiagnosisLineReportConfig(); + tsIntegrationDiagnosisLineReportConfig.setDisplayTerminologyCode(displayTerminologyCodeFlag); + tsIntegrationDiagnosisLineReportConfig.setTerminologyParentCode("dummyCode"); + if (shortNamePreferredFlag) + tsIntegrationDiagnosisLineReportConfig.setConceptNameDisplayFormat("shortNamePreferred"); + if (icd10ExtensionFlag) + tsIntegrationDiagnosisLineReportConfig.setExtensions(Arrays.asList("org.bahmni.reports.extensions.sample.SampleResultSetExtension")); + return tsIntegrationDiagnosisLineReportConfig; + } + + private TSIntegrationDiagnosisLineReportConfig addPatientAttributesToConfig(TSIntegrationDiagnosisLineReportConfig tsIntegrationDiagnosisLineReportConfig, boolean isEmpty) { + List patientAttributeList = isEmpty ? new ArrayList<>() : Arrays.asList("education", "primaryContact", "secondaryContact"); + tsIntegrationDiagnosisLineReportConfig.setPatientAttributes(patientAttributeList); + return tsIntegrationDiagnosisLineReportConfig; + } + + private TSIntegrationDiagnosisLineReportConfig addPatientAddressesToConfig(TSIntegrationDiagnosisLineReportConfig tsIntegrationDiagnosisLineReportConfig) { + List patientAddressesList = Arrays.asList("city_village", "address3"); + tsIntegrationDiagnosisLineReportConfig.setPatientAddresses(patientAddressesList); + return tsIntegrationDiagnosisLineReportConfig; + } + + private String getMockTerminologyDescendants() { + return FileReaderUtil.getFileContent("terminologyServices/descendantCodes.json"); + } + +} \ No newline at end of file diff --git a/src/test/resources/ts/descendantCodes.json b/src/test/resources/terminologyServices/descendantCodes.json similarity index 100% rename from src/test/resources/ts/descendantCodes.json rename to src/test/resources/terminologyServices/descendantCodes.json