001 /**
002 * ========================================
003 * JFreeReport : a free Java report library
004 * ========================================
005 *
006 * Project Info: http://reporting.pentaho.org/
007 *
008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009 *
010 * This library is free software; you can redistribute it and/or modify it under the terms
011 * of the GNU Lesser General Public License as published by the Free Software Foundation;
012 * either version 2.1 of the License, or (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016 * See the GNU Lesser General Public License for more details.
017 *
018 * You should have received a copy of the GNU Lesser General Public License along with this
019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020 * Boston, MA 02111-1307, USA.
021 *
022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023 * in the United States and other countries.]
024 *
025 * ------------
026 * $Id: AbstractExportDialog.java,v 1.7 2007/04/01 18:49:30 taqua Exp $
027 * ------------
028 * (C) Copyright 2000-2005, by Object Refinery Limited.
029 * (C) Copyright 2005-2007, by Pentaho Corporation.
030 */
031 package org.jfree.report.modules.gui.swing.common;
032
033 import java.awt.Dialog;
034 import java.awt.Frame;
035 import java.awt.event.ActionEvent;
036 import java.awt.event.WindowAdapter;
037 import java.awt.event.WindowEvent;
038 import java.io.File;
039 import java.util.Enumeration;
040 import java.util.Locale;
041 import java.util.ResourceBundle;
042 import javax.swing.AbstractAction;
043 import javax.swing.Action;
044 import javax.swing.JDialog;
045
046 import org.jfree.base.config.ModifiableConfiguration;
047 import org.jfree.report.flow.ReportJob;
048 import org.jfree.report.modules.gui.common.GuiContext;
049 import org.jfree.report.modules.preferences.base.ConfigFactory;
050 import org.jfree.report.modules.preferences.base.ConfigStorage;
051 import org.jfree.report.modules.preferences.base.ConfigStoreException;
052 import org.jfree.util.Configuration;
053 import org.jfree.util.Log;
054
055 public abstract class AbstractExportDialog extends JDialog
056 implements ExportDialog
057 {
058 /**
059 * Internal action class to confirm the dialog and to validate the input.
060 */
061 private class ConfirmAction extends AbstractAction
062 {
063 /**
064 * Default constructor.
065 */
066 public ConfirmAction(final ResourceBundle resources)
067 {
068 putValue(Action.NAME, resources.getString("OptionPane.okButtonText"));
069 }
070
071 /**
072 * Receives notification that the action has occurred.
073 *
074 * @param e the action event.
075 */
076 public void actionPerformed(final ActionEvent e)
077 {
078 if (performValidate() && performConfirm())
079 {
080 setConfirmed(true);
081 setVisible(false);
082 }
083 }
084 }
085
086 /**
087 * Internal action class to cancel the report processing.
088 */
089 private class CancelAction extends AbstractAction
090 {
091 /**
092 * Default constructor.
093 */
094 public CancelAction(final ResourceBundle resources)
095 {
096 putValue(Action.NAME, resources.getString("OptionPane.cancelButtonText"));
097 }
098
099 /**
100 * Receives notification that the action has occurred.
101 *
102 * @param e the action event.
103 */
104 public void actionPerformed(final ActionEvent e)
105 {
106 setConfirmed(false);
107 setVisible(false);
108 }
109 }
110
111 private class ExportDialogValidator extends FormValidator
112 {
113 public ExportDialogValidator()
114 {
115 super();
116 }
117
118 public boolean performValidate()
119 {
120 return AbstractExportDialog.this.performValidate();
121 }
122
123 public Action getConfirmAction()
124 {
125 return AbstractExportDialog.this.getConfirmAction();
126 }
127 }
128
129 private class WindowCloseHandler extends WindowAdapter
130 {
131 public WindowCloseHandler()
132 {
133 }
134
135 /**
136 * Invoked when a window is in the process of being closed. The close
137 * operation can be overridden at this point.
138 */
139 public void windowClosing(final WindowEvent e)
140 {
141 final Action cancelAction = getCancelAction();
142 if (cancelAction != null)
143 {
144 cancelAction.actionPerformed(null);
145 }
146 else
147 {
148 setConfirmed(false);
149 setVisible(false);
150 }
151 }
152 }
153
154 private Action cancelAction;
155 private Action confirmAction;
156 private FormValidator formValidator;
157 private ResourceBundle resources;
158 private boolean confirmed;
159 private ReportJob reportJob;
160 private GuiContext guiContext;
161
162 /**
163 * Creates a non-modal dialog without a title and without a specified
164 * <code>Frame</code> owner. A shared, hidden frame will be set as the owner
165 * of the dialog.
166 */
167 public AbstractExportDialog()
168 {
169 initialize();
170 }
171
172 /**
173 * Creates a non-modal dialog without a title with the specified
174 * <code>Frame</code> as its owner. If <code>owner</code> is
175 * <code>null</code>, a shared, hidden frame will be set as the owner of the
176 * dialog.
177 *
178 * @param owner the <code>Frame</code> from which the dialog is displayed
179 */
180 public AbstractExportDialog(final Frame owner)
181 {
182 super(owner);
183 initialize();
184 }
185
186
187 /**
188 * Creates a non-modal dialog without a title with the specified
189 * <code>Dialog</code> as its owner.
190 *
191 * @param owner the non-null <code>Dialog</code> from which the dialog is
192 * displayed
193 */
194 public AbstractExportDialog(final Dialog owner)
195 {
196 super(owner);
197 initialize();
198 }
199
200 private void initialize()
201 {
202 ResourceBundle resources = ResourceBundle.getBundle(SwingCommonModule.BUNDLE_NAME);
203
204 cancelAction = new CancelAction(resources);
205 confirmAction = new ConfirmAction(resources);
206
207 formValidator = new ExportDialogValidator();
208 setModal(true);
209 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
210 addWindowListener(new WindowCloseHandler());
211 }
212
213
214 public abstract JStatusBar getStatusBar();
215
216 protected Action getCancelAction()
217 {
218 return cancelAction;
219 }
220
221 protected void setCancelAction(final Action cancelAction)
222 {
223 this.cancelAction = cancelAction;
224 }
225
226 protected Action getConfirmAction()
227 {
228 return confirmAction;
229 }
230
231 protected void setConfirmAction(final Action confirmAction)
232 {
233 this.confirmAction = confirmAction;
234 }
235
236 protected abstract boolean performValidate();
237
238 protected FormValidator getFormValidator()
239 {
240 return formValidator;
241 }
242
243 protected abstract void initializeFromJob(ReportJob job,
244 final GuiContext guiContext);
245
246 protected ReportJob getReportJob()
247 {
248 return reportJob;
249 }
250
251 protected GuiContext getGuiContext()
252 {
253 return guiContext;
254 }
255
256 /**
257 * Opens the dialog to query all necessary input from the user. This will not
258 * start the processing, as this is done elsewhere.
259 *
260 * @param report the report that should be processed.
261 * @return true, if the processing should continue, false otherwise.
262 */
263 public boolean performQueryForExport(final ReportJob reportJob,
264 final GuiContext guiContext)
265 {
266 this.reportJob = reportJob;
267 this.guiContext = guiContext;
268
269 final Locale locale = reportJob.getReportStructureRoot().getLocale();
270 setLocale(locale);
271 pack();
272 clear();
273 initializeFromJob(reportJob, guiContext);
274
275 final FormValidator formValidator = getFormValidator();
276 formValidator.setEnabled(false);
277 final ModifiableConfiguration repConf = reportJob.getConfiguration();
278 final boolean inputStorageEnabled = isInputStorageEnabled(repConf);
279
280 Configuration loadedConfiguration;
281 if (inputStorageEnabled)
282 {
283 loadedConfiguration = loadFromConfigStore(reportJob, repConf);
284 }
285 else
286 {
287 loadedConfiguration = repConf;
288 }
289
290 setDialogContents(loadedConfiguration);
291
292 formValidator.setEnabled(true);
293 formValidator.handleValidate();
294 setModal(true);
295 setVisible(true);
296 if (isConfirmed() == false)
297 {
298 return false;
299 }
300
301 formValidator.setEnabled(false);
302
303 final Configuration fullDialogContents = grabDialogContents(true);
304 final Enumeration configProperties =
305 fullDialogContents.getConfigProperties();
306 while (configProperties.hasMoreElements())
307 {
308 final String key = (String) configProperties.nextElement();
309 repConf.setConfigProperty(key, fullDialogContents.getConfigProperty(key));
310 }
311
312 if (inputStorageEnabled)
313 {
314 saveToConfigStore(reportJob, repConf);
315 }
316
317 formValidator.setEnabled(true);
318 this.reportJob = null;
319 return true;
320 }
321
322 private void saveToConfigStore(final ReportJob reportJob,
323 final Configuration reportConfiguration)
324 {
325 final String configPath = ConfigFactory.encodePath(
326 reportJob.getName() + getConfigurationSuffix());
327
328 try
329 {
330 final boolean fullStorageEnabled = isFullInputStorageEnabled(reportConfiguration);
331 final Configuration dialogContents = grabDialogContents(fullStorageEnabled);
332 final ConfigStorage storage = ConfigFactory.getInstance().getUserStorage();
333 storage.store(configPath, dialogContents);
334 }
335 catch (ConfigStoreException cse)
336 {
337 Log.debug("Unable to store the defaults in Export export dialog. [" + getClass() + "]");
338 }
339 }
340
341 private Configuration loadFromConfigStore(final ReportJob reportJob,
342 final Configuration defaultConfig)
343 {
344 final String configPath = ConfigFactory.encodePath(
345 reportJob.getName() + getConfigurationSuffix());
346 final ConfigStorage storage = ConfigFactory.getInstance().getUserStorage();
347 try
348 {
349 return storage.load(configPath, defaultConfig);
350 }
351 catch (Exception cse)
352 {
353 Log.debug("Unable to load the defaults in Export export dialog. [" + getClass() + "]");
354 }
355 return defaultConfig;
356 }
357
358 protected abstract String getConfigurationPrefix();
359
360 /**
361 * Returns a new (and not connected to the default config from the job)
362 * configuration containing all properties from the dialog.
363 *
364 * @param full
365 * @return
366 */
367 protected abstract Configuration grabDialogContents(boolean full);
368
369 protected abstract void setDialogContents(Configuration properties);
370
371 protected abstract String getConfigurationSuffix();
372
373 /**
374 * Retrieves the resources for this dialog. If the resources are not
375 * initialized, they get loaded on the first call to this method.
376 *
377 * @return this frames ResourceBundle.
378 */
379 protected ResourceBundle getResources()
380 {
381 if (resources == null)
382 {
383 resources = ResourceBundle.getBundle(getResourceBaseName());
384 }
385 return resources;
386 }
387
388 protected boolean isInputStorageEnabled(Configuration config)
389 {
390 final String confVal = config.getConfigProperty
391 (getConfigurationPrefix() + "StoreDialogContents");
392 return "none".equalsIgnoreCase(confVal) == false;
393 }
394
395 protected boolean isFullInputStorageEnabled(Configuration config)
396 {
397 final String confVal = config.getConfigProperty
398 (getConfigurationPrefix() + "StoreDialogContents");
399 return "all".equalsIgnoreCase(confVal);
400 }
401
402 /**
403 * Returns <code>true</code> if the user confirmed the selection, and
404 * <code>false</code> otherwise. The file should only be saved if the result
405 * is <code>true</code>.
406 *
407 * @return A boolean.
408 */
409 public boolean isConfirmed()
410 {
411 return confirmed;
412 }
413
414 /**
415 * Defines whether this dialog has been finished using the 'OK' or the
416 * 'Cancel' option.
417 *
418 * @param confirmed set to <code>true</code>, if OK was pressed,
419 * <code>false</code> otherwise
420 */
421 protected void setConfirmed(final boolean confirmed)
422 {
423 this.confirmed = confirmed;
424 }
425
426 protected boolean performConfirm()
427 {
428 return true;
429 }
430
431 public abstract void clear();
432
433 protected abstract String getResourceBaseName();
434
435
436 /**
437 * Resolves file names for the exports. An occurence of "~/" at the beginning
438 * of the name will be replaced with the users home directory.
439 *
440 * @param baseDirectory the base directory as specified in the configuration.
441 * @return the file object pointing to that directory.
442 * @throws org.jfree.base.modules.ModuleInitializeException
443 * if an error occured or the directory could
444 * not be created.
445 * @throws IllegalArgumentException if the base directory is null.
446 */
447 protected File resolvePath(String baseDirectory)
448 {
449 if (baseDirectory == null)
450 {
451 throw new IllegalArgumentException("The base directory must not be null");
452 }
453
454 if (baseDirectory.startsWith("~/") == false)
455 {
456 return new File(baseDirectory);
457 }
458 else
459 {
460 final String homeDirectory = System.getProperty("user.home");
461 if ("~/".equals(baseDirectory))
462 {
463 return new File(homeDirectory);
464 }
465 else
466 {
467 baseDirectory = baseDirectory.substring(2);
468 return new File(homeDirectory, baseDirectory);
469 }
470 }
471 }
472 }