Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / extension / ProjectExtension.java @ 42221

History | View | Annotate | Download (24.1 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.app.extension;
25

    
26
import java.awt.Component;
27
import java.io.File;
28
import java.text.MessageFormat;
29
import java.util.ArrayList;
30
import java.util.Iterator;
31
import java.util.List;
32
import java.util.prefs.Preferences;
33

    
34
import javax.swing.JOptionPane;
35
import javax.swing.SwingUtilities;
36

    
37
import org.slf4j.Logger;
38
import org.slf4j.LoggerFactory;
39

    
40
import org.gvsig.tools.util.ArrayUtils;
41

    
42
import org.apache.commons.lang.StringUtils;
43

    
44
import org.gvsig.andami.IconThemeHelper;
45
import org.gvsig.andami.Launcher;
46
import org.gvsig.andami.Launcher.TerminationProcess;
47
import org.gvsig.andami.PluginServices;
48
import org.gvsig.andami.PluginsLocator;
49
import org.gvsig.andami.actioninfo.ActionInfo;
50
import org.gvsig.andami.actioninfo.ActionInfoManager;
51
import org.gvsig.andami.messages.NotificationManager;
52
import org.gvsig.andami.plugins.Extension;
53
import org.gvsig.andami.plugins.IExtension;
54
import org.gvsig.andami.plugins.status.IExtensionStatus;
55
import org.gvsig.andami.plugins.status.IUnsavedData;
56
import org.gvsig.andami.plugins.status.UnsavedData;
57
import org.gvsig.andami.ui.mdiManager.IWindow;
58
import org.gvsig.andami.ui.mdiManager.WindowInfo;
59
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
60
import org.gvsig.app.project.Project;
61
import org.gvsig.app.project.ProjectManager;
62
import org.gvsig.app.project.documents.gui.ProjectWindow;
63
import org.gvsig.app.project.documents.view.ViewManager;
64
import org.gvsig.gui.beans.swing.JFileChooser;
65
import org.gvsig.tools.ToolsLocator;
66
import org.gvsig.tools.dataTypes.DataTypes;
67
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
68
import org.gvsig.tools.persistence.exception.PersistenceException;
69
import org.gvsig.utils.GenericFileFilter;
70
import org.gvsig.utils.save.AfterSavingListener;
71
import org.gvsig.utils.save.BeforeSavingListener;
72
import org.gvsig.utils.save.SaveEvent;
73
import org.gvsig.utils.swing.threads.IMonitorableTask;
74

    
75

    
76
/**
77
 * Extension que proporciona controles para crear proyectos nuevos, abrirlos y
78
 * guardarlos. Adem?s los tipos de tabla que soporta el proyecto son a?adidos en
79
 * esta clase.
80
 *
81
 * @author Fernando Gonz?lez Cort?s
82
 */
83
public class ProjectExtension extends Extension implements IExtensionStatus {
84
        private static final Logger LOG = LoggerFactory
85
                        .getLogger(ProjectExtension.class);
86

    
87
        private static String projectPath = null;
88
        private ProjectWindow projectFrame;
89
        private Project p;
90
        private String lastSavePath;
91
        private WindowInfo seedProjectWindow;
92
        public static final String PROJECT_FILE_CHOOSER_ID = "PROJECT_FILECHOOSER_ID";
93
        /**
94
         * Use UTF-8 for encoding, as it can represent characters from any language.
95
         *
96
         * Another sensible option would be encoding =
97
         * System.getProperty("file.encoding"); but this would need some extra
98
         * testing.
99
         *
100
         * @deprecated see PersistentManager
101
         */
102
        public static String PROJECTENCODING = "UTF-8";
103

    
104
        private List<BeforeSavingListener> beforeSavingListeners = new ArrayList<BeforeSavingListener>();
105

    
106
        private List<AfterSavingListener> afterSavingListeners = new ArrayList<AfterSavingListener>();
107

    
108
        public void initialize() {
109
            initializeDocumentActionsExtensionPoint();
110
            registerDocuments();
111
            registerIcons();
112

    
113
            File projectFile = getProjectFileFromArguments();
114
            if( projectFile!=null ) {
115
                // Posponemos la apertura del proyecto ya que en este momento
116
                // puede que no este inicializado algun plugin que precise el
117
                // proyecto para poderse cargar.
118
                PluginsLocator.getManager().addStartupTask(
119
                    "Open project",
120
                    new OpenInitialProjectTask(projectFile), true, 1000);
121
            }
122
        }
123

    
124
        private void registerIcons() {
125
                IconThemeHelper.registerIcon("action", "application-project-new", this);
126
                IconThemeHelper
127
                                .registerIcon("action", "application-project-open", this);
128
                IconThemeHelper
129
                                .registerIcon("action", "application-project-save", this);
130
                IconThemeHelper.registerIcon("action", "application-project-save-as",
131
                                this);
132

    
133
                IconThemeHelper.registerIcon("project", "project-icon", this);
134
        }
135

    
136
        /**
137
         * Returns the file to be opened or null if no parameter
138
         * or file does not exist
139
         *
140
         * @return
141
         */
142
        private File getProjectFileFromArguments() {
143
            String[] theArgs = PluginServices.getArguments();
144
            if( theArgs.length< 3 ) {
145
                // application-name and extensions-folder are fixed arguments
146
                return null;
147
            }
148
            String lastArg = theArgs[theArgs.length - 1];
149
            if ( StringUtils.isEmpty(lastArg) ) {
150
                return null;
151
            }
152
            if( lastArg.startsWith("-") ) {
153
                // Args starts with "-" are flags
154
                return null;
155
            }
156
            if (!lastArg.toLowerCase().endsWith(Project.FILE_EXTENSION.toLowerCase())) {
157
                LOG.info("Do not open project file, does not have the expected extension '" +
158
                        Project.FILE_EXTENSION +"' ("+lastArg+").");
159
                return null;
160
            }
161
            File projectFile = new File(lastArg);
162
            if ( !projectFile.exists()) {
163
                LOG.info("Do not open project file, '" +projectFile.getAbsolutePath() + "' do not exist.");
164
                return null;
165
            }
166
            return projectFile;
167
        }
168

    
169
        private class OpenInitialProjectTask implements Runnable {
170
            private File projectFile;
171
            public OpenInitialProjectTask(File projectFile) {
172
                this.projectFile = projectFile;
173
            }
174
            public void run() {
175
                if (this.projectFile == null) {
176
                    return;
177
                }
178
                ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
179
                ActionInfo action = actionManager.getAction("application-project-open");
180
                action.execute(this.projectFile);
181
            }
182
        }
183

    
184
        public ProjectWindow getProjectFrame() {
185
                if (projectFrame == null) {
186
                        projectFrame = new ProjectWindow();
187
                }
188
                return projectFrame;
189
        }
190

    
191
        /**
192
         * Muestra la ventana con el gestor de proyectos.
193
         */
194
        public void showProjectWindow() {
195
                if (seedProjectWindow != null) {
196
                        if (seedProjectWindow.isClosed()) {
197
                                // if it was closed, we just don't open the window now
198
                                seedProjectWindow.setClosed(false);
199
                                return;
200
                        }
201
                        WindowInfo winProps = seedProjectWindow;
202
                        seedProjectWindow = null;
203
                        PluginServices.getMDIManager().addWindow(getProjectFrame());
204
                        PluginServices.getMDIManager().changeWindowInfo(getProjectFrame(),
205
                                        winProps);
206
                } else {
207
                        PluginServices.getMDIManager().addWindow(getProjectFrame());
208
                }
209
        }
210

    
211
        /**
212
         * Muestra la ventana con el gestor de proyectos, con las propiedades de
213
         * ventana especificadas.
214
         */
215
        public void showProjectWindow(WindowInfo wi) {
216
                seedProjectWindow = wi;
217
                showProjectWindow();
218
        }
219

    
220
        /**
221
         * Guarda el proyecto actual en disco.
222
         */
223
        private boolean saveProject() {
224
                boolean saved = false;
225
                // if (p.getPath() == null) {
226
                if (projectPath == null) {
227
                        saved = saveAsProject(null);
228
                } else {
229
                        long t1, t2;
230
                        t1 = System.currentTimeMillis();
231
                        saved = writeProject(new File(projectPath), p, false);
232
                        t2 = System.currentTimeMillis();
233
                        PluginServices.getLogger().info(
234
                                        "Project saved. " + (t2 - t1) + " miliseconds");
235
                        getProjectFrame().refreshControls();
236
                }
237
                return saved;
238
        }
239

    
240
        private boolean saveAsProject(File file) {
241
                boolean saved = false;
242

    
243
                if (lastSavePath == null) {
244
                        lastSavePath = projectPath;
245
                }
246

    
247
                if (file == null) {
248
                        Preferences prefs = Preferences.userRoot().node("gvsig.foldering");
249
                        JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID,
250
                                        prefs.get("ProjectsFolder", null));
251

    
252
                        jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
253

    
254
                        GenericFileFilter projExtensionFilter = new GenericFileFilter(
255
                                        Project.FILE_EXTENSION, MessageFormat.format(PluginServices
256
                                                        .getText(this, "tipo_fichero_proyecto"),
257
                                                        Project.FILE_EXTENSION));
258
      jfc.addChoosableFileFilter(projExtensionFilter);
259
      jfc.setFileFilter(projExtensionFilter);
260

    
261
                        if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
262
                                return saved;
263
                        }
264
                        file = jfc.getSelectedFile();
265
                }
266

    
267
                if (!(file.getPath().toLowerCase().endsWith(Project.FILE_EXTENSION
268
                                .toLowerCase()))) {
269
                        file = new File(file.getPath() + Project.FILE_EXTENSION);
270
                }
271
                saved = writeProject(file, p);
272
                String filePath = file.getAbsolutePath();
273
                lastSavePath = filePath.substring(0,
274
                                filePath.lastIndexOf(File.separatorChar));
275

    
276
                getProjectFrame().refreshControls();
277
                return saved;
278
        }
