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 @ 41314

History | View | Annotate | Download (23.7 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
import org.gvsig.tools.util.ArrayUtils;
40
import org.apache.commons.lang.StringUtils;
41
import org.gvsig.andami.IconThemeHelper;
42
import org.gvsig.andami.Launcher;
43
import org.gvsig.andami.Launcher.TerminationProcess;
44
import org.gvsig.andami.PluginServices;
45
import org.gvsig.andami.PluginsLocator;
46
import org.gvsig.andami.actioninfo.ActionInfo;
47
import org.gvsig.andami.actioninfo.ActionInfoManager;
48
import org.gvsig.andami.messages.NotificationManager;
49
import org.gvsig.andami.plugins.Extension;
50
import org.gvsig.andami.plugins.IExtension;
51
import org.gvsig.andami.plugins.status.IExtensionStatus;
52
import org.gvsig.andami.plugins.status.IUnsavedData;
53
import org.gvsig.andami.plugins.status.UnsavedData;
54
import org.gvsig.andami.ui.mdiManager.IWindow;
55
import org.gvsig.andami.ui.mdiManager.WindowInfo;
56
import org.gvsig.andami.ui.wizard.UnsavedDataPanel;
57
import org.gvsig.app.project.Project;
58
import org.gvsig.app.project.ProjectManager;
59
import org.gvsig.app.project.documents.gui.ProjectWindow;
60
import org.gvsig.app.project.documents.view.ViewManager;
61
import org.gvsig.gui.beans.swing.JFileChooser;
62
import org.gvsig.tools.ToolsLocator;
63
import org.gvsig.tools.dataTypes.DataTypes;
64
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
65
import org.gvsig.tools.persistence.exception.PersistenceException;
66
import org.gvsig.utils.GenericFileFilter;
67
import org.gvsig.utils.save.AfterSavingListener;
68
import org.gvsig.utils.save.BeforeSavingListener;
69
import org.gvsig.utils.save.SaveEvent;
70
import org.gvsig.utils.swing.threads.IMonitorableTask;
71

    
72

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

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

    
101
        private List<BeforeSavingListener> beforeSavingListeners = new ArrayList<BeforeSavingListener>();
102

    
103
        private List<AfterSavingListener> afterSavingListeners = new ArrayList<AfterSavingListener>();
104

    
105
        public void initialize() {
106
            initializeDocumentActionsExtensionPoint();
107
            registerDocuments();
108
            registerIcons();
109
            
110
            File projectFile = getProjectFileFromArguments();
111
            if( projectFile!=null ) {
112
                // Posponemos la apertura del proyecto ya que en este momento
113
                // puede que no este inicializado algun plugin que precise el
114
                // proyecto para poderse cargar.
115
                PluginsLocator.getManager().addStartupTask(
116
                    "Open project",
117
                    new OpenInitialProjectTask(projectFile), true, 1000);
118
            }
119
        }
120

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

    
130
                IconThemeHelper.registerIcon("project", "project-icon", this);
131
        }
132

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

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

    
181
        public ProjectWindow getProjectFrame() {
182
                if (projectFrame == null) {
183
                        projectFrame = new ProjectWindow();
184
                }
185
                return projectFrame;
186
        }
187

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

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

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

    
237
        private boolean saveAsProject(File file) {
238
                boolean saved = false;
239

    
240
                if (lastSavePath == null) {
241
                        lastSavePath = projectPath;
242
                }
243

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

    
249
                        jfc.setDialogTitle(PluginServices.getText(this, "guardar_proyecto"));
250
                        jfc.addChoosableFileFilter(new GenericFileFilter(
251
                                        Project.FILE_EXTENSION, MessageFormat.format(PluginServices
252
                                                        .getText(this, "tipo_fichero_proyecto"),
253
                                                        Project.FILE_EXTENSION)));
254

    
255
                        if (jfc.showSaveDialog((Component) PluginServices.getMainFrame()) != JFileChooser.APPROVE_OPTION) {
256
                                return saved;
257
                        }
258
                        file = jfc.getSelectedFile();
259
                }
