package org.openmrs.module.reporting.web.taglib; import java.io.IOException; import java.lang.reflect.Method; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.jsp.tagext.TagSupport; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.lang.StringEscapeUtils; import org.openmrs.Cohort; import org.openmrs.Concept; import org.openmrs.Encounter; import org.openmrs.EncounterType; import org.openmrs.Location; import org.openmrs.Obs; import org.openmrs.Person; import org.openmrs.User; import org.openmrs.api.context.Context; import org.openmrs.logic.result.EmptyResult; import org.openmrs.logic.result.Result; import org.openmrs.module.reporting.common.ObjectUtil; import org.openmrs.module.reporting.data.BaseData; 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.indicator.dimension.CohortDimensionResult; import org.openmrs.module.reporting.query.IdSet; import org.openmrs.module.reporting.report.ReportData; import org.springframework.util.StringUtils; public class FormatTag extends TagSupport { public static final long serialVersionUID = 1L; private final Log log = LogFactory.getLog(getClass()); private String var; private Object object; private Date date; private Integer conceptId; private Concept concept; private Obs obsValue; private Integer userId; private User user; private Integer encounterId; private Encounter encounter; private Integer encounterTypeId; private EncounterType encounterType; private Integer locationId; private Location location; private String string; private ReportData reportData; private DataSet dataSet; private Cohort cohort; public static String format(Object object) { StringBuilder sb = new StringBuilder(); new FormatTag().printObject(sb, object); return sb.toString(); } public int doStartTag() { StringBuilder sb = new StringBuilder(); if (object != null) { printObject(sb, object); } if (date != null) printDate(sb, date); if (conceptId != null) concept = Context.getConceptService().getConcept(conceptId); if (concept != null) { printConcept(sb, concept); } if (obsValue != null) printObsValue(sb, obsValue); if (userId != null) user = Context.getUserService().getUser(userId); if (user != null) printUser(sb, user); if (encounterId != null) encounter = Context.getEncounterService().getEncounter(encounterId); if (encounter != null) { printEncounter(sb, encounter); } if (encounterTypeId != null) encounterType = Context.getEncounterService().getEncounterType(encounterTypeId); if (encounterType != null) { printEncounterType(sb, encounterType); } if (locationId != null) location = Context.getLocationService().getLocation(locationId); if (location != null) { printLocation(sb, location); } if (reportData != null) { printReportData(sb, reportData); } if (dataSet != null) { printDataSet(sb, null, dataSet); } if (cohort != null) { printCohort(sb, cohort); } if (string != null) sb.append(string); if (StringUtils.hasText(var)) { pageContext.setAttribute(var, sb.toString()); } else { try { pageContext.getOut().write(sb.toString()); } catch (IOException e) { log.error("Failed to write to pageContext.getOut()", e); } } return SKIP_BODY; } /** * Formats anything and prints it to sb. (Delegates to other methods here * @param sb * @param o */ private void printObject(StringBuilder sb, Object o) { try { if (o instanceof Result) { printResult(sb, (Result) o); } else if (o instanceof Collection) { for (Iterator<?> i = ((Collection) o).iterator(); i.hasNext(); ) { printObject(sb, i.next()); if (i.hasNext()) sb.append(", "); } } else if (o instanceof Date) { printDate(sb, (Date) o); } else if (o instanceof Concept) { printConcept(sb, (Concept) o); } else if (o instanceof Obs) { printObsValue(sb, (Obs) o); } else if (o instanceof User) { printUser(sb, (User) o); } else if (o instanceof Encounter) { printEncounter(sb, (Encounter) o); } else if (o instanceof EncounterType) { printEncounterType(sb, (EncounterType) o); } else if (o instanceof Location) { printLocation(sb, (Location) o); } else if (o instanceof ReportData) { printReportData(sb, (ReportData) o); } else if (o instanceof DataSet) { printDataSet(sb, null, (DataSet) o); } else if (o instanceof Cohort) { printCohort(sb, (Cohort) o); } else if (o instanceof CohortDimensionResult) { printCohortDimensionResult(sb, (CohortDimensionResult) o); } else if (o instanceof BaseData) { printMap(sb, ((BaseData)o).getData()); } else if (o instanceof IdSet) { printCollection(sb, ((IdSet)o).getMemberIds()); } else { sb.append(ObjectUtil.format(o)); } } catch (Exception e) { sb.append(o.toString()); } } private void printResult(StringBuilder sb, Result result) { if (result instanceof EmptyResult) return; if (result.size() < 1) { // for some reason single results seem to have size 0 sb.append(result.toString()); } else { for (Iterator<Result> i = result.iterator(); i.hasNext(); ) { sb.append(i.next().toString()); if (i.hasNext()) sb.append(", "); } } } /** * formats a date and prints it to sb * * @param sb * @param date */ private void printDate(StringBuilder sb, Date date) { sb.append(Context.getDateFormat().format(date)); } /** * formats a location and prints it to sb * * @param sb * @param location */ private void printLocation(StringBuilder sb, Location location) { sb.append(location.getName()); } /** * formats an encounter type and prints it to sb * * @param sb * @param encounterType */ private void printEncounterType(StringBuilder sb, EncounterType encounterType) { sb.append(encounterType.getName()); } /** * formats a user and prints it to sb * * @param sb * @param u */ private void printUser(StringBuilder sb, User u) { sb.append(u.getPersonName()); } /** * formats a user and prints it to sb * * @param sb * @param u */ private void printUser(StringBuilder sb, Person u) { sb.append(u.getPersonName()); } /** * Formats a ReportData and prints it to sb * * @param sb * @param reportData */ private void printReportData(StringBuilder sb, ReportData reportData) { sb.append("<h4>" + StringEscapeUtils.escapeHtml(reportData.getDefinition().getName()) + "</h4>"); for (Map.Entry<String, DataSet> ds : reportData.getDataSets().entrySet()) { printDataSet(sb, ds.getKey(), ds.getValue()); } } /** * Formats a DataSet and prints it to sb * * @param sb * @param title * @param dataSet */ private void printDataSet(StringBuilder sb, String title, DataSet dataSet) { sb.append("<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">"); List<DataSetColumn> cols = dataSet.getMetaData().getColumns(); sb.append("<thead>"); if (StringUtils.hasText(title)) { sb.append("<tr bgcolor=\"#f0f0f0\"><th colspan=\"" + cols.size() + "\">" + title + "</th></tr>"); } if (!(dataSet instanceof MapDataSet)) { sb.append("<tr>"); for (DataSetColumn col : cols) { sb.append("<th>" + col.getLabel() + "</th>"); } sb.append("</tr>"); } sb.append("</thead>"); sb.append("<tbody>"); if (dataSet instanceof MapDataSet) { MapDataSet map = (MapDataSet) dataSet; DataSetRow row = map.getData(); for (DataSetColumn col : cols) { sb.append("<tr><th align=\"left\">") .append(Context.getMessageSourceService().getMessage(col.getLabel())) .append("</th><td>") .append(formatHelper(row.getColumnValue(col))) .append("</td></tr>"); } } else { for (DataSetRow row : dataSet) { sb.append("<tr>"); for (DataSetColumn col : cols) { sb.append("<td>").append(formatHelper(row.getColumnValue(col))).append("</td>"); } sb.append("</tr>"); } } sb.append("</tbody>"); sb.append("</table>"); } /** * Formats a DataSet and prints it to sb * * @param sb * @param title * @param dataSet */ private void printCohortDimensionResult(StringBuilder sb, CohortDimensionResult result) { sb.append("<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">"); for (Map.Entry<String, Cohort> e : result.getOptionCohorts().entrySet()) { sb.append("<tr><th align=\"left\">" + e.getKey() + "</th><td>"); printCohort(sb, e.getValue()); sb.append("</td></tr>"); } sb.append("</table>"); } /** * formats a cohort to sb * * @param sb * @param cohort */ private void printCohort(StringBuilder sb, Cohort cohort) { sb.append(cohort.size() + " patients"); } private void printObsValue(StringBuilder sb, Obs obsValue) { sb.append(obsValue.getValueAsString(Context.getLocale())); } private void printConcept(StringBuilder sb, Concept concept) { if (concept.getName() != null) sb.append(concept.getName().getName()); } private void printEncounter(StringBuilder sb, Encounter encounter) { printEncounterType(sb, encounter.getEncounterType()); sb.append(" @"); printLocation(sb, encounter.getLocation()); sb.append(" | "); printDate(sb, encounter.getEncounterDatetime()); sb.append(" | "); try { Method method = encounter.getClass().getMethod("getProvider", null); Object provider = method.invoke(encounter, null); printUser(sb, (User)provider); } catch (Exception ex) { //should be a newer version that removed the getProvider method } } private void printMap(StringBuilder sb, Map<?, ?> m) { if (m != null) { sb.append("<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">"); for (Map.Entry<?, ?> e : m.entrySet()) { sb.append("<tr><th align=\"left\">" + format(e.getKey()) + "</th><td align=\"left\">" + format(e.getValue()) + "</td></tr>"); } sb.append("</table>"); } } private void printCollection(StringBuilder sb, Collection<?> c){ if(c != null){ sb.append("<table cellspacing=\"0\" cellpadding=\"2\" border=\"1\">"); sb.append("<tr><th align=\"left\">" + Context.getMessageSourceService().getMessage("reporting.ids") + "</th></tr>"); for (Object item : c) { sb.append("<tr><td align=\"left\">"); printObject(sb, item); sb.append("</td></tr>"); } sb.append("</table>"); } } private String formatHelper(Object o) { if (o == null) { return ""; } else if (o instanceof Cohort) { return ((Cohort)o).getSize() + " patients"; } try { Method method = o.getClass().getMethod("getValue"); return method.invoke(o).toString(); } catch (Exception ex) { return o.toString(); } } public int doEndTag() { reset(); return EVAL_PAGE; } private void reset() { var = null; object = null; date = null; conceptId = null; concept = null; obsValue = null; userId = null; user = null; encounterId = null; encounter = null; encounterTypeId = null; encounterType = null; locationId = null; location = null; reportData = null; dataSet = null; cohort = null; string = null; } public Integer getConceptId() { return conceptId; } public void setConceptId(Integer conceptId) { this.conceptId = conceptId; } public Concept getConcept() { return concept; } public void setConcept(Concept concept) { this.concept = concept; } public Obs getObsValue() { return obsValue; } public void setObsValue(Obs obsValue) { this.obsValue = obsValue; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Integer getEncounterId() { return encounterId; } public void setEncounterId(Integer encounterId) { this.encounterId = encounterId; } public Encounter getEncounter() { return encounter; } public void setEncounter(Encounter encounter) { this.encounter = encounter; } public Integer getEncounterTypeId() { return encounterTypeId; } public void setEncounterTypeId(Integer encounterTypeId) { this.encounterTypeId = encounterTypeId; } public EncounterType getEncounterType() { return encounterType; } public void setEncounterType(EncounterType encounterType) { this.encounterType = encounterType; } public Integer getLocationId() { return locationId; } public void setLocationId(Integer locationId) { this.locationId = locationId; } public Location getLocation() { return location; } public void setLocation(Location location) { this.location = location; } public String getVar() { return var; } public void setVar(String var) { this.var = var; } public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }