/* *****************************************************************************
* JFire - it's hot - Free ERP System - http://jfire.org *
* Copyright (C) 2004-2005 NightLabs - http://NightLabs.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library 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. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
* Or get it online : *
* http://opensource.org/licenses/lgpl-license.php *
* *
* *
******************************************************************************/
package org.nightlabs.jfire.reporting.ui.layout.action.print;
import java.awt.print.PrinterException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import javax.jdo.JDOHelper;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.nightlabs.base.ui.job.Job;
import org.nightlabs.jfire.base.jdo.GlobalJDOManagerProvider;
import org.nightlabs.jfire.reporting.layout.ReportCategory;
import org.nightlabs.jfire.reporting.layout.ReportLayout;
import org.nightlabs.jfire.reporting.layout.ReportRegistryItem;
import org.nightlabs.jfire.reporting.layout.id.ReportRegistryItemID;
import org.nightlabs.jfire.reporting.layout.render.RenderReportRequest;
import org.nightlabs.jfire.reporting.ui.ReportingPlugin;
import org.nightlabs.jfire.reporting.ui.config.ReportUseCase;
import org.nightlabs.jfire.reporting.ui.config.ReportUseCaseRegistry;
import org.nightlabs.jfire.reporting.ui.layout.action.ReportRegistryItemAction;
import org.nightlabs.jfire.reporting.ui.parameter.ReportParameterWizard;
import org.nightlabs.jfire.reporting.ui.parameter.ReportParameterWizard.WizardResult;
import org.nightlabs.jfire.reporting.ui.resource.Messages;
import org.nightlabs.progress.ProgressMonitor;
import org.nightlabs.progress.SubProgressMonitor;
/**
* Abstract Action that can be used as basis for actions that print reports.
* The parameter acquisition and printing is implemented completely, subclasses
* may override the {@link ReportUseCase} and {@link Locale} used for the printing.
*
* @author Alexander Bieber <!-- alex [AT] nightlabs [DOT] de -->
*/
public abstract class AbstractPrintReportLayoutAction extends ReportRegistryItemAction {
/**
* Create a new {@link AbstractPrintReportLayoutAction}.
*/
public AbstractPrintReportLayoutAction() {
}
/**
* Create a new {@link AbstractPrintReportLayoutAction}.
*
* @param text The actions text,
*/
public AbstractPrintReportLayoutAction(String text) {
super(text);
}
/**
* Create a new {@link AbstractPrintReportLayoutAction}.
*
* @param text The actions text,
* @param image The actions image.
*/
public AbstractPrintReportLayoutAction(String text, ImageDescriptor image) {
super(text, image);
}
/**
* Create a new {@link AbstractPrintReportLayoutAction}.
*
* @param text The actions text.
* @param style The actions style.
*/
public AbstractPrintReportLayoutAction(String text, int style) {
super(text, style);
}
/**
* Extracts all {@link ReportRegistryItemID} of the given {@link ReportRegistryItem}s
* given that they are a {@link ReportLayout} and no {@link ReportCategory}.
*
* @param reportRegistryItems The {@link ReportRegistryItem}s to filter.
* @return A collection with only {@link ReportRegistryItem}s of {@link ReportLayout}s.
*/
protected Collection<ReportRegistryItemID> extractReportLayouts(Collection<ReportRegistryItem> reportRegistryItems) {
Collection<ReportRegistryItemID> itemIDs = new ArrayList<ReportRegistryItemID>();
for (ReportRegistryItem item : reportRegistryItems) {
ReportRegistryItemID id = (ReportRegistryItemID)JDOHelper.getObjectId(item);
if (ReportLayout.class.isAssignableFrom(GlobalJDOManagerProvider.sharedInstance().getObjectID2PCClassMap().getPersistenceCapableClass(id))) {
itemIDs.add(id);
}
}
return itemIDs;
}
/* (non-Javadoc)
* @see org.nightlabs.jfire.reporting.ui.layout.action.ReportRegistryItemAction#run(java.util.Collection)
*/
@Override
public void run(Collection<ReportRegistryItem> reportRegistryItems) {
runWithRegistryItemIDs(extractReportLayouts(reportRegistryItems));
}
private Map<String, Object> nextRunParams;
/**
* This method can be overridden in order to define a special {@link ReportUseCase}
* id that should be used to print the given report. The default implementation
* returns <code>null</code> to indicate that the {@link ReportUseCase} should be
* looked up in the configuration or queried from the user.
*
* @param reportID The id of the report to print.
* @param params The parameter the report should be printed with.
* @return The id of the {@link ReportUseCase} to use, or <code>null</code> to indicate that
* the {@link ReportUseCase} appropriate for the given report.
*/
protected String getReportUseCaseID(ReportRegistryItemID reportID, Map<String, Object> params) {
return null;
}
/**
* This method will print all given reports. It will either use the parameters set
* in {@link #setNextRunParams(Map)} or ask the user to provide the report parameters.
*
* @param reportRegistryItems The ids of the reports to print.
*/
public void runWithRegistryItemIDs(final Collection<ReportRegistryItemID> reportRegistryItems) {
Job printJob = new Job(Messages.getString("org.nightlabs.jfire.reporting.ui.layout.action.print.AbstractPrintReportLayoutAction.printJob.name")) { //$NON-NLS-1$
@Override
protected IStatus run(ProgressMonitor monitor) {
monitor.beginTask(Messages.getString("org.nightlabs.jfire.reporting.ui.layout.action.print.AbstractPrintReportLayoutAction.printJob.beginPrintingTask.name"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$
Map<String, Object> params = null;
boolean paramsSet = false;
if (nextRunParams != null) {
params = nextRunParams;
paramsSet = true;
nextRunParams = null;
};
String errorMessages = ""; //$NON-NLS-1$
for (ReportRegistryItemID itemID : reportRegistryItems) {
if (params == null && !paramsSet) {
// if no parameters set by now, get them from the user
WizardResult dialogResult = ReportParameterWizard.openResult(itemID, false);
if (!dialogResult.isAcquisitionFinished())
return Status.OK_STATUS;
params = dialogResult.getParameters();
paramsSet = true;
}
try {
printWithParams(itemID, params, monitor);
} catch (PrinterException e) {
errorMessages = addErrMessage(errorMessages, "Printing failed for "+itemID+": "+e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
continue;
}
}
if (!"".equals(errorMessages)) //$NON-NLS-1$
// TODO: Maybe throw typed exception wrapped in RuntimeException
throw new IllegalStateException(errorMessages);
return Status.OK_STATUS;
}
};
printJob.schedule();
}
/**
* Prints the given report (registryItemID) with the given parameters.
* The {@link ReportUseCase} for the given report will be searched and used for printing.
*
* @param registryItemID The id of the report to print.
* @param params The parameters to use to render the report.
* @param monitor The monitor to report progress to.
* @throws PrinterException If an error occurs while printing.
*/
public void printWithParams(ReportRegistryItemID registryItemID, Map<String, Object> params, ProgressMonitor monitor)
throws PrinterException
{
monitor.beginTask(Messages.getString("org.nightlabs.jfire.reporting.ui.layout.action.print.AbstractPrintReportLayoutAction.task.printingReportLayout"), 6); //$NON-NLS-1$
String useCaseID = getReportUseCaseID(registryItemID, params);
if (useCaseID == null) {
// Try to lookup the UseCase by the reportLayoutType
ReportUseCase useCase = ReportUseCaseRegistry.sharedInstance().getReportUseCaseByLayoutType(registryItemID.reportRegistryItemType);
if (useCase != null)
useCaseID = useCase.getId();
}
if (useCaseID == null) {
// if no usecase found till now, try to find the default/fallback one
ReportUseCase useCase = ReportUseCaseRegistry.sharedInstance().getReportUseCase(ReportingPlugin.DEFAULT_REPORT_USE_CASE_ID);
if (useCase == null) {
throw new PrinterException("No useCaseID could be found. A usecase for the type "+registryItemID.reportRegistryItemType+" could not be found and also the default/fallback usecase seems not to be registered."); //$NON-NLS-1$ //$NON-NLS-2$
}
useCaseID = useCase.getId();
}
RenderReportRequest renderRequest = new RenderReportRequest();
renderRequest.setReportRegistryItemID(registryItemID);
renderRequest.setParameters(params);
Locale requestLocale = getRenderRequestLocale(registryItemID, params, new SubProgressMonitor(monitor, 1));
if (requestLocale != null) {
renderRequest.setLocale(requestLocale);
} else {
renderRequest.setLocale(Locale.getDefault());
}
PrintReportLayoutUtil.printReportLayoutWithDefaultFormat(renderRequest, useCaseID, new SubProgressMonitor(monitor, 5));
monitor.done();
}
/**
* This method is consulted to get the locale the report should be rendered for.
* It's default implementation returns the vm's default locale.
* Subclasses may override this method and return an individual locale for each report.
*
* @param reportID The id of the report to render.
* @param params The parameters of the report.
* @param monitor TODO
* @return The locale the given report should be rendered for, or <code>null</code> to indicate
* that the default locale should be used.
*/
protected Locale getRenderRequestLocale(ReportRegistryItemID reportID, Map<String, Object> params, ProgressMonitor monitor) {
return Locale.getDefault();
}
private String addErrMessage(String errorMessages, String addition) {
if (!"".equals(errorMessages)) //$NON-NLS-1$
errorMessages = errorMessages + "\n"; //$NON-NLS-1$
errorMessages = errorMessages + addition;
return errorMessages;
}
/**
* Sets the parameters that should be used by this action in its next run.
* After the next run the reference to this parameters will be reseted so
* that on the next call the {@link ReportParameterWizard} will be shown
* if no other parameters were set.
*
* @param nextRunParams The parameters to use for the next run of this action.
*/
public void setNextRunParams(Map<String, Object> nextRunParams) {
this.nextRunParams = nextRunParams;
}
}