260

    
261
                if (!(file.getPath().toLowerCase().endsWith(Project.FILE_EXTENSION
262
                                .toLowerCase()))) {
263
                        file = new File(file.getPath() + Project.FILE_EXTENSION);
264
                }
265
                saved = writeProject(file, p);
266
                String filePath = file.getAbsolutePath();
267
                lastSavePath = filePath.substring(0,
268
                                filePath.lastIndexOf(File.separatorChar));
269

    
270
                getProjectFrame().refreshControls();
271
                return saved;
272
        }
273

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

    
307
        public void execute(String command) {
308
                this.execute(command, null);
309
        }
310
        
311
        public void execute(String actionCommand, Object[] args) {
312
                if (actionCommand.equals("application-project-new")) {
313
                        if (!askSave()) {
314
                                return;
315
                        }
316

    
317
                        projectPath = null;
318
                        PluginServices.getMDIManager().closeAllWindows();
319
                        setProject(ProjectManager.getInstance().createProject());
320
                        getProjectFrame().setProject(p);
321
                        showProjectWindow();
322
                        PluginServices.getMainFrame().setTitle(
323
                                        PluginServices.getText(this, "sin_titulo"));
324

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

    
337
                        if (projectFile == null) {
338
                                Preferences prefs = Preferences.userRoot().node(
339
                                                "gvsig.foldering");
340
                                JFileChooser jfc = new JFileChooser(PROJECT_FILE_CHOOSER_ID,
341
                                                prefs.get("ProjectsFolder", null));
342
                                jfc.addChoosableFileFilter(new GenericFileFilter(
343
                                                Project.FILE_EXTENSION, PluginServices.getText(this,
344
                                                                "tipo_fichero_proyecto")));
345

    
346
                                if (jfc.showOpenDialog((Component) PluginServices
347
                                                .getMainFrame()) != JFileChooser.APPROVE_OPTION) {
348
                                        return;
349
                                }
350
                                // ProjectDocument.initializeNUMS();
351
                                
352

    
353
                                projectFile = jfc.getSelectedFile();
354
                        }
355
                        
356
                        PluginServices.getMDIManager().closeAllWindows();
357

    
358
                        Project o = readProject(projectFile);
359
                        setPath(projectFile.getAbsolutePath());
360
                        // lastPath = getPath();
361
                        if (o != null) {
362
                                setProject(o);
363
                        }
364

    
365
                        getProjectFrame().setProject(p);
366
                        PluginServices.getMainFrame().setTitle(projectFile.getName());
367
                        getProjectFrame().refreshControls();
368

    
369
                        // p.restoreWindowProperties();
370

    
371
                } else if (actionCommand.equals("application-project-save")) {
372
                        saveProject();
373
                } else if (actionCommand.equals("application-project-save-as")) {
374
                        File file = (File) ArrayUtils.get(args, 0, DataTypes.FILE);
375
                        saveAsProject(file);
376
                }
377

    
378
        }
379

    
380
        
381
    private void createEmptyProject() {
382
        setProject(ProjectManager.getInstance().createProject());
383
        p.setName(PluginServices.getText(this, "untitled"));
384
        p.setModified(false);
385
        PluginServices.getMainFrame().setTitle(
386
                PluginServices.getText(this, "sin_titulo"));
387
        setProject(p);
388
        showProjectWindow();
389
    }
390

    
391
    /**
392
     * @see com.iver.mdiApp.plugins.IExtension#postInitialize()
393
     */
394
    public void postInitialize() {
395
        try {
396
            if( !SwingUtilities.isEventDispatchThread() ) {
397
                SwingUtilities.invokeAndWait(new Runnable() {
398
                    public void run() {
399
                        createEmptyProject();
400
                    }
401
                });
402
            } else {
403
                createEmptyProject();
404
            }
405
        } catch (Exception e) {
406
            LOG.warn("Can't load initial project.",e);
407
        }
408
    }        
409
        
410
        