279

    
280
        /**
281
         * Checks whether the project and related unsaved data is modified, and
282
         * allows the user to save it.
283
         *
284
         * @return true if the data has been correctly saved, false otherwise
285
         */
286
        private boolean askSave() {
287
                if (p != null && p.hasChanged()) {
288
                        TerminationProcess process = Launcher.getTerminationProcess();
289
                        UnsavedDataPanel panel = process.getUnsavedDataPanel();
290
                        panel.setHeaderText(PluginServices.getText(this,
291
                                        "_Select_resources_to_save_before_closing_current_project"));
292
                        panel.setAcceptText(
293
                                        PluginServices.getText(this, "save_resources"),
294
                                        PluginServices
295
                                                        .getText(this,
296
                                                                        "Save_the_selected_resources_and_close_current_project"));
297
                        panel.setCancelText(PluginServices.getText(this, "Cancel"),
298
                                        PluginServices.getText(this, "Return_to_current_project"));
299
                        int closeCurrProj;
300
                        try {
301
                                closeCurrProj = process.manageUnsavedData();
302
                                if (closeCurrProj == JOptionPane.NO_OPTION) {
303
                                        // the user chose to return to current project
304
                                        return false;
305
                                }
306
                        } catch (Exception e) {
307
                                LOG.error("Some data can not be saved", e);
308
                        }
309
                }
310
                return true;
311
        }
