/* *****************************************************************************
* 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;
}
}