/* ***************************************************************************** * 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.view; 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.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Shell; import org.nightlabs.base.ui.job.Job; import org.nightlabs.base.ui.util.RCPUtil; import org.nightlabs.jfire.base.jdo.GlobalJDOManagerProvider; import org.nightlabs.jfire.reporting.Birt; 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.config.ReportViewPrintConfigModule; import org.nightlabs.jfire.reporting.ui.config.ReportViewPrintConfigModule.UseCaseConfig; 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.jfire.reporting.ui.viewer.ReportViewer; import org.nightlabs.jfire.reporting.ui.viewer.ReportViewerFactory; import org.nightlabs.jfire.reporting.ui.viewer.ReportViewerRegistry; import org.nightlabs.progress.ProgressMonitor; import org.nightlabs.progress.SubProgressMonitor; /** * Abstract Action that can be used as basis for actions that show reports in a {@link ReportViewer} * . The parameter acquisition and printing is implemented completely, subclasses may override the * {@link ReportUseCase} and {@link Locale} used for the printing (See * {@link #getReportUseCaseID(ReportRegistryItemID, Map, ProgressMonitor)} and * {@link #getRenderRequestLocale(ReportRegistryItemID, Map, ProgressMonitor)}). * * @author Alexander Bieber <alex [AT] nightlabs [DOT] de> */ public abstract class AbstractViewReportLayoutAction extends ReportRegistryItemAction { /** * Create a new {@link AbstractViewReportLayoutAction}. */ public AbstractViewReportLayoutAction() { super(); } /** * Create a new {@link AbstractViewReportLayoutAction}. * * @param text The actions text. */ public AbstractViewReportLayoutAction(String text) { super(text); } /** * Create a new {@link AbstractViewReportLayoutAction}. * * @param text The actions text. * @param image The actions image. */ public AbstractViewReportLayoutAction(String text, ImageDescriptor image) { super(text, image); } /** * Create a new {@link AbstractViewReportLayoutAction}. * * @param text The actions text. * @param style The actions style. */ public AbstractViewReportLayoutAction(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; } /** * 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. * @param monitor The monitor to report progress to. * @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, ProgressMonitor monitor) { return null; } /* (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)); } /** The parameters to use for the next run, set to <code>null</code> after each run. */ private Map<String, Object> nextRunParams = null; /** user information don't override nextRunParams **/ private boolean askUser = false; /** * * @param reportRegistryItems */ public void runWithRegistryItemIDs(final Collection<ReportRegistryItemID> reportRegistryItems) { final Shell activeShell = RCPUtil.getActiveShell(); Job viewJob = new Job(Messages.getString("org.nightlabs.jfire.reporting.ui.layout.action.view.AbstractViewReportLayoutAction.printJob.name")) { //$NON-NLS-1$ @Override protected IStatus run(ProgressMonitor monitor) { monitor.beginTask(Messages.getString("org.nightlabs.jfire.reporting.ui.layout.action.view.AbstractViewReportLayoutAction.task.searchPrintPreviewConfiguration"), 6); //$NON-NLS-1$ Map<String, Object> params = null; boolean paramsSet = false; if (nextRunParams != null) { params = nextRunParams; paramsSet = !askUser; nextRunParams = null; }; String errorMessages = ""; //$NON-NLS-1$ for (ReportRegistryItemID itemID : reportRegistryItems) { if (!paramsSet) { // if no parameters set by now, get them from the user WizardResult dialogResult = ReportParameterWizard.openResult(activeShell, itemID, false); if (!dialogResult.isAcquisitionFinished()) return Status.OK_STATUS; Map<String, Object> parameters = dialogResult.getParameters(); if (params == null) { params = parameters; } else { params.putAll(parameters); } paramsSet = true; } String useCaseID = getReportUseCaseID(itemID, params, new SubProgressMonitor(monitor, 3)); if (useCaseID == null) { // Try to lookup the UseCase by the reportLayoutType ReportUseCase useCase = ReportUseCaseRegistry.sharedInstance().getReportUseCaseByLayoutType(itemID.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) { errorMessages = addErrMessage(errorMessages, "No useCaseID was specified and no useCase could be found for the reportLayoutType: "+itemID.reportRegistryItemType); //$NON-NLS-1$ continue; } useCaseID = useCase.getId(); } ReportViewPrintConfigModule cfMod = ReportViewPrintConfigModule.sharedInstance(); UseCaseConfig useCaseConfig = cfMod.getReportUseCaseConfigs().get(useCaseID); Birt.OutputFormat outFormat = getOutputFormat(useCaseConfig); String reportViewerID = null; if (useCaseConfig != null) reportViewerID = useCaseConfig.getReportViewerID(); if (reportViewerID == null) reportViewerID = ReportViewerRegistry.DEFAULT_REPORT_VIEWER_ID; ReportViewerFactory viewerFactory = ReportViewerRegistry.sharedInstance().getReportViewerFactory(reportViewerID); if (viewerFactory == null) viewerFactory = ReportViewerRegistry.sharedInstance().getReportViewerFactory(ReportViewerRegistry.DEFAULT_REPORT_VIEWER_ID); if (viewerFactory == null) { addErrMessage(errorMessages, "No ReportViewerFactory could be found for reportViewerID: '"+reportViewerID+"'"); //$NON-NLS-1$ //$NON-NLS-2$ continue; } ReportViewer viewer = viewerFactory.createReportViewer(); RenderReportRequest renderRequest = new RenderReportRequest(itemID, params, outFormat); Locale requestLocale = getRenderRequestLocale(itemID, params, new SubProgressMonitor(monitor, 3)); if (requestLocale != null) { renderRequest.setLocale(requestLocale); } else { renderRequest.setLocale(Locale.getDefault()); } viewer.showReport(renderRequest); } if (!"".equals(errorMessages)) //$NON-NLS-1$ // TODO: Maybe throw typed exception wrapped in RuntimeException throw new IllegalStateException(errorMessages); return Status.OK_STATUS; } }; viewJob.schedule(); } /** * Adds an error to the given list of messages separated by a linebreak. * * @param errorMessages The list of messages where to add the next one. * @param addition The addition to add to the list. * @return The new list with the added message. */ private String addErrMessage(String errorMessages, String addition) { if (errorMessages == null) errorMessages = ""; if (errorMessages.isEmpty()) errorMessages = errorMessages + "\n"; //$NON-NLS-1$ if (addition != null && !addition.isEmpty()) errorMessages = errorMessages + addition; return errorMessages; } /** * 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 Montior to report progress to. * @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(); } /** * 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; } /** * If true, than will be shown the {@link ReportParameterWizard} * @param askUser */ public void setAskUser(boolean askUser) { this.askUser = askUser; } protected Birt.OutputFormat getOutputFormat(UseCaseConfig useCaseConfig) { String format = "html"; //$NON-NLS-1$ if (useCaseConfig != null) format = useCaseConfig.getViewerFormat(); Birt.OutputFormat outFormat = Birt.OutputFormat.valueOf(format); return outFormat; } }