/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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 Lesser General Public License for more details.
*
* Copyright (c) 2009 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.extensions.modules.java14print;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.ServiceUI;
import javax.print.SimpleDoc;
import javax.print.attribute.Attribute;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.JobName;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaName;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PageRanges;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.PageDefinition;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.event.ReportProgressListener;
import org.pentaho.reporting.engine.classic.core.modules.gui.print.PrintUtil;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.graphics.PrintReportProcessor;
/**
* Creation-Date: 05.09.2005, 19:11:47
*
* @author Thomas Morgner
*/
public class Java14PrintUtil
{
private static final Log logger = LogFactory.getLog(Java14PrintUtil.class);
public static final int CONFIGURATION_VALID = 0;
public static final int CONFIGURATION_REPAGINATE = 1;
public static final int CONFIGURATION_SHOW_DIALOG = 2;
private static final double POINTS_PER_INCH = 72.0;
private Java14PrintUtil()
{
}
/**
* This tests, whether the given attribute set defines the same page properties as the given JFreeReport object.
* <p/>
* While showing the print dialog, the user has the chance to alter the page format of the print job. When that
* happens, we have to repaginate the whole report, which may render the users page range input invalid. In that case,
* we will have to redisplay the dialog.
*
* @param attributes
* @param report
* @return
*/
public static int isValidConfiguration(final PrintRequestAttributeSet attributes,
final MasterReport report)
{
final PrintRequestAttributeSet reportAttributes =
copyConfiguration(null, report);
// now, compare that minimal set with the given attribute collection.
final Attribute[] printAttribs = reportAttributes.toArray();
boolean invalidConfig = false;
for (int i = 0; i < printAttribs.length; i++)
{
final Attribute attrib = printAttribs[i];
if (attributes.containsValue(attrib) == false)
{
invalidConfig = true;
break;
}
}
if (invalidConfig == false)
{
return CONFIGURATION_VALID;
}
if (attributes.containsKey(PageRanges.class))
{
return CONFIGURATION_SHOW_DIALOG;
}
return CONFIGURATION_REPAGINATE;
}
/**
* This method replaces the media definition from the given attribute set with the one found in the report itself.
* <p/>
* If no JobName is set, a default jobname will be assigned.
*
* @param attributes
* @param report
* @return
*/
public static PrintRequestAttributeSet copyConfiguration
(PrintRequestAttributeSet attributes,
final MasterReport report)
{
if (attributes == null)
{
attributes = new HashPrintRequestAttributeSet();
}
// for now, be lazy, assume that the first page is the reference
final PageDefinition pdef = report.getPageDefinition();
final PageFormat format = pdef.getPageFormat(0);
final Paper paper = format.getPaper();
final Media media = MediaSize.findMedia((float) (paper.getWidth() / POINTS_PER_INCH),
(float) (paper.getHeight() / POINTS_PER_INCH), Size2DSyntax.INCH);
attributes.add(media);
final MediaPrintableArea printableArea = new MediaPrintableArea
((float) (paper.getImageableX() / POINTS_PER_INCH),
(float) (paper.getImageableY() / POINTS_PER_INCH),
(float) (paper.getImageableWidth() / POINTS_PER_INCH),
(float) (paper.getImageableHeight() / POINTS_PER_INCH),
Size2DSyntax.INCH);
attributes.add(printableArea);
attributes.add(mapOrientation(format.getOrientation()));
return attributes;
}
public static PrintRequestAttributeSet copyAuxillaryAttributes
(PrintRequestAttributeSet attributes,
final MasterReport report)
{
if (attributes == null)
{
attributes = new HashPrintRequestAttributeSet();
}
if (attributes.containsKey(JobName.class) == false)
{
final String jobName = report.getReportConfiguration().getConfigProperty
(PrintUtil.PRINTER_JOB_NAME_KEY, report.getTitle());
if (jobName != null)
{
attributes.add(new JobName(jobName, null));
}
}
if (attributes.containsKey(Copies.class) == false)
{
final int numberOfCopies =
PrintUtil.getNumberOfCopies(report.getReportConfiguration());
attributes.add(new Copies(numberOfCopies));
}
return attributes;
}
public static PageFormat extractPageFormat(final PrintRequestAttributeSet attributeSet)
{
final Media media = (Media) attributeSet.get(Media.class);
final MediaPrintableArea printableArea =
(MediaPrintableArea) attributeSet.get(MediaPrintableArea.class);
final OrientationRequested orientationRequested =
(OrientationRequested) attributeSet.get(OrientationRequested.class);
final MediaSize mediaSize = lookupMediaSize(media);
if (mediaSize == null)
{
logger.warn("Unknown media encountered, unable to compute page sizes.");
}
final PageFormat pageFormat = new PageFormat();
pageFormat.setPaper(createPaper(mediaSize, printableArea));
if (OrientationRequested.PORTRAIT.equals(orientationRequested))
{
pageFormat.setOrientation(PageFormat.PORTRAIT);
}
else if (OrientationRequested.LANDSCAPE.equals(orientationRequested))
{
pageFormat.setOrientation(PageFormat.LANDSCAPE);
}
else if (OrientationRequested.REVERSE_LANDSCAPE.equals
(orientationRequested))
{
pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);
}
else if (OrientationRequested.REVERSE_PORTRAIT.equals(orientationRequested))
{
pageFormat.setOrientation(PageFormat.PORTRAIT);
}
return pageFormat;
}
private static Paper createPaper(final MediaSize mediaSize,
final MediaPrintableArea printableArea)
{
final Paper paper = new Paper();
if (mediaSize != null)
{
paper.setSize(mediaSize.getX(Size2DSyntax.INCH) * POINTS_PER_INCH,
mediaSize.getY(Size2DSyntax.INCH) * POINTS_PER_INCH);
}
if (printableArea != null)
{
paper.setImageableArea
(printableArea.getX(Size2DSyntax.INCH) * POINTS_PER_INCH,
printableArea.getY(Size2DSyntax.INCH) * POINTS_PER_INCH,
printableArea.getWidth(Size2DSyntax.INCH) * POINTS_PER_INCH,
printableArea.getHeight(Size2DSyntax.INCH) * POINTS_PER_INCH);
}
return paper;
}
private static MediaSize lookupMediaSize(final Media media)
{
if (media instanceof MediaSizeName)
{
return MediaSize.getMediaSizeForName((MediaSizeName) media);
}
else if (media instanceof MediaName)
{
if (media.equals(MediaName.ISO_A4_TRANSPARENT) ||
media.equals(MediaName.ISO_A4_WHITE))
{
return MediaSize.getMediaSizeForName(MediaSizeName.ISO_A4);
}
else if (media.equals(MediaName.NA_LETTER_TRANSPARENT) ||
media.equals(MediaName.NA_LETTER_WHITE))
{
return MediaSize.getMediaSizeForName(MediaSizeName.NA_LETTER);
}
}
return null;
}
private static OrientationRequested mapOrientation(final int orientation)
{
switch (orientation)
{
case PageFormat.LANDSCAPE:
return OrientationRequested.LANDSCAPE;
case PageFormat.REVERSE_LANDSCAPE:
return OrientationRequested.REVERSE_LANDSCAPE;
case PageFormat.PORTRAIT:
return OrientationRequested.PORTRAIT;
default:
throw new IllegalArgumentException
("The given value is no valid PageFormat orientation.");
}
}
public static void printDirectly(final MasterReport report,
PrintService printService)
throws PrintException, ReportProcessingException
{
// with that method we do not use the PrintService UI ..
// it is up to the user to supply a valid print service that
// supports the Pageable printing.
if (printService == null)
{
printService = lookupPrintService();
}
else
{
if (printService.isDocFlavorSupported(DocFlavor.SERVICE_FORMATTED.PAGEABLE) == false)
{
throw new PrintException
("The print service implementation does not support the Pageable Flavor.");
}
}
PrintRequestAttributeSet attributes =
Java14PrintUtil.copyConfiguration(null, report);
attributes = Java14PrintUtil.copyAuxillaryAttributes(attributes, report);
final PrintReportProcessor reportPane = new PrintReportProcessor(report);
final DocPrintJob job = printService.createPrintJob();
final SimpleDoc document = new SimpleDoc
(reportPane, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
try
{
job.print(document, attributes);
}
finally
{
reportPane.close();
}
}
private static PrintService lookupPrintService()
throws PrintException
{
final PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
if (defaultService != null &&
defaultService.isDocFlavorSupported(DocFlavor.SERVICE_FORMATTED.PAGEABLE))
{
return defaultService;
}
final PrintService printService;
final PrintService[] services = PrintServiceLookup.lookupPrintServices(
DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
if (services.length == 0)
{
throw new PrintException
("Unable to find a matching print service implementation.");
}
printService = services[0];
return printService;
}
public static boolean print(final MasterReport report)
throws PrintException, ReportProcessingException
{
return print(report, null);
}
public static boolean print(final MasterReport report, final ReportProgressListener progressListener)
throws PrintException, ReportProcessingException
{
final PrintService[] services = PrintServiceLookup.lookupPrintServices(
DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
if (services.length == 0)
{
throw new PrintException
("Unable to find a matching print service implementation.");
}
PrintRequestAttributeSet attributes =
Java14PrintUtil.copyConfiguration(null, report);
attributes = Java14PrintUtil.copyAuxillaryAttributes(attributes, report);
final PrintService service = ServiceUI.printDialog
(null, 50, 50, services, lookupPrintService(),
DocFlavor.SERVICE_FORMATTED.PAGEABLE, attributes);
if (service == null)
{
return false;
}
final PrintReportProcessor reportPane = new PrintReportProcessor(report);
if (progressListener != null)
{
reportPane.addReportProgressListener(progressListener);
}
try
{
reportPane.fireProcessingStarted();
final DocPrintJob job = service.createPrintJob();
final SimpleDoc document = new SimpleDoc
(reportPane, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
job.print(document, attributes);
}
finally
{
reportPane.fireProcessingFinished();
reportPane.close();
if (progressListener != null)
{
reportPane.removeReportProgressListener(progressListener);
}
}
return true;
}
}