411
        /**
412
         * Escribe el proyecto en XML.
413
         * 
414
         * @param file
415
         *            Fichero.
416
         * @param p
417
         *            Proyecto.
418
         */
419
        public boolean writeProject(File file, Project p) {
420
                return writeProject(file, p, true);
421
        }
422

    
423
        /**
424
         * Escribe el proyecto en XML. Pero permite decidir si se pide confirmaci?n
425
         * para sobreescribir
426
         * 
427
         * @param file
428
         *            Fichero.
429
         * @param p
430
         *            Proyecto.
431
         * @param askConfirmation
432
         *            boolean
433
         */
434
        public boolean writeProject(File file, Project p, boolean askConfirmation) {
435
                if (askConfirmation && file.exists()) {
436
                        int resp = JOptionPane.showConfirmDialog((Component) PluginServices
437
                                        .getMainFrame(), PluginServices.getText(this,
438
                                        "fichero_ya_existe_seguro_desea_guardarlo"), PluginServices
439
                                        .getText(this, "guardar"), JOptionPane.YES_NO_OPTION);
440
                        if (resp != JOptionPane.YES_OPTION) {
441
                                return false;
442
                        }
443
                }
444
                NotificationManager.addInfo(PluginServices.getText(this,
445
                                "writinng_project") + ": " + file.getName());
446

    
447
                // write it out as XML
448
                try {
449
                        fireBeforeSavingFileEvent(new SaveEvent(this,
450
                                        SaveEvent.BEFORE_SAVING, file));
451
                        p.saveState(file);
452
                        fireAfterSavingFileEvent(new SaveEvent(this,
453
                                        SaveEvent.AFTER_SAVING, file));
454

    
455
                        PluginServices.getMainFrame().setTitle(file.getName());
456
                        setPath(file.toString());
457

    
458
                } catch (PersistenceException e) {
459
                        String messagestack = e.getLocalizedMessageStack();
460
                        NotificationManager.addError(
461
                                        PluginServices.getText(this, "error_writing_project")
462
                                                        + ": " + file.getName() + "\n" + messagestack, e);
463
                        return false;
464
                } catch (Exception e) {
465
                        NotificationManager.addError(
466
                                        PluginServices.getText(this, "error_writing_project")
467
                                                        + ": " + file.getName(), e);
468
                        return false;
469
                }
470
                NotificationManager.addInfo(PluginServices.getText(this,
471
                                "wrote_project") + ": " + file.getName());
472
                return true;
473
        }
474

    
475
        public Project readProject(String path) {
476
                Project project = ProjectManager.getInstance().createProject();
477

    
478
                project.loadState(new File(path));
479
                return (Project) project;
480
        }
481

    
482
        /**
483
         * Lee del XML el proyecto.<br>
484
         * <br>
485
         * 
486
         * Reads the XML of the project.<br>
487
         * It returns a project object holding all needed info that is not linked to
488
         * the Project Dialog. <br>
489
         * In case you want the project to be linked to the window you must set this
490
         * object to the extension:<br>
491
         * 
492
         * <b>Example:</b><br>
493
         * 
494
         * ...<br>
495
         * ...<br>
496
         * Project p = ProjectExtension.readProject(projectFile);<br>
497
         * ProjectExtension.setProject(p); ...<br>
498
         * ...<br>
499
         * 
500
         * @param file
501
         *            Fichero.
502
         * 
503
         * @return Project
504
         * 
505
         */
506
        public Project readProject(File file) {
507
                Project project = ProjectManager.getInstance().createProject();
508

    
509
                project.loadState(file);
510
                return (Project) project;
511
        }
512

    
513
        /**
514
         * Devuelve el proyecto.
515
         * 
516
         * @return Proyecto.
517
         */
518
        public Project getProject() {
519
                return p;
520
        }
521

    
522
        /**
523
         * @see org.gvsig.andami.plugins.IExtension#isEnabled()
524
         */
525
        public boolean isEnabled() {
526
                return true;
527
        }
528

    
529
        /**
530
         * @see org.gvsig.andami.plugins.IExtension#isVisible()
531
         */