312

    
313
        public void execute(String command) {
314
                this.execute(command, null);
315
        }
316

    
317
        public void execute(String actionCommand, Object[] args) {
318
                if (actionCommand.equals("application-project-new")) {
319
                        if (!askSave()) {
320
                                return;
321
                        }
322

    
323
                        projectPath = null;
324
                        PluginServices.getMDIManager().closeAllWindows();
325
                        setProject(ProjectManager.getInstance().createProject());
326
                        getProjectFrame().setProject(p);
327
                        showProjectWindow();
328
                        PluginServices.getMainFrame().setTitle(
329
                                        PluginServices.getText(this, "sin_titulo"));
330

    
331
                } else if (actionCommand.equals("application-project-open")) {
332
                        if (!askSave()) {
333
                                return;
334
                        }
335
                        File projectFile = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
336
                        if ( projectFile != null && !projectFile.exists() ) {
337
                            LOG.warn("Can't load project '"
338
                                    + projectFile.getAbsolutePath()
339
                                    + "', file not exist.");
340
                            projectFile = null;
341
                        }
342

    
343
                        if (projectFile == null) {
344
                                Preferences prefs = Preferences.userRoot().node(
345
                                                "gvsig.foldering");
346
                                JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID,
347
                                                prefs.get("ProjectsFolder", null));
348

    
349
                                GenericFileFilter projExtensionFilter = new GenericFileFilter(
350
                                                Project.FILE_EXTENSION, PluginServices.getText(this,
351
                                                                "tipo_fichero_proyecto"));
352
        jfc.addChoosableFileFilter(projExtensionFilter);
353
                                jfc.setFileFilter(projExtensionFilter);
354

    
355
                                if (jfc.showOpenDialog((Component) PluginServices
356
                                                .getMainFrame()) != JFileChooser.APPROVE_OPTION) {
357
                                        return;
358
                                }
359
                                // ProjectDocument.initializeNUMS();
360

    
361

    
362
                                projectFile = jfc.getSelectedFile();
363
                        }
364

    
365
                        PluginServices.getMDIManager().closeAllWindows();
366

    
367
                        Project o = readProject(projectFile);
368
                        setPath(projectFile.getAbsolutePath());
369
                        // lastPath = getPath();
370
                        if (o != null) {
371
                                setProject(o);
372
                        }
373

    
374
                        getProjectFrame().setProject(p);
375
                        PluginServices.getMainFrame().setTitle(projectFile.getName());
376
                        getProjectFrame().refreshControls();
377

    
378
                        // p.restoreWindowProperties();
379

    
380
                } else if (actionCommand.equals("application-project-save")) {
381
//                        saveProject();
382
                        try {
383
                Launcher.manageUnsavedData("there_are_unsaved_resources");
384
            } catch (Exception e) {
385
                LOG.warn("Can't manage unsaved data", e);
386
            }
387
                } else if (actionCommand.equals("application-project-save-as")) {
388
                        File file = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
389
                        saveAsProject(file);
390
                }
