/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module.reporting.report.renderer;
import org.openmrs.Cohort;
import org.openmrs.annotation.Handler;
import org.openmrs.api.context.Context;
import org.openmrs.module.reporting.common.ExcelBuilder;
import org.openmrs.module.reporting.common.Localized;
import org.openmrs.module.reporting.common.ObjectUtil;
import org.openmrs.module.reporting.dataset.DataSet;
import org.openmrs.module.reporting.dataset.DataSetColumn;
import org.openmrs.module.reporting.dataset.DataSetRow;
import org.openmrs.module.reporting.dataset.MapDataSet;
import org.openmrs.module.reporting.dataset.definition.DataSetDefinition;
import org.openmrs.module.reporting.dataset.definition.service.DataSetDefinitionService;
import org.openmrs.module.reporting.evaluation.EvaluationContext;
import org.openmrs.module.reporting.evaluation.EvaluationException;
import org.openmrs.module.reporting.evaluation.parameter.Mapped;
import org.openmrs.module.reporting.evaluation.parameter.Parameter;
import org.openmrs.module.reporting.indicator.dimension.CohortIndicatorAndDimensionResult;
import org.openmrs.module.reporting.report.ReportData;
import org.openmrs.module.reporting.report.ReportDesign;
import org.openmrs.module.reporting.report.ReportDesignResource;
import org.openmrs.module.reporting.report.ReportRequest;
import org.openmrs.module.reporting.report.definition.ReportDefinition;
import org.openmrs.module.reporting.report.service.ReportService;
import org.openmrs.module.reporting.serializer.ReportingSerializer;
import org.openmrs.serialization.SerializationException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Supports rendering a series of Cohorts with particular datasets
*/
@Handler
@Localized("reporting.CohortDetailReportRenderer")
public class CohortDetailReportRenderer extends ReportDesignRenderer {
/**
* @see ReportRenderer#getRenderedContentType(org.openmrs.module.reporting.report.ReportRequest)
* @param request
*/
public String getRenderedContentType(ReportRequest request) {
if ("excel".equalsIgnoreCase(request.getRenderingMode().getArgument())) {
return "application/vnd.ms-excel";
}
return "text/html";
}
@Override
public String getFilename(ReportRequest request) {
String argument = request.getRenderingMode().getArgument();
String[] split = argument.split(":");
return getFilenameBase(request) + "." + split[1];
}
/**
* @see ReportRenderer#getRenderingModes(ReportDefinition)
*/
public Collection<RenderingMode> getRenderingModes(ReportDefinition definition) {
List<RenderingMode> ret = new ArrayList<RenderingMode>();
int index = 100;
List<ReportDesign> designs = Context.getService(ReportService.class).getReportDesigns(definition, getClass(), false);
for (ReportDesign d : designs) {
ret.add(new RenderingMode(this, d.getName() + " (html)", d.getUuid() + ":html", index++));
ret.add(new RenderingMode(this, d.getName() + " (xls)", d.getUuid() + ":xls", index++));
}
return ret;
}
/**
* @see ReportRenderer#render(org.openmrs.module.reporting.report.ReportData, String, java.io.OutputStream)
*/
@SuppressWarnings("unchecked")
public void render(ReportData results, String argument, OutputStream out) throws IOException, RenderingException {
String[] args = argument.split(":");
ReportDesign design = getDesign(args[0]);
ReportDesignResource resource = design.getResourceByName("designFile");
Map<String, String> parameterValues = new LinkedHashMap<String, String>();
for (Map.Entry<String, Object> e : results.getContext().getParameterValues().entrySet()) {
Parameter p = results.getDefinition().getParameter(e.getKey());
if (p != null) {
String value = (e.getValue() instanceof Date ? Context.getDateFormat().format((Date)e.getValue()) : e.getValue().toString());
parameterValues.put(p.getLabelOrName(), value);
}
}
// Collect all available Cohorts by key
Map<String, Cohort> cohorts = new HashMap<String, Cohort>();
Map<String, String> cohortLabels = new HashMap<String, String>();
boolean usePrefix = results.getDataSets().size() > 1;
for (String dsKey : results.getDataSets().keySet()) {
String prefix = usePrefix ? dsKey + "." : "";
DataSet ds = results.getDataSets().get(dsKey);
if (ds instanceof MapDataSet) {
MapDataSet mds = (MapDataSet)ds;
for (DataSetColumn column : mds.getMetaData().getColumns()) {
String cohortKey = prefix + column.getName();
Object colValue = mds.getData(column);
Cohort c = null;
if (colValue instanceof Cohort) {
c = (Cohort)colValue;
}
else if (colValue instanceof CohortIndicatorAndDimensionResult) {
c = ((CohortIndicatorAndDimensionResult)colValue).getCohortIndicatorAndDimensionCohort();
}
if (c != null) {
cohorts.put(cohortKey, c);
cohortLabels.put(cohortKey, column.getLabel());
}
}
}
}
Map<String, Mapped<? extends DataSetDefinition>> m;
try {
ReportingSerializer s = new ReportingSerializer();
m = s.deserialize(new String(resource.getContents()), Map.class);
}
catch (SerializationException e) {
throw new RenderingException("Error deserializing the design file.", e);
}
// Iterate across all of the defined data sets to show, and evaluate them
Map<String, DataSet> datasets = new LinkedHashMap<String, DataSet>();
DataSetDefinitionService svc = Context.getService(DataSetDefinitionService.class);
for (Map.Entry<String, Mapped<? extends DataSetDefinition>> e : m.entrySet()) {
Cohort c = cohorts.get(e.getKey());
if (c != null) {
EvaluationContext ctx = results.getContext().shallowCopy();
if (ctx.getBaseCohort() == null) {
ctx.setBaseCohort(c);
}
else {
ctx.setBaseCohort(Cohort.intersect(ctx.getBaseCohort(), c));
}
try {
DataSet ds = svc.evaluate(e.getValue(), ctx);
datasets.put(e.getKey(), ds);
} catch (Exception ex) {
throw new RenderingException("Error evaluating dataset " + e.getKey(), new EvaluationException("dataset: " + e.getKey(), ex));
}
}
}
// Not, render it depending on the argument passed in
if ("xls".equalsIgnoreCase(args[1])) {
ExcelBuilder excelBuilder = new ExcelBuilder();
// For each dataset that is defined to be included, evaluate and include it
for (String dataSetKey : datasets.keySet()) {
DataSet dataset = datasets.get(dataSetKey);
String displayName = cohortLabels.get(dataSetKey);
excelBuilder.newSheet(displayName);
excelBuilder.addCell(displayName, "bold");
excelBuilder.nextRow();
excelBuilder.addCell(ObjectUtil.toString(parameterValues, ": ", ", "));
excelBuilder.nextRow();
excelBuilder.nextRow();
for (DataSetColumn column : dataset.getMetaData().getColumns()) {
excelBuilder.addCell(column.getLabel(), "bold");
}
excelBuilder.nextRow();
for (DataSetRow row : dataset) {
for (DataSetColumn column : dataset.getMetaData().getColumns()) {
Object cellValue = row.getColumnValue(column);
excelBuilder.addCell(cellValue);
}
excelBuilder.nextRow();
}
}
excelBuilder.write(out);
}
else {
Writer w = new OutputStreamWriter(out,"UTF-8");
// First output the name, description, and parameters of the report
w.write("<h4>" + results.getDefinition().getName() + "</h4>");
w.write("<small>");
for (Iterator<String> i = parameterValues.keySet().iterator(); i.hasNext();) {
String key = i.next();
w.write(key + ": <strong>" + parameterValues.get(key) + "</strong>" + (i.hasNext() ? " | " : ""));
}
w.write("</small>");
// For each dataset that is defined to be included, evaluate and include it
for (String dataSetKey : datasets.keySet()) {
DataSet dataset = datasets.get(dataSetKey);
w.write("<br/><br/><strong>" + cohortLabels.get(dataSetKey) + "</strong>");
w.write("<table id=\"indicator-report-dataset-" + dataSetKey +"\" class=\"display indicator-report-dataset\" border=1>");
w.write("<tr>");
for (DataSetColumn column : dataset.getMetaData().getColumns()) {
w.write("<th>"+column.getLabel()+"</th>");
}
w.write("</tr>");
for (DataSetRow row : dataset) {
w.write("<tr>");
for (DataSetColumn column : dataset.getMetaData().getColumns()) {
Object cellValue = row.getColumnValue(column.getName());
w.write("<td>" + ObjectUtil.nvlStr(cellValue, "") + "</td>");
}
w.write("</tr>");
}
w.write("</table>");
}
w.flush();
}
}
}