532
        public boolean isVisible() {
533
                return true;
534
        }
535

    
536
        /**
537
         * Sets the project
538
         * 
539
         * @param p
540
         */
541
        public void setProject(Project p) {
542
                getProjectFrame().setProject(p);
543
                this.p = p;
544
        }
545

    
546
        private void registerDocuments() {
547
                ViewManager.register();
548
        }
549

    
550
        private void initializeDocumentActionsExtensionPoint() {
551
                ExtensionPointManager epMan = ToolsLocator.getExtensionPointManager();
552
                epMan.add(
553
                                "DocumentActions_View",
554
                                "Context menu options of the view document list"
555
                                                + " in the project window "
556
                                                + "(register instances of "
557
                                                + "org.gvsig.app.project.AbstractDocumentContextMenuAction)");
558
        }
559

    
560
        public static String getPath() {
561
                return projectPath;
562
        }
563

    
564
        public static void setPath(String path) {
565
                projectPath = path;
566
        }
567

    
568
        public IWindow getProjectWindow() {
569
                return getProjectFrame();
570
        }
571

    
572
        public IExtensionStatus getStatus() {
573
                return this;
574
        }
575

    
576
        public boolean hasUnsavedData() {
577
                return p.hasChanged();
578
        }
579

    
580
        public IUnsavedData[] getUnsavedData() {
581
                if (hasUnsavedData()) {
582
                        UnsavedProject data = new UnsavedProject(this);
583
                        IUnsavedData[] dataArray = { data };
584
                        return dataArray;
585
                } else {
586
                        return null;
587
                }
588
        }
589

    
590
        /**
591
         * Implements the IUnsavedData interface to show unsaved projects in the
592
         * Unsavad Data dialog.
593
         * 
594
         * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
595
         */
596
        public class UnsavedProject extends UnsavedData {
597

    
598
                public UnsavedProject(IExtension extension) {
599
                        super(extension);
600
                }
601

    
602
                public String getDescription() {
603
                        if (getPath() == null) {
604
                                return PluginServices.getText(ProjectExtension.this,
605
                                                "Unnamed_new_gvsig_project_");
606
                        } else {
607
                                return PluginServices.getText(ProjectExtension.this,
608
                                                "Modified_project_");
609
                        }
610
                }
611

    
612
                public String getResourceName() {
613
                        if (getPath() == null) {
614
                                return PluginServices.getText(ProjectExtension.this, "Unnamed");
615
                        } else {
616
                                return getPath();
617
                        }
618

    
619
                }
620

    
621
                public boolean saveData() {
622
                        return saveProject();
623
                }
624

    
625
                public String getIcon() {
626
                        return "project-icon";
627
                }
628
        }
629

    
630
        public IMonitorableTask[] getRunningProcesses() {
631
                // TODO Auto-generated method stub
632
                return null;
633
        }
634

    
635
        public boolean hasRunningProcesses() {
636
                // TODO Auto-generated method stub
637
                return false;
638
        }
639

    
640
        /**
641
         * Adds the specified before saving listener to receive
642
         * "before saving file events" from this component. If l is null, no
643
         * exception is thrown and no action is performed.
644
         * 
645
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
646
         * 
647
         * @param l
648
         *            the before saving listener.
649
         * @see SaveEvent
650
         * @see BeforeSavingListener
651
         * @see #removeListener(BeforeSavingListener)
652
         * @see #getBeforeSavingListeners
653
         */
654
        public synchronized void addListener(BeforeSavingListener l) {
655
                if (l == null) {
656
                        return;
657
                }
658
                if (!this.beforeSavingListeners.contains(l)) {
659
                        this.beforeSavingListeners.add(l);
660
                }
661
        }
662

    
663
        /**
664
         * Adds the specified after saving listener to receive
665
         * "after saving file events" from this component. If l is null, no
666
         * exception is thrown and no action is performed.
667
         * 
668
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
669
         * 
670
         * @param l
671
         *            the after saving listener.
672
         * @see SaveEvent
673
         * @see AfterSavingListener
674
         * @see #removeListener(AfterSavingListener)
675
         * @see #getAfterSavingListeners()
676
         */