391

    
392
        }
393

    
394

    
395
    private void createEmptyProject() {
396
        setProject(ProjectManager.getInstance().createProject());
397
        p.setName(PluginServices.getText(this, "untitled"));
398
        p.setModified(false);
399
        PluginServices.getMainFrame().setTitle(
400
                PluginServices.getText(this, "sin_titulo"));
401
        setProject(p);
402
        showProjectWindow();
403
    }
404

    
405
    /**
406
     * @see com.iver.mdiApp.plugins.IExtension#postInitialize()
407
     */
408
    public void postInitialize() {
409
        try {
410
            if( !SwingUtilities.isEventDispatchThread() ) {
411
                SwingUtilities.invokeAndWait(new Runnable() {
412
                    public void run() {
413
                        createEmptyProject();
414
                    }
415
                });
416
            } else {
417
                createEmptyProject();
418
            }
419
        } catch (Exception e) {
420
            LOG.warn("Can't load initial project.",e);
421
        }
422
    }
423

    
424

    
425
        /**
426
         * Escribe el proyecto en XML.
427
         *
428
         * @param file
429
         *            Fichero.
430
         * @param p
431
         *            Proyecto.
432
         */
433
        public boolean writeProject(File file, Project p) {
434
                return writeProject(file, p, true);
435
        }
