org.openvpms.report.jasper.AbstractJasperIMReport.java Source code

Java tutorial

Introduction

Here is the source code for org.openvpms.report.jasper.AbstractJasperIMReport.java

Source

/*
 * Version: 1.0
 *
 * The contents of this file are subject to the OpenVPMS 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://www.openvpms.org/license/
 *
 * 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 2015 (C) OpenVPMS Ltd. All Rights Reserved.
 */

package org.openvpms.report.jasper;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JRRewindableDataSource;
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.ReportContext;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPrintServiceExporter;
import net.sf.jasperreports.engine.export.JRRtfExporter;
import net.sf.jasperreports.engine.export.JRTextExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXmlExporter;
import net.sf.jasperreports.engine.fill.JREvaluator;
import net.sf.jasperreports.engine.query.JRQueryExecuter;
import net.sf.jasperreports.export.Exporter;
import net.sf.jasperreports.export.ExporterConfiguration;
import net.sf.jasperreports.export.ExporterInput;
import net.sf.jasperreports.export.OutputStreamExporterOutput;
import net.sf.jasperreports.export.ReportExportConfiguration;
import net.sf.jasperreports.export.SimpleCsvExporterConfiguration;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.export.SimplePrintServiceExporterConfiguration;
import net.sf.jasperreports.export.SimpleWriterExporterOutput;
import net.sf.jasperreports.export.SimpleXlsReportConfiguration;
import net.sf.jasperreports.export.WriterExporterOutput;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.jxpath.Functions;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openvpms.archetype.rules.doc.DocumentArchetypes;
import org.openvpms.archetype.rules.doc.DocumentException;
import org.openvpms.archetype.rules.doc.DocumentHandler;
import org.openvpms.archetype.rules.doc.DocumentHandlers;
import org.openvpms.component.business.domain.im.document.Document;
import org.openvpms.component.business.service.archetype.ArchetypeServiceException;
import org.openvpms.component.business.service.archetype.IArchetypeService;
import org.openvpms.component.business.service.lookup.ILookupService;
import org.openvpms.report.DocFormats;
import org.openvpms.report.ParameterType;
import org.openvpms.report.PrintProperties;
import org.openvpms.report.ReportException;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrinterName;
import javax.print.attribute.standard.Sides;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import static org.openvpms.report.ReportException.ErrorCode.FailedToGenerateReport;
import static org.openvpms.report.ReportException.ErrorCode.FailedToGetParameters;
import static org.openvpms.report.ReportException.ErrorCode.NoPagesToPrint;
import static org.openvpms.report.ReportException.ErrorCode.UnsupportedMimeType;

/**
 * Abstract implementation of the {@link JasperIMReport} interface.
 *
 * @author Tim Anderson
 */
public abstract class AbstractJasperIMReport<T> implements JasperIMReport<T> {

    /**
     * The archetype service.
     */
    private final IArchetypeService service;

    /**
     * The lookup service.
     */
    private final ILookupService lookups;

    /**
     * The document handlers.
     */
    private final DocumentHandlers handlers;

    /**
     * Cached expression evaluator.
     */
    private JREvaluator evaluator;

    /**
     * The JXPath extension functions.
     */
    private final Functions functions;

    /**
     * The supported mime types.
     */
    private static final String[] MIME_TYPES = { DocFormats.PDF_TYPE, DocFormats.RTF_TYPE, DocFormats.XLS_TYPE,
            DocFormats.CSV_TYPE, DocFormats.TEXT_TYPE };

    /**
     * The logger.
     */
    private static final Log log = LogFactory.getLog(AbstractJasperIMReport.class);

    /**
     * Constructs an {@link AbstractJasperIMReport}.
     *
     * @param service   the archetype service
     * @param lookups   the lookup service
     * @param handlers  the document handlers
     * @param functions the JXPath extension functions
     */
    public AbstractJasperIMReport(IArchetypeService service, ILookupService lookups, DocumentHandlers handlers,
            Functions functions) {
        this.service = service;
        this.lookups = lookups;
        this.handlers = handlers;
        this.functions = functions;
    }

