/**
* 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.report.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Cohort;
import org.openmrs.GlobalProperty;
import org.openmrs.api.APIException;
import org.openmrs.api.DataSetService;
import org.openmrs.api.ReportService;
import org.openmrs.api.context.Context;
import org.openmrs.report.DataSet;
import org.openmrs.report.DataSetDefinition;
import org.openmrs.report.EvaluationContext;
import org.openmrs.report.RenderingMode;
import org.openmrs.report.ReportData;
import org.openmrs.report.ReportRenderer;
import org.openmrs.report.ReportSchema;
import org.openmrs.report.ReportSchemaXml;
import org.openmrs.report.db.ReportDAO;
import org.openmrs.util.OpenmrsClassLoader;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.simpleframework.xml.Serializer;
/**
* Methods specific to objects in the report package. These methods render reports or save them to
* the database
*
* @see org.openmrs.api.ReportService
* @see org.openmrs.api.context.Context
* @deprecated see reportingcompatibility module
*/
@Deprecated
public class ReportServiceImpl implements ReportService {
public Log log = LogFactory.getLog(this.getClass());
private ReportDAO dao = null;
/**
* Report renderers that have been registered. This is filled via {@link #setRenderers(Map)} and
* spring's applicationContext-service.xml object
*/
private static Map<Class<? extends ReportRenderer>, ReportRenderer> renderers = null;
/**
* Default constructor
*/
public ReportServiceImpl() {
}
/**
* Method used by Spring injection to set the ReportDAO implementation to use in this service
*
* @param dao The ReportDAO to use in this service
*/
public void setReportDAO(ReportDAO dao) {
this.dao = dao;
}
/**
* Clean up after this class. Set the static var to null so that the classloader can reclaim the
* space.
*
* @see org.openmrs.api.impl.BaseOpenmrsService#onShutdown()
*/
public void onShutdown() {
renderers = null;
}
/**
* @see org.openmrs.api.ReportService#deleteReportSchema(org.openmrs.report.ReportSchema)
*/
public void deleteReportSchema(ReportSchema reportSchema) {
throw new APIException("Not Yet Implemented");
}
/**
* @see org.openmrs.api.ReportService#evaluate(org.openmrs.report.ReportSchema,
* org.openmrs.Cohort, org.openmrs.report.EvaluationContext)
*/
@SuppressWarnings("unchecked")
public ReportData evaluate(ReportSchema reportSchema, Cohort inputCohort, EvaluationContext evalContext) {
ReportData ret = new ReportData();
Map<String, DataSet> data = new HashMap<String, DataSet>();
ret.setDataSets(data);
ret.setReportSchema(reportSchema);
ret.setEvaluationContext(evalContext);
DataSetService dss = Context.getDataSetService();
if (reportSchema.getDataSetDefinitions() != null)
for (DataSetDefinition dataSetDefinition : reportSchema.getDataSetDefinitions()) {
data.put(dataSetDefinition.getName(), dss.evaluate(dataSetDefinition, inputCohort, evalContext));
}
return ret;
}
/**
* @see org.openmrs.api.ReportService#getReportRenderer(java.lang.String)
*/
public ReportRenderer getReportRenderer(Class<? extends ReportRenderer> clazz) {
try {
return renderers.get(clazz);
}
catch (Exception ex) {
log.error("Failed to get report renderer for " + clazz, ex);
return null;
}
}
/**
* @see org.openmrs.api.ReportService#getReportRenderer(java.lang.String)
*/
public ReportRenderer getReportRenderer(String className) {
try {
return renderers.get(OpenmrsClassLoader.getInstance().loadClass(className));
}
catch (Exception ex) {
log.error("Failed to get report renderer for " + className, ex);
return null;
}
}
/**
* @see org.openmrs.api.ReportService#getReportRenderers()
*/
public Collection<ReportRenderer> getReportRenderers() {
return getRenderers().values();
}
/**
* @see org.openmrs.api.ReportService#getRenderingModes(org.openmrs.report.ReportSchema)
*/
public List<RenderingMode> getRenderingModes(ReportSchema schema) {
List<RenderingMode> ret = new Vector<RenderingMode>();
for (ReportRenderer r : getReportRenderers()) {
Collection<RenderingMode> modes = r.getRenderingModes(schema);
if (modes != null)
ret.addAll(modes);
}
Collections.sort(ret);
return ret;
}
/**
* @see org.openmrs.api.ReportService#getReportSchema(java.lang.Integer)
*/
public ReportSchema getReportSchema(Integer reportSchemaId) throws APIException {
ReportSchemaXml xml = getReportSchemaXml(reportSchemaId);
return getReportSchema(xml);
}
/**
* @see org.openmrs.api.ReportService#getReportSchema(org.openmrs.report.ReportSchemaXml)
*/
public ReportSchema getReportSchema(ReportSchemaXml reportSchemaXml) throws APIException {
ReportSchema reportSchema = null;
if (reportSchemaXml == null || reportSchemaXml.getXml() == null || reportSchemaXml.getXml().length() == 0) {
throw new APIException("The current serialized ReportSchema string named 'xml' is null or empty");
}
Serializer deserializer = OpenmrsUtil.getSerializer();
String expandedXml = applyReportXmlMacros(reportSchemaXml.getXml());
try {
reportSchema = deserializer.read(ReportSchema.class, expandedXml);
}
catch (Exception e) {
throw new APIException(e);
}
return reportSchema;
}
/**
* @see org.openmrs.api.ReportService#getReportSchemas()
*/
public List<ReportSchema> getReportSchemas() throws APIException {
List<ReportSchema> ret = new ArrayList<ReportSchema>();
for (ReportSchemaXml xml : getReportSchemaXmls()) {
ret.add(getReportSchema(xml));
}
return ret;
}
/**
* ADDs renderers...doesn't replace them.
*
* @see org.openmrs.api.ReportService#setRenderers(java.util.Map)
*/
public void setRenderers(Map<Class<? extends ReportRenderer>, ReportRenderer> newRenderers) throws APIException {
for (Map.Entry<Class<? extends ReportRenderer>, ReportRenderer> entry : newRenderers.entrySet()) {
registerRenderer(entry.getKey(), entry.getValue());
}
}
/**
* @see org.openmrs.api.ReportService#getRenderers()
*/
public Map<Class<? extends ReportRenderer>, ReportRenderer> getRenderers() throws APIException {
if (renderers == null)
renderers = new LinkedHashMap<Class<? extends ReportRenderer>, ReportRenderer>();
return renderers;
}
/**
* @see org.openmrs.api.ReportService#registerRenderer(java.lang.Class,
* org.openmrs.report.ReportRenderer)
*/
public void registerRenderer(Class<? extends ReportRenderer> rendererClass, ReportRenderer renderer) throws APIException {
getRenderers().put(rendererClass, renderer);
}
/**
* @see org.openmrs.api.ReportService#registerRenderer(java.lang.String)
*/
@SuppressWarnings("unchecked")
public void registerRenderer(String rendererClass) throws APIException {
try {
Class loadedClass = OpenmrsClassLoader.getInstance().loadClass(rendererClass);
registerRenderer(loadedClass, (ReportRenderer) loadedClass.newInstance());
}
catch (Exception e) {
throw new APIException("Unable to load and instantiate renderer", e);
}
}
/**
* @see org.openmrs.api.ReportService#removeRenderer(Class)
*/
public void removeRenderer(Class<? extends ReportRenderer> renderingClass) {
renderers.remove(renderingClass);
}
/**
* @see org.openmrs.api.ReportService#saveReportSchema(org.openmrs.report.ReportSchema)
*/
public void saveReportSchema(ReportSchema reportSchema) {
throw new APIException("Not Yet Implemented");
}
/**
* @see org.openmrs.api.ReportService#getReportSchemaXml(java.lang.Integer)
*/
public ReportSchemaXml getReportSchemaXml(Integer reportSchemaXmlId) {
return dao.getReportSchemaXml(reportSchemaXmlId);
}
/**
* @see org.openmrs.api.ReportService#saveReportSchemaXml(org.openmrs.report.ReportSchemaXml)
*/
public void saveReportSchemaXml(ReportSchemaXml reportSchemaXml) {
dao.saveReportSchemaXml(reportSchemaXml);
}
/**
* @see org.openmrs.api.ReportService#createReportSchemaXml(org.openmrs.report.ReportSchemaXml)
* @deprecated use saveReportSchemaXml(reportSchemaXml)
*/
public void createReportSchemaXml(ReportSchemaXml reportSchemaXml) {
Context.getReportService().saveReportSchemaXml(reportSchemaXml);
}
/**
* @see org.openmrs.api.ReportService#updateReportSchemaXml(org.openmrs.report.ReportSchemaXml)
* @deprecated use saveReportSchemaXml(reportSchemaXml)
*/
public void updateReportSchemaXml(ReportSchemaXml reportSchemaXml) {
Context.getReportService().saveReportSchemaXml(reportSchemaXml);
}
/**
* @see org.openmrs.api.ReportService#deleteReportSchemaXml(org.openmrs.report.ReportSchemaXml)
*/
public void deleteReportSchemaXml(ReportSchemaXml reportSchemaXml) {
dao.deleteReportSchemaXml(reportSchemaXml);
}
/**
* @see org.openmrs.api.ReportService#getReportSchemaXmls()
*/
public List<ReportSchemaXml> getReportSchemaXmls() {
return dao.getReportSchemaXmls();
}
/**
* @see org.openmrs.api.ReportService#getReportXmlMacros()
*/
public Properties getReportXmlMacros() {
try {
String macrosAsString = Context.getAdministrationService().getGlobalProperty(
OpenmrsConstants.GLOBAL_PROPERTY_REPORT_XML_MACROS);
Properties macros = new Properties();
if (macrosAsString != null) {
OpenmrsUtil.loadProperties(macros, new ByteArrayInputStream(macrosAsString.getBytes("UTF-8")));
}
return macros;
}
catch (Exception ex) {
throw new APIException(ex);
}
}
/**
* @see org.openmrs.api.ReportService#saveReportXmlMacros(java.util.Properties)
*/
public void saveReportXmlMacros(Properties macros) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
OpenmrsUtil.storeProperties(macros, out, null);
GlobalProperty prop = new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_REPORT_XML_MACROS, out.toString());
Context.getAdministrationService().saveGlobalProperty(prop);
}
catch (Exception ex) {
throw new APIException(ex);
}
}
/**
* @see org.openmrs.api.ReportService#applyReportXmlMacros(java.lang.String)
*/
public String applyReportXmlMacros(String input) {
Properties macros = getReportXmlMacros();
if (macros != null && macros.size() > 0) {
log.debug("XML Before macros: " + input);
String prefix = macros.getProperty("macroPrefix", "");
String suffix = macros.getProperty("macroSuffix", "");
while (true) {
String replacement = input;
for (Map.Entry<Object, Object> e : macros.entrySet()) {
String key = prefix + e.getKey() + suffix;
String value = e.getValue() == null ? "" : e.getValue().toString();
log.debug("Trying to replace " + key + " with " + value);
replacement = replacement.replace(key, (String) e.getValue());
}
if (input.equals(replacement)) {
log.debug("Macro expansion complete.");
break;
}
input = replacement;
log.debug("XML Exploded to: " + input);
}
}
return input;
}
}