677
        public synchronized void addListener(AfterSavingListener l) {
678
                if (l == null) {
679
                        return;
680
                }
681

    
682
                if (!this.afterSavingListeners.contains(l)) {
683
                        this.afterSavingListeners.add(l);
684
                }
685

    
686
        }
687

    
688
        /**
689
         * Returns an array of all the before saving listeners registered on this
690
         * component.
691
         * 
692
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
693
         * 
694
         * @return all of this component's <code>BeforeSavingListener</code>s or an
695
         *         empty array if no key listeners are currently registered
696
         * 
697
         * @see #addBeforeSavingListener(BeforeSavingListener)
698
         * @see #removeBeforeSavingListener(BeforeSavingListener)
699
         */
700
        public synchronized BeforeSavingListener[] getBeforeSavingListeners() {
701
                return this.beforeSavingListeners
702
                                .toArray(new BeforeSavingListener[] {});
703
        }
704

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

    
720
        }
721

    
722
        /**
723
         * Removes the specified before saving listener so that it no longer
724
         * receives save file events from this component. This method performs no
725
         * function, nor does it throw an exception, if the listener specified by
726
         * the argument was not previously added to this component. If listener
727
         * <code>l</code> is <code>null</code>, no exception is thrown and no action
728
         * is performed.
729
         * 
730
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
731
         * 
732
         * @param l
733
         *            the before saving listener
734
         * @see SaveEvent
735
         * @see BeforeSavingListener
736
         * @see #addListener(BeforeSavingListener)
737
         * @see #getBeforeSavingListeners()
738
         */
739
        public synchronized void removeListener(BeforeSavingListener l) {
740
                if (l == null) {
741
                        return;
742
                }
743

    
744
                this.beforeSavingListeners.remove(l);
745
        }
746

    
747
        /**
748
         * Removes the specified after saving listener so that it no longer receives
749
         * save file events from this component. This method performs no function,
750
         * nor does it throw an exception, if the listener specified by the argument
751
         * was not previously added to this component. If listener <code>l</code> is
752
         * <code>null</code>, no exception is thrown and no action is performed.
753
         * 
754
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
755
         * 
756
         * @param l
757
         *            the after saving listener
758
         * @see SaveEvent
759
         * @see AfterSavingListener
760
         * @see #addListener(AfterSavingListener)
761
         * @see #getAfterSavingListeners()
762
         */
763
        public synchronized void removeListener(AfterSavingListener l) {
764
                if (l == null) {
765
                        return;
766
                }
767

    
768
                this.afterSavingListeners.remove(l);
769
        }
770

    
771
        /**
772
         * Reports a before saving file event.
773
         * 
774
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
775
         * 
776
         * @param evt
777
         *            the before saving file event
778
         */
779
        protected void fireBeforeSavingFileEvent(SaveEvent evt) {
780
                if ((evt.getID() != SaveEvent.BEFORE_SAVING) || (evt.getFile() == null)) {
781
                        return;
782
                }
783

    
784
                Iterator<BeforeSavingListener> iter = this.beforeSavingListeners
785
                                .iterator();
786

    
787
                while (iter.hasNext()) {
788
                        iter.next().beforeSaving(evt);
789
                }
790
        }
791

    
792
        /**
793
         * Reports a after saving file event.
794
         * 
795
         * @author Pablo Piqueras Bartolom? <pablo.piqueras@iver.es>
796
         * 
797
         * @param evt
798
         *            the after saving file event
799
         */
800
        protected void fireAfterSavingFileEvent(SaveEvent evt) {
801
                if ((evt.getID() != SaveEvent.AFTER_SAVING) || (evt.getFile() == null)) {
802
                        return;
803
                }
804
                Iterator<AfterSavingListener> iter = this.afterSavingListeners
805
                                .iterator();
806

    
807
                while (iter.hasNext()) {
808
                        iter.next().afterSaving(evt);
809
                }
810

    
811
        }
812
}