org.yes.cart.report.impl.ReportServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.yes.cart.report.impl.ReportServiceImpl.java

Source

/*
 * Copyright 2009 Denys Pavlov, Igor Azarnyi
 *
 *    Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.yes.cart.report.impl;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.context.ServletContextAware;
import org.xml.sax.SAXException;
import org.yes.cart.report.ReportService;
import org.yes.cart.report.ReportWorker;

import javax.servlet.ServletContext;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;

//JAXP
//FOP

/**
 * User: Igor Azarny iazarny@yahoo.com
 * Date: 7/2/12
 * Time: 2:46 PM
 */
public class ReportServiceImpl implements ReportService, ServletContextAware {

    private final Logger LOG = LoggerFactory.getLogger(ReportServiceImpl.class);

    private final List<ReportDescriptor> reportDescriptors;

    private final Map<String, ReportWorker> reportWorkers;

    private final String reportFolder;

    private ServletContext servletContext;

    /**
     * Construct report service.
     *
     * @param reportDescriptors list of configured reports.
     * @param reportWorkers     report workers
     * @param reportFolder      report folder
     */
    public ReportServiceImpl(final List<ReportDescriptor> reportDescriptors,
            final Map<String, ReportWorker> reportWorkers, final String reportFolder) {

        this.reportDescriptors = reportDescriptors;
        this.reportWorkers = reportWorkers;

        if (StringUtils.isNotBlank(reportFolder)) {
            this.reportFolder = "WEB-INF" + File.separator + reportFolder + File.separator;
        } else {
            this.reportFolder = StringUtils.EMPTY;
        }

    }

    /**
     * {@inheritDoc}
     */
    public List<ReportPair> getParameterValues(final String lang, final String reportId, final String param,
            final Map<String, Object> currentSelection) {

        if (reportWorkers.containsKey(reportId)) {
            return reportWorkers.get(reportId).getParameterValues(lang, param, currentSelection);
        }
        return Collections.emptyList();

    }

    /**
     * Get the list of report descriptors.
     *
     * @return list of reports which visible on UI.
     */
    @SuppressWarnings("unchecked")
    public List<ReportDescriptor> getReportDescriptors() {

        return (List<ReportDescriptor>) CollectionUtils.select(reportDescriptors, new Predicate() {
            public boolean evaluate(Object object) {
                return ((ReportDescriptor) object).isVisible();
            }
        }

        );
    }

    ReportDescriptor getReportDescriptorbyId(final String reportId) {

        Assert.notNull(reportId, "ReportId must be not null");

        return (ReportDescriptor) CollectionUtils.find(reportDescriptors, new Predicate() {
            public boolean evaluate(final Object o) {
                return reportId.equalsIgnoreCase(((ReportDescriptor) o).getReportId());
            }
        });

    }

    /**
     * {@inheritDoc}
     */
    public byte[] downloadReport(String lang, String reportId, Map<String, Object> params) throws Exception {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        if (createReport(lang, reportId, baos, params)) {
            return baos.toByteArray();
        } else {
            throw new Exception("Unable to create report");
        }
    }

    private boolean createReport(final String lang, final String reportId, final OutputStream reportStream,
            final Map<String, Object> currentSelection) throws Exception {

        final List<Object> rez = getQueryResult(lang, reportId, currentSelection);

        return createReport(lang, reportId, reportStream, rez);

    }

    /*
     * @param reportId report descriptor.
     * @param reportStream report filename
     * @param lang     given lang to produce report.
     * @param rez      list of object for report
     * @return true in case if report was generated
     * @throws SAXException
     * @throws IOException
     */
    private boolean createReport(String lang, String reportId, OutputStream reportStream, List<Object> rez)
            throws SAXException, IOException {

        final byte[] xmlfile = getXml(rez);

        if (LOG.isDebugEnabled()) {
            //            System.out.println(new String(xmlfile));
            LOG.debug(new String(xmlfile));
        }

        final String xslFoFile = getReportDescriptorbyId(reportId).getLangXslfo(lang);

        if (xmlfile != null && xmlfile.length > 0) {

            final File xsltfile;

            // configure fopFactory as desired
            final FopFactory fopFactory = FopFactory.newInstance();

            final FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
            // configure foUserAgent as desired

            final URL configFileUrl = this.getClass().getClassLoader().getResource("fop-userconfig.xml");
            if (configFileUrl == null) {
                LOG.error("FOP config file not  found, "
                        + "please put the fop-userconfig.xml file into the classpath of the  server, UTF - 8characters won't be displayed correctly");
            } else {
                File userConfigXml = new File(configFileUrl.getFile());
                fopFactory.setUserConfig(userConfigXml);
            }

            if (servletContext == null) {
                xsltfile = new File(reportFolder + xslFoFile);
            } else {
                xsltfile = new File(servletContext.getRealPath(reportFolder + xslFoFile));
                fopFactory.getFontManager().setFontBaseURL(servletContext.getRealPath("WEB-INF"));
                foUserAgent.setBaseURL("file:///" + servletContext.getRealPath("WEB-INF/report/"));
            }

            if (!xsltfile.exists()) {
                LOG.error("XSLT file does not exist: " + xsltfile.getAbsolutePath());
                return false;
            }

            // Setup output
            OutputStream out = new BufferedOutputStream(reportStream);

            try {
                // Construct fop with desired output format
                final Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

                // Setup XSLT 2.0
                final TransformerFactory factory = TransformerFactory
                        .newInstance("net.sf.saxon.TransformerFactoryImpl", null);
                final Transformer transformer = factory.newTransformer(new StreamSource(xsltfile));

                // Set the value of a <param> in the stylesheet
                transformer.setParameter("versionParam", "2.0");
                transformer.setOutputProperty("encoding", "UTF-8");

                // Setup input for XSLT transformation
                final Source src = new StreamSource(
                        new InputStreamReader(new ByteArrayInputStream(xmlfile), "UTF-8"));

                // Resulting SAX events (the generated FO) must be piped through to FOP
                final Result res = new SAXResult(fop.getDefaultHandler());

                // Start XSLT transformation and FOP processing
                transformer.transform(src, res);

            } catch (Exception ex) {

                LOG.error("Cannot create pdf " + ex.getMessage(), ex);

                return false;

            } finally {

                out.close();

            }

            return true;

        }

        return false;
    }

    /**
     * Write into given file name xml result.
     *
     * @param rez list of objects.
     * @return tmp xml file name
     */
    byte[] getXml(final List<Object> rez) {

        final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        ObjectOutputStream os = null;

        try {

            os = ReportObjectStreamFactory.getObjectOutputStream(new OutputStreamWriter(bytesOut));

            for (Object obj : rez) {
                os.writeObject(obj);
            }

        } catch (Exception e) {
            LOG.error("Cannot create xml ", e);

        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    LOG.error("Cannot close file", e);
                }
            }

        }

        return bytesOut.toByteArray();
    }

    /**
     * Get query result as object list.
     *
     * @param lang language
     * @param reportId reportId
     * @param currentSelection parameters.
     * @return list of objects.
     */
    List<Object> getQueryResult(final String lang, final String reportId,
            final Map<String, Object> currentSelection) {

        if (reportWorkers.containsKey(reportId)) {
            return reportWorkers.get(reportId).getResult(lang, currentSelection);
        }
        return Collections.emptyList();

    }

    /**
     * {@inheritDoc}
     */
    public void setServletContext(final ServletContext servletContext) {
        this.servletContext = servletContext;
    }

}