436

    
437
        /**
438
         * Escribe el proyecto en XML. Pero permite decidir si se pide confirmaci?n
439
         * para sobreescribir
440
         *
441
         * @param file
442
         *            Fichero.
443
         * @param p
444
         *            Proyecto.
445
         * @param askConfirmation
446
         *            boolean
447
         */
448
        public boolean writeProject(File file, Project p, boolean askConfirmation) {
449
                if (askConfirmation && file.exists()) {
450
                        int resp = JOptionPane.showConfirmDialog((Component) PluginServices
451
                                        .getMainFrame(), PluginServices.getText(this,
452
                                        "fichero_ya_existe_seguro_desea_guardarlo"), PluginServices
453
                                        .getText(this, "guardar"), JOptionPane.YES_NO_OPTION);
454
                        if (resp != JOptionPane.YES_OPTION) {
455
                                return false;
456
                        }
457
                }
458
                NotificationManager.addInfo(PluginServices.getText(this,
459
                                "writing_project") + ": " + file.getName());
460

    
461
                // write it out as XML
462
                try {
463
                        fireBeforeSavingFileEvent(new SaveEvent(this,
464
                                        SaveEvent.BEFORE_SAVING, file));
465
                        p.saveState(file);
466
                        fireAfterSavingFileEvent(new SaveEvent(this,
467
                                        SaveEvent.AFTER_SAVING, file));
468

    
469
                        PluginServices.getMainFrame().setTitle(file.getName());
470
                        setPath(file.toString());
471

    
472
                } catch (PersistenceException e) {
473
                        String messagestack = e.getLocalizedMessageStack();
474
                        NotificationManager.addError(
475
                                        PluginServices.getText(this, "error_writing_project")
476
                                                        + ": " + file.getName() + "\n" + messagestack, e);
477
                        return false;
478
                } catch (Exception e) {
479
                        NotificationManager.addError(
480
                                        PluginServices.getText(this, "error_writing_project")
481
                                                        + ": " + file.getName(), e);
482
                        return false;
483
                }
484
                NotificationManager.addInfo(PluginServices.getText(this,
485
                                "wrote_project") + ": " + file.getName());
486
                return true;
487
        }
488

    
489
        public Project readProject(String path) {
490
                Project project = ProjectManager.getInstance().createProject();
491

    
492
                project.loadState(new File(path));
493
                return (Project) project;
494
        }
495

    
496
        /**
497
         * Lee del XML el proyecto.<br>
498
         * <br>
499
         *
500
         * Reads the XML of the project.<br>
501
         * It returns a project object holding all needed info that is not linked to
502
         * the Project Dialog. <br>
503
         * In case you want the project to be linked to the window you must set this
504
         * object to the extension:<br>
505
         *
506
         * <b>Example:</b><br>
507
         *
508
         * ...<br>
509
         * ...<br>
510
         * Project p = ProjectExtension.readProject(projectFile);<br>
511
         * ProjectExtension.setProject(p); ...<br>
512
         * ...<br>
513
         *
514
         * @param file
515
         *            Fichero.
516
         *
517
         * @return Project
518
         *
519
         */
520
        public Project readProject(File file) {
521
                Project project = ProjectManager.getInstance().createProject();
522

    
523
                project.loadState(file);
524
                return (Project) project;
525
        }
526

    
527
        /**
528
         * Devuelve el proyecto.
529
         *
530
         * @return Proyecto.
531
         */
532
        public Project getProject() {
533
                return p;
534
        }
535

    
536
        /**
537
         * @see org.gvsig.andami.plugins.IExtension#isEnabled()
538
         */
539
        public boolean isEnabled() {
540
                return true;
541
        }
542

    
543
        /**
544
         * @see org.gvsig.andami.plugins.IExtension#isVisible()
545
         */
546
        public boolean isVisible() {
547
                return true;
548
        }
549

    
550
        /**
551
         * Sets the project
552
         *
553
         * @param p
554
         */
555
        public void setProject(Project p) {
556
                getProjectFrame().setProject(p);
557
                this.p = p;
558
        }
559

    
560
        private void registerDocuments() {
561
                ViewManager.register();
562
        }