    /**
     * Returns the set of parameter types that may be supplied to the report.
     *
     * @return the parameter types
     * @throws ReportException if a parameter expression can't be evaluated
     */
    @Override
    public Set<ParameterType> getParameterTypes() {
        Set<ParameterType> types = new LinkedHashSet<ParameterType>();
        JasperReport report = getReport();
        for (JRParameter p : report.getParameters()) {
            if (!p.isSystemDefined() && p.isForPrompting()) {
                JRExpression expression = p.getDefaultValueExpression();
                Object defaultValue = null;
                if (expression != null) {
                    try {
                        defaultValue = getEvaluator().evaluate(expression);
                    } catch (JRException exception) {
                        throw new ReportException(exception, FailedToGetParameters);
                    }
                }
                ParameterType type = new ParameterType(p.getName(), p.getValueClass(), p.getDescription(),
                        defaultValue);
                types.add(type);
            }
        }
        return types;
    }

    /**
     * Determines if the report accepts the named parameter.
     *
     * @param name the parameter name
     * @return {@code true} if the report accepts the parameter, otherwise {@code false}
     */
    @Override
    public boolean hasParameter(String name) {
        for (JRParameter p : getReport().getParameters()) {
            if (ObjectUtils.equals(p.getName(), name)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns the default mime type for report documents.
     *
     * @return the default mime type
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public String getDefaultMimeType() {
        return DocFormats.PDF_TYPE;
    }

    /**
     * Returns the supported mime types for report documents.
     *
     * @return the supported mime types
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public String[] getMimeTypes() {
        return MIME_TYPES;
    }

    /**
     * Generates a report.
     * <p/>
     * The default mime type will be used to select the output format.
     *
     * @param parameters a map of parameter names and their values, to pass to the report
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @return a document containing the report
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public Document generate(Map<String, Object> parameters, Map<String, Object> fields) {
        return generate(parameters, fields, getDefaultMimeType());
    }

    /**
     * Generates a report.
     *
     * @param parameters a map of parameter names and their values, to pass to the report
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @param mimeType   the output format of the report
     * @return a document containing the report
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public Document generate(Map<String, Object> parameters, Map<String, Object> fields, String mimeType) {
        Document document;
        Map<String, Object> properties = getDefaultParameters();
        if (parameters != null) {
            properties.putAll(parameters);
        }
        if (mimeType.equals(DocFormats.CSV_TYPE) || mimeType.equals(DocFormats.XLS_TYPE)) {
            properties.put(JRParameter.IS_IGNORE_PAGINATION, true);
        }
        JasperReport report = getReport();
        JRQueryExecuter executer = null;
        try {
            executer = initDataSource(properties, fields, report);
            JasperPrint print = JasperFillManager.fillReport(report, properties);
            document = export(print, properties, mimeType);
        } catch (JRException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        } finally {
            if (executer != null) {
                executer.close();
            }
        }
        return document;
    }

    /**
     * Generates a report for a collection of objects.
     * <p/>
     * The default mime type will be used to select the output format.
     *
     * @param objects the objects to report on
     * @return a document containing the report
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public Document generate(Iterable<T> objects) {
        return generate(objects, getDefaultMimeType());
    }

    /**
     * Generates a report for a collection of objects.
     *
     * @param objects  the objects to report on
     * @param mimeType the output format of the report
     * @return a document containing the report
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public Document generate(Iterable<T> objects, String mimeType) {
        Map<String, Object> empty = Collections.emptyMap();
        return generate(objects, empty, null, mimeType);
    }

    /**
     * Generates a report for a collection of objects.
     * <p/>
     * The default mime type will be used to select the output format.
     *
     * @param objects    the objects to report on
     * @param parameters a map of parameter names and their values, to pass to the report. May be {@code null}
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @return a document containing the report
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    public Document generate(Iterable<T> objects, Map<String, Object> parameters, Map<String, Object> fields) {
        return generate(objects, parameters, fields, getDefaultMimeType());
    }

    /**
     * Generates a report for a collection of objects.
     *
     * @param objects    the objects to report on
     * @param parameters a map of parameter names and their values, to pass to the report. May be {@code null}
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @param mimeType   the output format of the report
     * @return a document containing the report
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    public Document generate(Iterable<T> objects, Map<String, Object> parameters, Map<String, Object> fields,
            String mimeType) {
        Document document;
        parameters = (parameters != null) ? new HashMap<String, Object>(parameters) : new HashMap<String, Object>();
        try {
            if (mimeType.equals(DocFormats.CSV_TYPE) || mimeType.equals(DocFormats.XLS_TYPE)) {
                parameters.put(JRParameter.IS_IGNORE_PAGINATION, true);
            }
            JasperPrint print = report(objects, parameters, fields);
            document = export(print, parameters, mimeType);
        } catch (JRException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        }
        return document;
    }

    /**
     * Generates a report for a collection of objects to the specified stream.
     *
     * @param objects    the objects to report on
     * @param parameters a map of parameter names and their values, to pass to the report. May be {@code null}
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @param mimeType   the output format of the report
     * @param stream     the stream to write to   @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    public void generate(Iterable<T> objects, Map<String, Object> parameters, Map<String, Object> fields,
            String mimeType, OutputStream stream) {
        try {
            if (mimeType.equals(DocFormats.CSV_TYPE) || mimeType.equals(DocFormats.XLS_TYPE)) {
                parameters.put(JRParameter.IS_IGNORE_PAGINATION, true);
            }
            JasperPrint report = report(objects, parameters, fields);
            export(report, stream, parameters, mimeType);
        } catch (JRException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        }
    }

    /**
     * Prints a report directly to a printer.
     *
     * @param parameters a map of parameter names and their values, to pass to the report. May be {@code null}
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @param properties the print properties
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    public void print(Map<String, Object> parameters, Map<String, Object> fields, PrintProperties properties) {
        Map<String, Object> params = getDefaultParameters();
        JasperReport report = getReport();
        if (parameters != null) {
            params.putAll(parameters);
        }
        JRQueryExecuter executer = null;
        try {
            executer = initDataSource(params, fields, report);
            JasperPrint print = JasperFillManager.fillReport(getReport(), params);
            print(print, properties);
        } catch (JRException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        } finally {
            if (executer != null) {
                executer.close();
            }
        }
    }

    /**
     * Prints a report directly to a printer.
     *
     * @param objects    the objects to report on
     * @param properties the print properties
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    @Override
    public void print(Iterable<T> objects, PrintProperties properties) {
        Map<String, Object> empty = Collections.emptyMap();
        print(objects, empty, null, properties);
    }

    /**
     * Prints a report directly to a printer.
     *
     * @param objects    the objects to report on
     * @param parameters a map of parameter names and their values, to pass to the report
     * @param fields     additional fields available to the report. May be {@code null}
     * @param properties the print properties
     * @throws ReportException           for any report error
     * @throws ArchetypeServiceException for any archetype service error
     */
    public void print(Iterable<T> objects, Map<String, Object> parameters, Map<String, Object> fields,
            PrintProperties properties) {
        try {
            JasperPrint print = report(objects, parameters, fields);
            print(print, properties);
        } catch (JRException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        }
    }

    /**
     * Generates a report.
     *
     * @param objects the objects to report on
     * @return the report the report
     * @throws JRException for any error
     */
    @Override
    public JasperPrint report(Iterable<T> objects) throws JRException {
        return report(objects, null, null);
    }

    /**
     * Generates a report.
     *
     * @param objects    the objects to report on
     * @param parameters a map of parameter names and their values, to pass to the report. May be {@code null}
     * @param fields     a map of additional field names and their values, to pass to the report. May be {@code null}
     * @return the report
     * @throws JRException for any error
     */
    public JasperPrint report(Iterable<T> objects, Map<String, Object> parameters, Map<String, Object> fields)
            throws JRException {
        JRDataSource source = createDataSource(objects, fields);
        HashMap<String, Object> properties = new HashMap<String, Object>(getDefaultParameters());
        if (parameters != null) {
            properties.putAll(parameters);
        }
        properties.put("dataSource", source); // custom data source name, to avoid casting
        properties.put(JRParameter.REPORT_DATA_SOURCE, source);
        return JasperFillManager.fillReport(getReport(), properties, source);
    }

    /**
     * Creates a data source for a collection of objects.
     *
     * @param objects an iterator over the collection of objects
     * @param fields  a map of additional field names and their values, to pass to the report. May be {@code null}
     * @return a new data source
     */
    protected abstract JRRewindableDataSource createDataSource(Iterable<T> objects, Map<String, Object> fields);

    /**
     * Returns the archetype service.
     *
     * @return the archetype service
     */
    protected IArchetypeService getArchetypeService() {
        return service;
    }

    /**
     * Returns the lookup service.
     *
     * @return the lookup service
     */
    protected ILookupService getLookupService() {
        return lookups;
    }

    /**
     * Returns the document handlers.
     *
     * @return the document handlers
     */
    protected DocumentHandlers getDocumentHandlers() {
        return handlers;
    }

    /**
     * Returns the JXPath extension functions.
     *
     * @return the JXPath extension functions
     */
    protected Functions getFunctions() {
        return functions;
    }

    /**
     * Returns the default report parameters to use when filling the report.
     *
     * @return the report parameters
     */
    protected Map<String, Object> getDefaultParameters() {
        return new HashMap<String, Object>();
    }

    /**
     * Converts a report to a document.
     *
     * @param report     the report to convert
     * @param parameters export parameters
     * @param mimeType   the mime-type of the document
     * @return a document containing the report
     * @throws ReportException           for any error
     * @throws ArchetypeServiceException for any archetype service error
     */
    protected Document export(JasperPrint report, Map<String, Object> parameters, String mimeType) {
        Document document;
        try {
            ByteArrayOutputStream output = new ByteArrayOutputStream(2048);
            String ext = export(report, output, parameters, mimeType);
            byte[] data = output.toByteArray();

            String name = report.getName() + "." + ext;
            DocumentHandler handler = handlers.get(name, DocumentArchetypes.DEFAULT_DOCUMENT, mimeType);
            ByteArrayInputStream stream = new ByteArrayInputStream(data);
            document = handler.create(name, stream, mimeType, data.length);
        } catch (DocumentException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        } catch (JRException exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        } catch (Exception exception) {
            throw new ReportException(exception, FailedToGenerateReport, exception.getMessage());
        }
        return document;
    }

    /**
     * Exports a report to a stream as the specified mime type.
     *
     * @param report     the report to export
     * @param stream     the stream to write to
     * @param mimeType   the mime type to export as
     * @param parameters export parameters
     * @return the file name extension of the mime-type
     * @throws JRException if the export fails
     */
    protected String export(JasperPrint report, OutputStream stream, Map<String, Object> parameters,
            String mimeType) throws JRException {
        String ext;
        if (DocFormats.PDF_TYPE.equals(mimeType)) {
            exportToPDF(report, stream);
            ext = DocFormats.PDF_EXT;
        } else if (DocFormats.RTF_TYPE.equals(mimeType)) {
            exportToRTF(report, stream);
            ext = DocFormats.RTF_EXT;
        } else if (DocFormats.XLS_TYPE.equals(mimeType)) {
            exportToXLS(report, stream);
            ext = DocFormats.XLS_EXT;
        } else if (DocFormats.CSV_TYPE.equals(mimeType)) {
            exportToCSV(report, stream);
            ext = DocFormats.CSV_EXT;
        } else if (DocFormats.XML_TYPE.equals(mimeType)) {
            exportToXML(report, stream);
            ext = DocFormats.XML_EXT;
        } else if (DocFormats.TEXT_TYPE.equals(mimeType)) {
            exportToText(report, stream, parameters);
            ext = DocFormats.TEXT_EXT;
        } else {
            throw new ReportException(UnsupportedMimeType, mimeType);
        }
        return ext;
    }

    /**
     * Exports a generated jasper report to PDF.
     *
     * @param report the report
     * @param stream the stream to write to
     * @throws JRException if the export fails
     */
    private void exportToPDF(JasperPrint report, OutputStream stream) throws JRException {
        exportStream(report, stream, new JRPdfExporter());
    }

    /**
     * Exports a generated jasper report to an RTF stream.
     *
     * @param report the report
     * @param stream the stream to write to
     * @throws JRException if the export fails
     */
    private void exportToRTF(JasperPrint report, OutputStream stream) throws JRException {
        exportWriter(report, stream, new JRRtfExporter());
    }

    /**
     * Exports a generated jasper report to a stream as XLS.
     *
     * @param report the report
     * @param stream the stream to write to
     * @throws JRException if the export fails
     */
    private void exportToXLS(JasperPrint report, OutputStream stream) throws JRException {
        JRXlsExporter exporter = new JRXlsExporter();
        SimpleXlsReportConfiguration configuration = new SimpleXlsReportConfiguration();
        configuration.setDetectCellType(true);
        configuration.setWhitePageBackground(false);
        configuration.setIgnorePageMargins(true);
        configuration.setCollapseRowSpan(true);
        configuration.setRemoveEmptySpaceBetweenRows(true);
        configuration.setRemoveEmptySpaceBetweenColumns(true);
        exporter.setConfiguration(configuration);
        exportStream(report, stream, exporter);
    }

    /**
     * Exports a generated jasper report to a stream as CSV.
     *
     * @param report the report
     * @param stream the stream to write to
     * @throws JRException if the export fails
     */
    private void exportToCSV(JasperPrint report, OutputStream stream) throws JRException {
        JRCsvExporter exporter = new JRCsvExporter();
        SimpleCsvExporterConfiguration configuration = new SimpleCsvExporterConfiguration();
        configuration.setFieldDelimiter(",");
        configuration.setRecordDelimiter("\n");
        exporter.setConfiguration(configuration);
        exportWriter(report, stream, exporter);
    }

    /**
     * Exports a generated jasper report to a stream as XML.
     *
     * @param report the report
     * @param stream the stream to write to
     * @throws JRException if the export fails
     */
    private void exportToXML(JasperPrint report, OutputStream stream) throws JRException {
        exportWriter(report, stream, new JRXmlExporter());
    }

    /**
     * Exports a generated jasper report to a stream as plain text.
     *
     * @param report the report
     * @param stream the stream to write to
     * @throws JRException if the export fails
     */
    private void exportToText(JasperPrint report, OutputStream stream, Map<String, Object> parameters)
            throws JRException {
        JRTextExporter exporter = new JRTextExporter();
        ReportContext context = JasperReportHelper.createReportContext(parameters);
        exporter.setReportContext(context);
        exportWriter(report, stream, exporter);
    }

    /**
     * Exports a report using a stream.
     *
     * @param report   the report to export
     * @param stream   the stream to export to
     * @param exporter the exporter
     * @throws JRException if the export fails
     */
    private void exportStream(JasperPrint report, OutputStream stream,
            Exporter<ExporterInput, ? extends ReportExportConfiguration, ? extends ExporterConfiguration, OutputStreamExporterOutput> exporter)
            throws JRException {
        exporter.setExporterInput(new SimpleExporterInput(report));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(stream));
        exporter.exportReport();
    }

    /**
     * Exports a report using a writer.
     *
     * @param report   the report to export
     * @param stream   the underlying stream to export to
     * @param exporter the exporter
     * @throws JRException if the export fails
     */
    private void exportWriter(JasperPrint report, OutputStream stream,
            Exporter<ExporterInput, ? extends ReportExportConfiguration, ? extends ExporterConfiguration, WriterExporterOutput> exporter)
            throws JRException {
        exporter.setExporterInput(new SimpleExporterInput(report));
        exporter.setExporterOutput(new SimpleWriterExporterOutput(stream));
        exporter.exportReport();
    }

    /**
     * Prints a {@code JasperPrint} to a printer.
     *
     * @param print      the object to print
     * @param properties the print properties
     * @throws ReportException if {@code print} contains no pages
     * @throws JRException     for any error
     */
    private void print(JasperPrint print, PrintProperties properties) throws JRException {
        if (print.getPages().isEmpty()) {
            throw new ReportException(NoPagesToPrint);
        }
        if (log.isDebugEnabled()) {
            log.debug("PrinterName: " + properties.getPrinterName());
        }

        JRPrintServiceExporter exporter = new JRPrintServiceExporter();
        exporter.setExporterInput(new SimpleExporterInput(print));
        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
        aset.add(new Copies(properties.getCopies()));
        MediaSizeName mediaSize = properties.getMediaSize();
        OrientationRequested orientation = properties.getOrientation();
        MediaTray tray = properties.getMediaTray();
        Sides sides = properties.getSides();
        if (mediaSize != null) {
            if (log.isDebugEnabled()) {
                log.debug("MediaSizeName: " + mediaSize);
            }
            aset.add(mediaSize);
        }
        if (orientation != null) {
            if (log.isDebugEnabled()) {
                log.debug("Orientation: " + orientation);
            }
            aset.add(orientation);
        }
        if (tray != null) {
            if (log.isDebugEnabled()) {
                log.debug("MediaTray: " + tray);
            }
            aset.add(tray);
        }
        if (sides != null) {
            if (log.isDebugEnabled()) {
                log.debug("Sides: " + sides);
            }
            aset.add(sides);
        }
        SimplePrintServiceExporterConfiguration printConfiguration = new SimplePrintServiceExporterConfiguration();
        printConfiguration.setPrintRequestAttributeSet(aset);
        // set the printer name
        PrintServiceAttributeSet serviceAttributeSet = new HashPrintServiceAttributeSet();
        serviceAttributeSet.add(new PrinterName(properties.getPrinterName(), null));
        printConfiguration.setPrintServiceAttributeSet(serviceAttributeSet);
        exporter.setConfiguration(printConfiguration);
        // print it
        exporter.exportReport();
    }

    /**
     * Returns the expression evaluator.
     *
     * @return the expression evaluator
     * @throws JRException if the evaluator can't be loaded
     */
    private JREvaluator getEvaluator() throws JRException {
        if (evaluator == null) {
            evaluator = JasperCompileManager.loadEvaluator(getReport());
        }
        return evaluator;
    }

    /**
     * Initialises a JDBC data source, if required.
     *
     * @param params the report parameters
     * @param fields a map of additional field names and their values, to pass to the report. May be {@code null}
     * @param report the report
     * @throws JRException if the data source cannot be created
     */
    private JRQueryExecuter initDataSource(Map<String, Object> params, Map<String, Object> fields,
            JasperReport report) throws JRException {
        JRQueryExecuter executer = null;
        Connection connection = (Connection) params.get(JRParameter.REPORT_CONNECTION);
        if (connection != null) {
            executer = new JDBCQueryExecuter(report.getMainDataset(), params, fields, service);
            JRDataSource dataSource = executer.createDatasource();
            params.put(JRParameter.REPORT_DATA_SOURCE, dataSource);
        }
        return executer;
    }

}