/** * *************************************************************************** * Copyright (c) 2010 Qcadoo Limited * Project: Qcadoo Framework * Version: 1.4 * * This file is part of Qcadoo. * * Qcadoo 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************** */ package com.qcadoo.report.internal; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExporter; import net.sf.jasperreports.engine.JRExporterParameter; import net.sf.jasperreports.engine.JRParameter; import net.sf.jasperreports.engine.JasperCompileManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.export.JRCsvExporter; import net.sf.jasperreports.engine.export.JRPdfExporter; import net.sf.jasperreports.engine.export.JRXlsExporter; import net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.context.support.MessageSourceResourceBundle; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import com.qcadoo.model.api.DataDefinitionService; import com.qcadoo.model.api.Entity; import com.qcadoo.report.api.ReportException; import com.qcadoo.report.api.ReportService; import com.qcadoo.report.api.pdf.PdfHelper; import com.qcadoo.report.internal.templates.ReportTemplateService; import com.qcadoo.report.internal.util.ReportFormatFactory; import com.qcadoo.view.api.ComponentState; import com.qcadoo.view.api.ComponentState.MessageType; import com.qcadoo.view.api.ViewDefinitionState; import com.qcadoo.view.api.components.FormComponent; @Service public class ReportServiceImpl implements ReportService { private static final Logger LOG = LoggerFactory.getLogger(ReportServiceImpl.class); @Autowired private ReportTemplateService reportTemplateService; @Autowired private SessionFactory sessionFactory; @Autowired private MessageSource messageSource; @Autowired private DataDefinitionService dataDefinitionService; @Autowired private PdfHelper pdfHelper; @Override public byte[] generateReportForEntity(final String templatePlugin, final String templateName, final ReportType type, final List<Long> entityIds, final Map<String, String> userArgs, final Locale locale) throws ReportException { Map<String, Object> parameters = new HashMap<String, Object>(userArgs); parameters.put("EntityIds", entityIds); return generateReport(templatePlugin, templateName, type, parameters, locale); } @Transactional(readOnly = true) @Override public byte[] generateReport(final String templatePlugin, final String templateName, final ReportType type, final Map<String, Object> parameters, final Locale locale) throws ReportException { if (LOG.isDebugEnabled()) { LOG.debug("Try to generate report [" + type + ", " + templatePlugin + "." + templateName + ", " + parameters + "]"); } JasperReport template = reportTemplateService.getTemplate(templatePlugin, templateName); if (template == null) { throw new ReportException(ReportException.Type.NO_TEMPLATE_FOUND, templatePlugin + "." + templateName); } return generateReport(template, type, parameters, locale); } @Transactional(readOnly = true) @Override public byte[] generateReport(final String templateContent, final ReportType type, final Map<String, Object> parameters, final Locale locale) throws ReportException { InputStream in = null; try { in = new ByteArrayInputStream(templateContent.getBytes("UTF-8")); JasperReport template = JasperCompileManager.compileReport(in); return generateReport(template, type, parameters, locale); } catch (JRException e) { throw new ReportException(ReportException.Type.NO_TEMPLATE_FOUND, e); } catch (UnsupportedEncodingException e) { throw new ReportException(ReportException.Type.NO_TEMPLATE_FOUND, e); } finally { IOUtils.closeQuietly(in); } } private byte[] generateReport(final JasperReport template, final ReportType type, final Map<String, Object> parameters, final Locale locale) throws ReportException { Session session = null; try { session = sessionFactory.openSession(); parameters.put(JRParameter.REPORT_LOCALE, locale); parameters.put("Author", pdfHelper.getDocumentAuthor()); parameters.put(JRHibernateQueryExecuterFactory.PARAMETER_HIBERNATE_SESSION, session); ResourceBundle resourceBundle = new MessageSourceResourceBundle(messageSource, locale); parameters.put(JRParameter.REPORT_RESOURCE_BUNDLE, resourceBundle); parameters.put(JRParameter.REPORT_FORMAT_FACTORY, new ReportFormatFactory()); JasperPrint jasperPrint = JasperFillManager.fillReport(template, parameters); JRExporter exporter = getExporter(type); ByteArrayOutputStream stream = new ByteArrayOutputStream(); exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, stream); exporter.exportReport(); return stream.toByteArray(); } catch (JRException e) { throw new ReportException(ReportException.Type.GENERATE_REPORT_EXCEPTION, e); } finally { if (session != null) { session.close(); } } } private JRExporter getExporter(final ReportType type) throws ReportException { JRExporter exporter = null; switch (type) { case PDF: exporter = new JRPdfExporter(); break; case XLS: exporter = new JRXlsExporter(); break; case CSV: exporter = new JRCsvExporter(); break; default: throw new ReportException(ReportException.Type.WRONG_REPORT_TYPE, type.toString()); } return exporter; } @Override public void printGeneratedReport(final ViewDefinitionState viewDefinitionState, final ComponentState state, final String[] args) { if (state.getFieldValue() instanceof Long) { Entity entity = dataDefinitionService.get(args[1], args[2]).get((Long) state.getFieldValue()); if (entity == null) { state.addMessage("qcadooView.message.entityNotFound", MessageType.FAILURE); } else if (StringUtils.hasText(entity.getStringField("fileName"))) { final StringBuilder urlBuilder = new StringBuilder(); urlBuilder.append("/generateSavedReport/").append(args[1]); urlBuilder.append("/").append(args[2]).append("."); urlBuilder.append(args[0]).append("?id=").append(state.getFieldValue()); if (args.length >= 4) { urlBuilder.append("&reportNo=").append(args[3]); } viewDefinitionState.redirectTo(urlBuilder.toString(), true, false); } else { state.addMessage("qcadooReport.errorMessage.documentsWasNotGenerated", MessageType.FAILURE); } } else { if (state instanceof FormComponent) { state.addMessage("qcadooView.form.entityWithoutIdentifier", MessageType.FAILURE); } else { state.addMessage("qcadooView.grid.noRowSelectedError", MessageType.FAILURE); } } } }