/* * Electronic Logistics Management Information System (eLMIS) is a supply chain management system for health commodities in a developing country setting. * * Copyright (C) 2015 John Snow, Inc (JSI). This program was produced for the U.S. Agency for International Development (USAID). It was prepared under the USAID | DELIVER PROJECT, Task Order 4. * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.openlmis.ivdform.view.xml; import org.exolab.castor.types.DateTime; import org.openlmis.core.domain.Facility; import org.openlmis.core.domain.GeographicZone; import org.openlmis.core.domain.ProcessingPeriod; import org.openlmis.core.domain.User; import org.openlmis.demographics.domain.AnnualFacilityEstimateEntry; import org.openlmis.equipment.domain.EquipmentOperationalStatus; import org.openlmis.ivdform.domain.DiscardingReason; import org.openlmis.ivdform.domain.Manufacturer; import org.openlmis.ivdform.domain.reports.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; import org.springframework.web.servlet.view.AbstractView; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.SAXException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @Component("ivdFormInputTool") public class IvdFormView extends AbstractView { private static final String PERIODS = "periods"; private static final String DISTRICTS = "districts"; private static final String FACILITIES = "facilities"; private static Logger logger = LoggerFactory.getLogger(IvdFormView.class); Document doc; public IvdFormView(){ setContentType("application/octet-stream"); } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // read template doc = readTemplate(); Element rootNode = doc.getDocumentElement(); Node data = rootNode.getElementsByTagName("xfa:data").item(0); Element report = doc.createElement("ivdReport"); writeDetails(report, (Long)model.get("program_id"), model.get("url").toString(), model.get("year").toString(), (User) model.get("user") ); VaccineReport vaccineReportTemplate = (VaccineReport) model.get("reportTemplate"); writePeriods(report, (List<ProcessingPeriod>) model.get(PERIODS)); writeRegions(report, (List<GeographicZone>) model.get(DISTRICTS)); writeFacilities(report, (List<Facility>) model.get(FACILITIES)); writeProducts(report, vaccineReportTemplate); writeStockStatus(report, vaccineReportTemplate); writeVaccinations(report, vaccineReportTemplate); writeDiseases(report, vaccineReportTemplate); writeSupplements(report, vaccineReportTemplate); writeManufacturers(report, (List< Manufacturer>) model.get("manufacturers") ); writeAdjustmentReasons(report, (List<DiscardingReason>) model.get("adjustment_reasons") ); writeOperationalStatuses(report, (List<EquipmentOperationalStatus>) model.get("operational_status") ); //writeFacilityDetails(report, (List<VaccineReport>)model.get("facility_details")); writeDemographicEstimates(report, (List<VaccineReport>)model.get("facility_details")); writeEquipments(report, (List<VaccineReport>)model.get("facility_details")); data.appendChild(report); response.setHeader("Content-Transfer-Encoding", "binary"); response.setHeader("Content-Disposition","attachment; filename=\"" + "ivd-reporting-form.xdp\""); writeResponse(response, doc); } private void createElement(Element parent, String name, String value){ Element childElement = doc.createElement(name); childElement.setTextContent(value); parent.appendChild(childElement); } private void writeResponse(HttpServletResponse response, Document doc) throws IOException, TransformerException { TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "no"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(response.getWriter()); try { transformer.transform(source, result); }catch (javax.xml.transform.TransformerException exp){ logger.warn("Transformer Warning: ", exp); } } private Document readTemplate() throws IOException, ParserConfigurationException, SAXException { Resource resource = new ClassPathResource("form_template.xml"); InputStream stream = resource.getInputStream(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); return dBuilder.parse(stream); } private void writeDetails(Element report, Long programId, String url, String year, User user){ Element detailsElement = doc.createElement("details"); createElement(detailsElement, "programId", programId.toString()); createElement(detailsElement, "baseUrl", url); createElement(detailsElement, "url", String.format("%s/rest-api/ivd-from/pdf-submit", url)); createElement(detailsElement, "generatedDate", new DateTime().toDate().toString()); createElement(detailsElement, "year", year); createElement(detailsElement, "username", user.getUserName()); createElement(detailsElement, "userFirstName", user.getFirstName()); createElement(detailsElement, "userLastName", user.getLastName()); report.appendChild(detailsElement); } private void writePeriods(Element report, List<ProcessingPeriod> periods){ Element periodsElement = doc.createElement("periods"); Collections.sort(periods, Comparator.comparing(ProcessingPeriod::getStartDate)); for(ProcessingPeriod period: periods){ Element processingPeriodElement = doc.createElement("period"); createElement(processingPeriodElement, "periodId", period.getId().toString()); createElement(processingPeriodElement, "periodName", period.getName()); periodsElement.appendChild(processingPeriodElement); } report.appendChild(periodsElement); } private void writeRegions(Element report, List<GeographicZone> zones){ Element periodsElement = doc.createElement("regions"); for(GeographicZone zone: zones){ Element regionElement = doc.createElement("region"); createElement(regionElement, "regionId", zone.getId().toString() ); createElement(regionElement, "regionName", zone.getName() ); periodsElement.appendChild(regionElement); } report.appendChild(periodsElement); } private void writeFacilities(Element report, List<Facility> facilities){ Element periodsElement = doc.createElement("facilities"); for(Facility facility: facilities){ Element facilityElement = doc.createElement("facility"); createElement(facilityElement, "regionId", facility.getGeographicZone().getId().toString() ); createElement(facilityElement, "facilityId", facility.getId().toString() ); createElement(facilityElement, "facilityName", facility.getName() ); periodsElement.appendChild(facilityElement); } report.appendChild(periodsElement); } private void writeEquipments(Element report, List<VaccineReport> reports){ Element equipmentRoot = doc.createElement("equipments"); for(VaccineReport reportT: reports){ for(ColdChainLineItem li : reportT.getColdChainLineItems()){ Element equipment = doc.createElement("equipment"); createElement(equipment, "facilityId", reportT.getFacility().getId().toString()); createElement(equipment, "equipmentInventoryId", li.getEquipmentInventoryId().toString()); createElement(equipment, "energySource", li.getEnergySource()); createElement(equipment, "equipmentName", li.getEquipmentName()); createElement(equipment, "model", li.getModel()); createElement(equipment, "serial", (li.getSerial() == null) ? "-": li.getSerial()); equipmentRoot.appendChild(equipment); } } report.appendChild(equipmentRoot); } private void writeDemographicEstimates(Element report, List<VaccineReport> reports){ Element demographicEstimatesRoot = doc.createElement("demographics"); for(VaccineReport reportT: reports){ for(AnnualFacilityEstimateEntry entry: reportT.getFacilityDemographicEstimates()){ Element estimate = doc.createElement("estimate"); createElement(estimate, "facilityId", reportT.getFacility().getId().toString() ); createElement(estimate, "estimateName", entry.getCategory().getName()); createElement(estimate, "estimateValue", entry.getValue().toString()); demographicEstimatesRoot.appendChild(estimate); } } report.appendChild(demographicEstimatesRoot); } private void writeFacilityDetails(Element report, List<VaccineReport> reports){ Element periodsElement = doc.createElement("facilityDetails"); for(VaccineReport reportT: reports){ Element facilityElement = doc.createElement("facility"); createElement(facilityElement, "facilityId", reportT.getFacility().getId().toString() ); createElement(facilityElement, "facilityName", reportT.getFacility().getName()); Element demographics = doc.createElement("demographics"); facilityElement.appendChild(demographics); for(AnnualFacilityEstimateEntry entry: reportT.getFacilityDemographicEstimates()){ Element estimate = doc.createElement("estimate"); createElement(estimate, "id", entry.getDemographicEstimateId().toString()); createElement(estimate, "name", entry.getCategory().getName()); createElement(estimate, "value", entry.getValue().toString()); demographics.appendChild(estimate); } Element equipments = doc.createElement("equipments"); facilityElement.appendChild(equipments); for(ColdChainLineItem li : reportT.getColdChainLineItems()){ Element equipment = doc.createElement("equipment"); createElement(equipment, "equipmentInventoryId", li.getEquipmentInventoryId().toString()); createElement(equipment, "energySource", li.getEnergySource()); createElement(equipment, "equipmentName", li.getEquipmentName()); createElement(equipment, "model", li.getModel()); createElement(equipment, "serial", li.getSerial()); equipments.appendChild(equipment); } facilityElement.appendChild(equipments); periodsElement.appendChild(facilityElement); } report.appendChild(periodsElement); } private void writeProducts(Element report, VaccineReport template) { Element productsElement = doc.createElement("products"); for (LogisticsLineItem li : template.getLogisticsLineItems()) { Element productElement = doc.createElement("product"); createElement(productElement, "productId", li.getProductId().toString()); createElement(productElement, "productName", li.getProductName()); productsElement.appendChild(productElement); } report.appendChild(productsElement); } private void writeVaccinations(Element report, VaccineReport template) { Element productsElement = doc.createElement("vaccinations"); Integer displayOrder = 1; for (VaccineCoverageItem li : template.getCoverageLineItems()) { Element productElement = doc.createElement("vaccine"); createElement(productElement, "productId", li.getProductId().toString()); createElement(productElement, "productName", li.getProductName()); createElement(productElement, "doseId", li.getDoseId().toString()); createElement(productElement, "doseName", li.getDisplayName()); createElement(productElement, "displayOrder", displayOrder.toString()); createElement(productElement, "trackMale", li.getTrackMale().toString()); createElement(productElement, "trackFemale", li.getTrackFemale().toString()); displayOrder ++; productsElement.appendChild(productElement); } report.appendChild(productsElement); } private void writeStockStatus(Element report, VaccineReport template) { Element stockStatus = doc.createElement("stockStatus"); Element productsElement = doc.createElement("products"); for (LogisticsLineItem li : template.getLogisticsLineItems()) { Element productElement = doc.createElement("product"); createElement(productElement, "productId", li.getProductId().toString()); createElement(productElement, "productName", li.getProductName()); createElement(productElement, "productCode", li.getProductCode()); createElement(productElement, "productCategory", li.getProductCategory()); createElement(productElement, "displayOrder", li.getDisplayOrder().toString()); createElement(productElement, "unit", li.getDosageUnit()); productsElement.appendChild(productElement); } stockStatus.appendChild(productsElement); report.appendChild(stockStatus); } private void writeDiseases(Element report, VaccineReport template) { Element diseasesElement = doc.createElement("diseases"); for (DiseaseLineItem li : template.getDiseaseLineItems()) { Element diseaseElement = doc.createElement("disease"); createElement(diseaseElement, "diseaseId", li.getDiseaseId().toString()); createElement(diseaseElement, "diseaseName", li.getDiseaseName()); createElement(diseaseElement, "displayOrder", li.getDisplayOrder().toString()); diseasesElement.appendChild(diseaseElement); } report.appendChild(diseasesElement); } private void writeSupplements(Element report, VaccineReport template) { Element supplementsElement = doc.createElement("supplements"); for (VitaminSupplementationLineItem li : template.getVitaminSupplementationLineItems()) { Element supplementElement = doc.createElement("supplement"); createElement(supplementElement, "vitaminId", li.getVaccineVitaminId().toString()); createElement(supplementElement, "vitaminName", li.getVitaminName()); createElement(supplementElement, "ageGroupId", li.getVitaminAgeGroupId().toString()); createElement(supplementElement, "ageGroupName", li.getAgeGroup()); createElement(supplementElement, "displayOrder", li.getDisplayOrder().toString()); supplementsElement.appendChild(supplementElement); } report.appendChild(supplementsElement); } private void writeManufacturers(Element report, List<Manufacturer> manufacturers) { Element manufacturersElement = doc.createElement("manufacturers"); for (Manufacturer manufacturer : manufacturers) { Element manufacturerElement = doc.createElement("manufacturer"); createElement(manufacturerElement, "manufacturerId", manufacturer.getId().toString()); createElement(manufacturerElement, "manufacturerName", manufacturer.getName()); manufacturersElement.appendChild(manufacturerElement); } report.appendChild(manufacturersElement); } private void writeAdjustmentReasons(Element report, List<DiscardingReason> reasons) { Element reasonsElement = doc.createElement("adjustmentReasons"); for (DiscardingReason reason : reasons) { Element reasonElement = doc.createElement("reason"); createElement(reasonElement, "reasonId", reason.getId().toString()); createElement(reasonElement, "reasonName", reason.getName()); reasonsElement.appendChild(reasonElement); } report.appendChild(reasonsElement); } private void writeOperationalStatuses(Element report, List<EquipmentOperationalStatus> equipmentOperationalStatuses) { Element reasonsElement = doc.createElement("coldChainOperationalStatuses"); for (EquipmentOperationalStatus status : equipmentOperationalStatuses) { Element statusElement = doc.createElement("status"); createElement(statusElement, "statusId", status.getId().toString()); createElement(statusElement, "statusName", status.getName()); reasonsElement.appendChild(statusElement); } report.appendChild(reasonsElement); } }