563

    
564
        private void initializeDocumentActionsExtensionPoint() {
565
                ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
566
                epMan.add(
567
                                "DocumentActions_View",
568
                                "Context menu options of the view document list"
569
                                                + " in the project window "
570
                                                + "(register instances of "
571
                                                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
572
        }
573

    
574
        public static String getPath() {
575
                return projectPath;
576
        }
577

    
578
        public static void setPath(String path) {
579
                projectPath = path;
580
        }
581

    
582
        public IWindow getProjectWindow() {
583
                return getProjectFrame();
584
        }
585

    
586
        public IExtensionStatus getStatus() {
587
                return this;
588
        }
589

    
590
        public boolean hasUnsavedData() {
591
                return p.hasChanged();
592
        }
593

    
594
        public IUnsavedData[] getUnsavedData() {
595
                if (hasUnsavedData()) {
596
                        UnsavedProject data = new UnsavedProject(this);
597
                        IUnsavedData[] dataArray = { data };
598
                        return dataArray;
599
                } else {
600
                        return null;
601
                }
602
        }
603

    
604
        /**
605
         * Implements the IUnsavedData interface to show unsaved projects in the
606
         * Unsavad Data dialog.
607
         *
608
         * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
609
         */
610
        public class UnsavedProject extends UnsavedData {
611

    
612
                public UnsavedProject(IExtension extension) {
613
                        super(extension);
614
                }
615

    
616
                public String getDescription() {
617
                        if (getPath() == null) {
618
                                return PluginServices.getText(ProjectExtension.this,
619
                                                "Unnamed_new_gvsig_project_");
620
                        } else {
621
                                return PluginServices.getText(ProjectExtension.this,
622
                                                "Modified_project_");
623
                        }
624
                }
625

    
626
                public String getResourceName() {
627
                        if (getPath() == null) {
628
                                return PluginServices.getText(ProjectExtension.this, "Unnamed");
629
                        } else {
630
                                return getPath();
631
                        }
632

    
633
                }
634

    
635
                public boolean saveData() {
636
                        return saveProject();
637
                }
638

    
639
                public String getIcon() {
640
                        return "project-icon";
641
                }
642
        }
643

    
644
        public IMonitorableTask[] getRunningProcesses() {
645
                // TODO Auto-generated method stub
646
                return null;
647
        }
648

    
649
        public boolean hasRunningProcesses() {
650
                // TODO Auto-generated method stub
651
                return false;
652
        }
653

    
654
        /**
655
         * Adds the specified before saving listener to receive
656
         * "before saving file events" from this component. If l is null, no
657
         * exception is thrown and no action is performed.
658
         *
659
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
660
         *
661
         * @param l
662
         *            the before saving listener.
663
         * @see SaveEvent
664
         * @see BeforeSavingListener
665
         * @see #removeListener(BeforeSavingListener)
666
         * @see #getBeforeSavingListeners
667
         */
668
        public synchronized void addListener(BeforeSavingListener l) {
669
                if (l == null) {
670
                        return;
671
                }
672
                if (!this.beforeSavingListeners.contains(l)) {
673
                        this.beforeSavingListeners.add(l);
674
                }
675
        }
676

    
677
        /**
678
         * Adds the specified after saving listener to receive
679
         * "after saving file events" from this component. If l is null, no
680
         * exception is thrown and no action is performed.
681
         *
682
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
683
         *
684
         * @param l
685
         *            the after saving listener.
686
         * @see SaveEvent
687
         * @see AfterSavingListener
688
         * @see #removeListener(AfterSavingListener)
689
         * @see #getAfterSavingListeners()
690
         */
691
        public synchronized void addListener(AfterSavingListener l) {
692
                if (l == null) {
693
                        return;
694
                }
695

    
696
                if (!this.afterSavingListeners.contains(l)) {
697
                        this.afterSavingListeners.add(l);
698
                }
699

    
700
        }
701

    
702
        /**
703
         * Returns an array of all the before saving listeners registered on this
704
         * component.
705
         *
706
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
707
         *
708
         * @return all of this component's <code>BeforeSavingListener</code>s or an
709
         *         empty array if no key listeners are currently registered
710
         *
711
         * @see #addBeforeSavingListener(BeforeSavingListener)
712
         * @see #removeBeforeSavingListener(BeforeSavingListener)
713
         */
714
        public synchronized BeforeSavingListener[] getBeforeSavingListeners() {
715
                return this.beforeSavingListeners
716
                                .toArray(new BeforeSavingListener[] {});
717
        }
718

    
719
        /**
720
         * Returns an array of all the after saving listeners registered on this
721
         * component.
722
         *
723
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
724
         *
725
         * @return all of this component's <code>AfterSavingListener</code>s or an
726
         *         empty array if no key listeners are currently registered
727
         *
728
         * @see #addAfterSavingListener(AfterSavingListener)
729
         * @see #removeAfterSavingListener
730
         */
731
        public synchronized AfterSavingListener[] getAfterSavingListeners() {
732
                return this.afterSavingListeners.toArray(new AfterSavingListener[] {});
733

    
734
        }
735

    
736
        /**
737
         * Removes the specified before saving listener so that it no longer
738
         * receives save file events from this component. This method performs no
739
         * function, nor does it throw an exception, if the listener specified by
740
         * the argument was not previously added to this component. If listener
741
         * <code>l</code> is <code>null</code>, no exception is thrown and no action
742
         * is performed.
743
         *
744
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
745
         *
746
         * @param l
747
         *            the before saving listener
748
         * @see SaveEvent
749
         * @see BeforeSavingListener
750
         * @see #addListener(BeforeSavingListener)
751
         * @see #getBeforeSavingListeners()
752
         */
753
        public synchronized void removeListener(BeforeSavingListener l) {
754
                if (l == null) {
755
                        return;
756
                }
757

    
758
                this.beforeSavingListeners.remove(l);
759
        }
760

    
761
        /**
762
         * Removes the specified after saving listener so that it no longer receives
763
         * save file events from this component. This method performs no function,
764
         * nor does it throw an exception, if the listener specified by the argument
765
         * was not previously added to this component. If listener <code>l</code> is
766
         * <code>null</code>, no exception is thrown and no action is performed.
767
         *
768
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
769
         *
770
         * @param l
771
         *            the after saving listener
772
         * @see SaveEvent
773
         * @see AfterSavingListener
774
         * @see #addListener(AfterSavingListener)
775
         * @see #getAfterSavingListeners()
776
         */
777
        public synchronized void removeListener(AfterSavingListener l) {
778
                if (l == null) {
779
                        return;
780
                }
781

    
782
                this.afterSavingListeners.remove(l);
783
        }
784

    
785
        /**
786
         * Reports a before saving file event.
787
         *
788
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
789
         *
790
         * @param evt
791
         *            the before saving file event
792
         */
793
        protected void fireBeforeSavingFileEvent(SaveEvent evt) {
794
                if ((evt.getID() != SaveEvent.BEFORE_SAVING) || (evt.getFile() == null)) {
795
                        return;
796
                }
797

    
798
                Iterator<BeforeSavingListener> iter = this.beforeSavingListeners
799
                                .iterator();
800

    
801
                while (iter.hasNext()) {
802
                        iter.next().beforeSaving(evt);
803
                }
804
        }
805

    
806
        /**
807
         * Reports a after saving file event.
808
         *
809
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
810
         *
811
         * @param evt
812
         *            the after saving file event
813
         */
814
        protected void fireAfterSavingFileEvent(SaveEvent evt) {
815
                if ((evt.getID() != SaveEvent.AFTER_SAVING) || (evt.getFile() == null)) {
816
                        return;
817
                }
818
                Iterator<AfterSavingListener> iter = this.afterSavingListeners
819
                                .iterator();
820

    
821
                while (iter.hasNext()) {
822
                        iter.next().afterSaving(evt);
823
                }
824

    
825
        }
826
}