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 / project / DefaultProject.java @ 47784

History | View | Annotate | Download (51.8 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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.app.project;
24

    
25
import java.awt.Color;
26
import java.awt.image.BufferedImage;
27
import java.beans.PropertyChangeEvent;
28
import java.beans.PropertyChangeListener;
29
import java.beans.PropertyChangeSupport;
30
import java.io.File;
31
import java.io.FileInputStream;
32
import java.io.FileNotFoundException;
33
import java.io.FileOutputStream;
34
import java.io.IOException;
35
import java.io.InputStream;
36
import java.io.OutputStream;
37
import java.io.Serializable;
38
import java.text.DateFormat;
39
import java.text.MessageFormat;
40
import java.text.SimpleDateFormat;
41
import java.util.ArrayList;
42
import java.util.Collections;
43
import java.util.Date;
44
import java.util.HashMap;
45
import java.util.HashSet;
46
import java.util.Iterator;
47
import java.util.List;
48
import java.util.Map;
49
import java.util.Set;
50
import java.util.function.Predicate;
51
import java.util.zip.ZipEntry;
52
import java.util.zip.ZipException;
53
import java.util.zip.ZipFile;
54
import java.util.zip.ZipOutputStream;
55
import javax.imageio.ImageIO;
56
import javax.swing.JOptionPane;
57
import javax.swing.SwingUtilities;
58
import org.apache.commons.io.FileUtils;
59
import org.apache.commons.io.FilenameUtils;
60
import org.apache.commons.io.IOUtils;
61
import org.apache.commons.lang3.StringUtils;
62
import org.cresques.cts.IProjection;
63
import org.gvsig.andami.PluginServices;
64
import org.gvsig.andami.ui.mdiManager.IWindow;
65
import org.gvsig.andami.ui.mdiManager.MDIManager;
66
import org.gvsig.andami.ui.mdiManager.SingletonWindow;
67
import org.gvsig.andami.ui.mdiManager.WindowInfo;
68
import org.gvsig.app.ApplicationLocator;
69
import org.gvsig.app.ApplicationManager;
70
import org.gvsig.app.extension.ProjectExtension;
71
import org.gvsig.app.extension.Version;
72
import org.gvsig.app.project.ProjectManager.ProjectEventImpl;
73
import org.gvsig.app.project.documents.AbstractDocument;
74
import org.gvsig.app.project.documents.Document;
75
import org.gvsig.app.project.documents.DocumentManager;
76
import org.gvsig.app.project.documents.exceptions.SaveException;
77
import org.gvsig.app.project.documents.gui.IDocumentWindow;
78
import org.gvsig.app.project.documents.gui.ProjectWindow;
79
import org.gvsig.app.project.documents.view.DefaultViewDocument;
80
import org.gvsig.app.project.documents.view.ViewManager;
81
import org.gvsig.fmap.mapcontext.MapContext;
82
import org.gvsig.fmap.mapcontext.layers.ExtendedPropertiesHelper;
83
import org.gvsig.fmap.mapcontext.layers.FLayer;
84
import org.gvsig.fmap.mapcontext.layers.FLayers;
85
import org.gvsig.tools.ToolsLocator;
86
import org.gvsig.tools.dispose.DisposeUtils;
87
import org.gvsig.tools.dynobject.DynStruct;
88
import org.gvsig.tools.i18n.I18nManager;
89
import org.gvsig.tools.observer.ObservableHelper;
90
import org.gvsig.tools.observer.Observer;
91
import org.gvsig.tools.persistence.PersistenceManager;
92
import org.gvsig.tools.persistence.Persistent;
93
import org.gvsig.tools.persistence.PersistentContext;
94
import org.gvsig.tools.persistence.PersistentState;
95
import org.gvsig.tools.persistence.exception.PersistenceException;
96
import org.gvsig.tools.swing.api.ToolsSwingLocator;
97
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
98
import org.gvsig.utils.StringUtilities;
99
import org.slf4j.Logger;
100
import org.slf4j.LoggerFactory;
101

    
102
/**
103
 * Clase que representa un proyecto de gvSIG
104
 *
105
 */
106
public class DefaultProject implements Serializable, PropertyChangeListener,
107
        Project {
108

    
109
    private Logger LOG = LoggerFactory.getLogger(DefaultProject.class);
110
    /**
111
     * @deprecated see ApplicationLocator.getManager().getVersion()
112
     */
113
    public static String VERSION = Version.format();
114

    
115
    private ExtendedPropertiesHelper propertiesHelper = new ExtendedPropertiesHelper();
116

    
117
    private ObservableHelper observableHelper = new ObservableHelper();
118

    
119
    /**
120
     *
121
     */
122
    private static final long serialVersionUID = -4449622027521773178L;
123

    
124
    private static final Logger logger = LoggerFactory.getLogger(Project.class);
125

    
126
    private static ProjectPreferences preferences = new ProjectPreferences();
127

    
128
    /**
129
     * Index used by the generator of unique names of documents.
130
     */
131
    private Map<String, Integer> nextDocumentIndexByType = new HashMap<>();
132

    
133
    private PropertyChangeSupport change;
134

    
135
    private boolean modified = false;
136

    
137
    private String name = null;
138

    
139
    private String creationDate = null;
140

    
141
    private String modificationDate = null;
142

    
143
    private String owner = null;
144

    
145
    private String comments = null;
146

    
147
    private Color selectionColor = null;
148

    
149
    private List<Document> documents = null;
150

    
151
    private List<ProjectExtent> extents = null;
152

    
153
    private IProjection projection;
154

    
155
    private File fname = null;
156

    
157
    private Set<String> unloadedObjects;
158
    private PersistenceException loadErrors = null;
159

    
160
    /**
161
     * Creates a new Project object.
162
     */
163
    DefaultProject() {
164
        this.change = new PropertyChangeSupport(this);
165
        this.clean();
166
        notifyProjectManagerEvent(ProjectNotification.NEW_PROJECT);
167
    }
168

    
169
    protected void clean() {
170
        this.owner = "";
171
        this.comments = "";
172
        this.name = PluginServices.getText(this, "untitled");
173
        this.creationDate = DateFormat.getDateInstance().format(new Date());
174
        this.modificationDate = this.creationDate;
175

    
176
        this.documents = new ArrayList<Document>();
177
        this.extents = new ArrayList<ProjectExtent>();
178

    
179
        this.setSelectionColor(getPreferences().getDefaultSelectionColor());
180

    
181
        this.projection = null; // se inicializa en el getProjection()
182
    }
183

    
184
    public static ProjectPreferences getPreferences() {
185
        return preferences;
186
    }
187

    
188
    @Override
189
    public void propertyChange(PropertyChangeEvent evt) {
190
        change.firePropertyChange(evt);
191
    }
192

    
193
    @Override
194
    public synchronized void addPropertyChangeListener(
195
            PropertyChangeListener arg0) {
196
        change.addPropertyChangeListener(arg0);
197
    }
198

    
199
    @Override
200
    public void removePropertyChangeListener(PropertyChangeListener listener) {
201
        change.removePropertyChangeListener(listener);
202
    }
203
    
204
    /**
205
     * Return the creation date of the project
206
     *
207
     * @return
208
     */
209
    @Override
210
    public String getCreationDate() {
211
        return creationDate;
212
    }
213

    
214
    protected void setCreationDate(String creationDate) {
215
        this.creationDate = creationDate;
216
        change.firePropertyChange("setCreationDate", null, null);
217
    }
218

    
219
    @Override
220
    public Document createDocument(String type) {
221
        logger.info("createDocument('{}')", type);
222
        return ProjectManager.getInstance().createDocument(type);
223
    }
224

    
225
    /**
226
     * Return the name of the project
227
     *
228
     * @return
229
     */
230
    @Override
231
    public String getName() {
232
        return name;
233
    }
234

    
235
    /**
236
     * Set the name of he project.
237
     *
238
     * @param string
239
     */
240
    @Override
241
    public void setName(String name) {
242
        this.name = name;
243
        change.firePropertyChange("setName", null, null);
244
    }
245

    
246
    /**
247
     * Return the comments associateds with the project
248
     *
249
     * @return comments
250
     */
251
    @Override
252
    public String getComments() {
253
        return comments;
254
    }
255

    
256
    /**
257
     * Set the comments associateds with the project
258
     *
259
     * @param comments as string
260
     */
261
    @Override
262
    public void setComments(String string) {
263
        comments = string;
264
        change.firePropertyChange("setComments", null, null);
265
    }
266

    
267
    /**
268
     * Retuen the modification date of the project.
269
     *
270
     * @return modification date as string
271
     */
272
    @Override
273
    public String getModificationDate() {
274
        return modificationDate;
275
    }
276

    
277
    protected void setModificationDate(String string) {
278
        modificationDate = string;
279
        change.firePropertyChange("setModificationDate", null, null);
280
    }
281

    
282
    /**
283
     * Return the author of the project,
284
     *
285
     * @return author as string
286
     */
287
    @Override
288
    public String getOwner() {
289
        return owner;
290
    }
291

    
292
    /**
293
     * Sets the author of the project
294
     *
295
     * @param author name as string
296
     */
297
    @Override
298
    public void setOwner(String owner) {
299
        this.owner = owner;
300
        change.firePropertyChange("setOwner", null, null);
301
    }
302

    
303
    /**
304
     * Obtiene el color de selecci�n que se usar� en el proyecto
305
     *
306
     * @return
307
     */
308
    @Override
309
    public Color getSelectionColor() {
310
        if (selectionColor == null) {
311
            selectionColor = getPreferences().getDefaultSelectionColor();
312
        }
313
        return selectionColor;
314
    }
315

    
316
    /**
317
     * Sets the selecction color
318
     *
319
     * @param selection color as string
320
     */
321
    @Override
322
    public void setSelectionColor(String selectionColor) {
323
        this.setSelectionColor(StringUtilities.string2Color(selectionColor));
324
    }
325

    
326
    /**
327
     * Sets the selecction color
328
     *
329
     * @param selection color as Color
330
     */
331
    @Override
332
    public void setSelectionColor(Color selectionColor) {
333
        this.selectionColor = selectionColor;
334
        MapContext.setSelectionColor(selectionColor);
335
        change.firePropertyChange("selectionColor", null, selectionColor);
336
    }
337

    
338
    @Override
339
    public IProjection getProjection() {
340
        if (projection == null) {
341
            projection = getPreferences().getDefaultProjection();
342
        }
343
        return projection;
344
    }
345

    
346
    @Override
347
    public void setProjection(IProjection projection) {
348
        this.projection = projection;
349
    }
350

    
351
    /**
352
     * Sets the modified state of project.
353
     *
354
     * Can't set to not modified.
355
     *
356
     * @param modified as boolean
357
     */
358
    @Override
359
    public void setModified(boolean modified) {
360
        this.modified = modified;
361
        if (modified == false) {
362
            List<Document> documents = this.getDocuments();
363
            for (int i = 0; i < documents.size(); i++) {
364
                documents.get(i).setModified(false);
365
            }
366
        }
367
    }
368

    
369
    @Override
370
    public boolean hasChanged() {
371
        if( modified ) {
372
            return true;
373
        }
374
        if (this.getDocuments().isEmpty() ) {
375
            return false;
376
        }
377
        for (Document document : this.getDocuments()) {
378
            if( document.isTemporary()) {
379
                continue;
380
            }
381
            if( document.isModified() ) {
382
                return true;
383
            }
384
        }
385
        return false;
386
    }
387

    
388
    /**
389
     * Return a list of documents in the project.
390
     *
391
     * @return documents as List of IProjectDocument
392
     */
393
    @Override
394
    public List<Document> getDocuments() {
395
        return this.getDocuments((Predicate<Document>)null);
396
    }
397

    
398
    /**
399
     * Return a list with all documents of especified type.
400
     *
401
     * @param type of document
402
     *
403
     * @return List of IProjectDocument
404
     */
405
    @Override
406
    public List<Document> getDocuments(String type) {
407
        return this.getDocuments((Document t) -> t!=null && 
408
                (type==null  || StringUtils.equalsIgnoreCase(type, t.getTypeName()))
409
        );
410
    }
411

    
412
    @Override
413
    public List<Document> getDocuments(Class<? extends Document> documentClass) {
414
        return this.getDocuments((Document t) -> t!=null && 
415
                (documentClass==null  || documentClass.isAssignableFrom(t.getClass()))
416
        );
417
    }
418

    
419
    @Override
420
    public List<Document> getDocuments(Predicate<Document> filter) {
421
        List<Document> docs;
422
        if( filter == null ) {
423
            docs = new ArrayList<Document>(this.documents);
424
        } else {
425
            docs = new ArrayList<Document>();
426
            for (Document document : this.documents) {
427
                if ( filter.test(document) ) {
428
                    docs.add(document);
429
                }
430
            }
431
        }
432
        Collections.sort(docs, (Document o1, Document o2) -> StringUtils.compareIgnoreCase(o1.getName(), o2.getName()));
433
        return Collections.unmodifiableList(docs);
434
    }
435

    
436
    /**
437
     * Adds a document to the project
438
     *
439
     * @param document as Document
440
     */
441
    @Override
442
    public void add(Document document) {
443
        this.addDocument(document);
444
    }
445

    
446
    @Override
447
    public void addDocument(Document document) {
448
        logger.info("add('{}')", document.toString());
449

    
450
        if (notifyObservers(ProjectNotification.BEFORE_ADD_DOCUMENT, document).isProcessCanceled()) {
451
            return;
452
        }
453
        document.addPropertyChangeListener(this);
454
        document.setProject(this);
455
        document.setName(this.getUniqueNameForDocument(document.getTypeName(),
456
                document.getName()));
457
        documents.add(document);
458
        DisposeUtils.bind(document);
459
        document.afterAdd();
460
        this.setModified(true);
461
        notifyObservers(ProjectNotification.AFTER_ADD_DOCUMENT, document);
462
        change.firePropertyChange("addDocument", null, document);
463
    }
464

    
465
    @Override
466
    public void remove(Document doc) {
467
        this.removeDocument(doc);
468
    }
469

    
470
    @Override
471
    public void removeDocument(Document doc) {
472
        logger.info("remove('{}')", doc.toString());
473
        if (notifyObservers(ProjectNotification.BEFORE_REMOVE_DOCUMENT, doc).isProcessCanceled()) {
474
            return;
475
        }
476
        documents.remove(doc);
477
        this.setModified(true);
478
        change.firePropertyChange("delDocument", doc, null);
479
        doc.afterRemove();
480
        notifyObservers(ProjectNotification.AFTER_REMOVE_DOCUMENT, doc);
481
        DisposeUtils.disposeQuietly(doc);
482
    }
483

    
484
    @Override
485
    public Iterator<Document> iterator() {
486
        return documents.iterator();
487
    }
488

    
489
    @Override
490
    public boolean isEmpty() {
491
        return documents.isEmpty();
492
    }
493

    
494
    /**
495
     * Return the view that contains the especified layer.
496
     *
497
     * @param layer
498
     *
499
     * @return name of the view that contains the layer
500
     *
501
     * @throws RuntimeException Si la capa que se pasa como par�metro no se
502
     * encuentra en ninguna vista
503
     */
504
    @Override
505
    public String getViewName(FLayer layer) {
506
        List<Document> views = getDocuments(ViewManager.TYPENAME);
507
        for (int v = 0; v < views.size(); v++) {
508
            DefaultViewDocument pView = (DefaultViewDocument) views.get(v);
509
            FLayers layers = pView.getMapContext().getLayers();
510
            if (isView(layers, layer)) {
511
                return pView.getName();
512
            }
513
        }
514

    
515
        throw new RuntimeException(MessageFormat.format(
516
                "The layer '{1}' is not in a view", layer.getName()));
517
    }
518

    
519
    private boolean isView(FLayers layers, FLayer layer) {
520
        for (int i = 0; i < layers.getLayersCount(); i++) {
521
            if (layers.getLayer(i) instanceof FLayers) {
522
                if (isView((FLayers) layers.getLayer(i), layer)) {
523
                    return true;
524
                }
525
            }
526
            if (layers.getLayer(i) == layer) {
527
                return true;
528
            }
529
        }
530
        return false;
531
    }
532

    
533
    @Override
534
    public void addExtent(ProjectExtent arg1) {
535
        extents.add(arg1);
536
        change.firePropertyChange("addExtent", null, null);
537
    }
538

    
539
    @Override
540
    public ProjectExtent removeExtent(int arg0) {
541
        change.firePropertyChange("delExtent", null, null);
542
        return extents.remove(arg0);
543
    }
544

    
545
    @Override
546
    public ProjectExtent[] getExtents() {
547
        return (ProjectExtent[]) extents.toArray(new ProjectExtent[0]);
548
    }
549

    
550
    /**
551
     * Obtiene un documento a partir de su nombre y el nombre de registro en el
552
     * pointExtension, este �ltimo se puede obtener del
553
     * Project****Factory.registerName.
554
     *
555
     * @param name Nombre del documento
556
     * @param type nombre de registro en el extensionPoint
557
     *
558
     * @return Documento
559
     */
560
    @Override
561
    public Document getDocument(String name, String type) {
562
        if (type == null) {
563
            for (int i = 0; i < documents.size(); i++) {
564
                Document document = documents.get(i);
565
                if( document == null ) {
566
                    continue;
567
                }
568
                if( StringUtils.equalsIgnoreCase(name, document.getName()) ) {
569
                    return document;
570
                }
571
            }
572
        } else {
573
            for (int i = 0; i < documents.size(); i++) {
574
                Document document = documents.get(i);
575
                if( document == null ) {
576
                    continue;
577
                }
578
                if( StringUtils.equalsIgnoreCase(type, document.getTypeName()) 
579
                        && StringUtils.equalsIgnoreCase(name, document.getName()) ) {
580
                    return document;
581
                }
582
            }
583
        }
584
        return null;
585
    }
586

    
587
    public Document getDocument(Predicate<Document>condition) {
588
        for (Document document : documents) {
589
            if( document == null ) {
590
                continue;
591
            }
592
            if( condition.test(document) ) {
593
                return document;
594
            }
595
        }
596
        return null;
597
    }
598

    
599
    @Override
600
    public Document getDocument(String name) {
601
        return this.getDocument(name, null);
602
    }
603

    
604
    public String getUniqueNameForDocument(String type, String name) {
605
        Document document = getDocument(name, type);
606
        if (document == null) {
607
            return name;
608
        }
609

    
610
        String newName = null;
611
        int num = this.getNextDocumentIndex(type);
612
        while (document != null) {
613
            newName = name + " - " + num++;
614
            document = getDocument(newName, type);
615
        }
616
        this.setNextDocumentIndex(type, num);
617
        return newName;
618
    }
619

    
620
    private int getNextDocumentIndex(String type) {
621
        if (nextDocumentIndexByType.get(type) == null) {
622
            nextDocumentIndexByType.put(type, new Integer(1));
623
            return 1;
624
        }
625
        return nextDocumentIndexByType.get(type).intValue();
626
    }
627

    
628
    private void setNextDocumentIndex(String type, int newIndex) {
629
        if (nextDocumentIndexByType.get(type) == null) {
630
            nextDocumentIndexByType.put(type, new Integer(newIndex));
631
        } else {
632
            nextDocumentIndexByType.put(type, new Integer(newIndex));
633
        }
634
    }
635

    
636
    @Override
637
    public void saveState(File out) throws PersistenceException {
638
        FileOutputStream fout;
639
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_FILE, out).isProcessCanceled()) {
640
            return;
641
        }
642
        try {
643
            fout = new FileOutputStream(out);
644
            saveState(fout, new File(out.getParent()));
645
        } catch (FileNotFoundException e) {
646
            createProjectCopy(true);
647
            throw new PersistenceException(e);
648
        }
649
        if( !isValidZIP(out) ) {
650
            throw new PersistenceException(new ZipException());
651
        }
652
        this.fname = out;
653
        //sacar copia al bak
654
        createProjectCopy(false);
655
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_FILE, out);
656
    }
657

    
658
    boolean isValidZIP(final File file) {
659
        ZipFile zipfile = null;
660
        try {
661
            zipfile = new ZipFile(file);
662
            return true;
663
        } catch (IOException e) {
664
            //sacar copia. 
665
            return false;
666
        } finally {
667
            try {
668
                if (zipfile != null) {
669
                    zipfile.close();
670
                    zipfile = null;
671
                }
672
            } catch (IOException e) {
673
            }
674
        }
675
    }
676
   
677
    @Override
678
    public File getFile() {
679
        return this.fname;
680
    }
681

    
682
    @Deprecated
683
    @Override
684
    public void saveState(OutputStream out) throws PersistenceException {
685
        saveState(out, null);
686
    }
687
    
688
    @Override
689
    public void saveState(File file, BufferedImage preview) {
690
        FileOutputStream fout=null;
691
        ZipOutputStream zout=null;
692
        try {
693
            fout = new FileOutputStream(file);
694
            zout = new ZipOutputStream(fout);
695
            this.saveState(zout, file.getParentFile());
696

    
697
            zout.putNextEntry(new ZipEntry("preview.jpg"));
698
            try {
699
                ImageIO.write(preview, "jpg", zout);
700
            } catch (IOException ex) {
701
                LOG.warn("Can't save preview image'.", ex);
702
            }
703
            IOUtils.closeQuietly(zout);
704
            IOUtils.closeQuietly(fout);
705

    
706
            if( !isValidZIP(file) ) {
707
                throw new ZipException("Invalid project file '"+file.getAbsolutePath()+"'");
708
            }
709
            this.fname = file;
710
            if (file.exists()) {
711
                createProjectCopy(false);
712
            }
713
            I18nManager i18n = ToolsLocator.getI18nManager();
714
            ThreadSafeDialogsManager dialog = ToolsSwingLocator.getThreadSafeDialogsManager();
715
            dialog.message(
716
                    i18n.getTranslation("wrote_project"), 
717
                    JOptionPane.INFORMATION_MESSAGE
718
            );
719
        } catch (Exception ex) {
720
            createProjectCopy(true);
721
            throw new RuntimeException("Can't write project in '" + file.getAbsolutePath() + ".", ex);
722
        } finally {
723
            IOUtils.closeQuietly(zout);
724
            IOUtils.closeQuietly(fout);
725

    
726
        }
727
    }
728
    
729
    @Override
730
    public void saveState(OutputStream out, File rootFolder)
731
            throws PersistenceException {
732
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_STREAM, rootFolder).isProcessCanceled()) {
733
            return;
734
        }
735
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
736
        PersistentState state = null;
737
        state = manager.getState(this, true);
738
        try {
739
            if (rootFolder != null) {
740
                state.relativizeFiles(rootFolder);
741
            }
742
        } catch (Exception ex) {
743
            state.getContext().addError(ex);
744
        }
745
        manager.saveState(state, out, true);
746
        if (state.getContext().getErrors() != null) {
747
            createProjectCopy(true);
748
            throw state.getContext().getErrors();
749
        }
750
        this.fname = null;
751
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_STREAM, rootFolder);
752
    }
753
    
754
    private File getNameFileForProject(File actualProjectFile, boolean error) {
755
        // if there is a error, creates a file with a unique timecode
756
        // not error: return path with .gvsproj.bak extension that could exists
757
               
758
        if (actualProjectFile==null) {
759
            LOG.info("Doesn't have previous project to create a bak");
760
            return null;
761
        }
762
        String noExt = FilenameUtils.removeExtension(actualProjectFile.getAbsolutePath());
763
        String timeCode = new SimpleDateFormat("_MMddHHmmss").format(new Date());
764
        String ext = ".gvsproj.bak";
765

    
766
        int code = 0;
767
        if (noExt.length() > 230) {
768
            noExt = noExt.substring(0, 229);
769
        }
770
        
771
        File bakProjectFile;
772
        if (error) {
773
            bakProjectFile = new File(noExt + timeCode + ext);
774
            while (bakProjectFile.exists()) {
775
                code = code + 1;
776
                bakProjectFile = new File(noExt + timeCode + "_" + code + ext);
777
            }
778
        } else {
779
            bakProjectFile = new File(noExt + ext);
780
        }
781
        return bakProjectFile;
782
    }
783
    public File createProjectCopy(boolean error) {
784
        File actualProjectFile = ApplicationLocator.getProjectManager().getCurrentProject().getFile();
785
        File bakProjectFile = getNameFileForProject(actualProjectFile, error);
786
        if (bakProjectFile==null){
787
            return null;
788
        }
789
        if (!error){
790
            try {
791
                if (bakProjectFile.exists()){
792
                    FileUtils.deleteQuietly(bakProjectFile);
793
                }
794
            } catch (Exception ex) {
795
                LOG.warn("Not possible to delete file", ex);
796
            }
797
            try {
798
                FileUtils.copyFile(actualProjectFile, bakProjectFile);
799
            } catch (IOException ex) {
800
                LOG.warn("Can't create bak copy from project", ex);
801
            }
802
        } else {
803
            File bakProjectFileOld = getNameFileForProject(actualProjectFile, false);
804
            if (bakProjectFileOld.exists()) {
805
                try {
806
                    FileUtils.moveFile(bakProjectFileOld, bakProjectFile);
807
                } catch (IOException ex) {
808
                    LOG.warn("Can't rename file", ex);
809
                }
810
            } else {
811
                LOG.info("Can't find bak project. Probably doesn't exist or already has been renamed");
812
            }
813
        }
814
        
815
        return bakProjectFile;
816
    }
817

    
818
    @Deprecated
819
    @Override
820
    public void loadState(InputStream in) {
821
        loadState(in, null);
822
    }
823

    
824
    public void loadState(InputStream in, File rootFolder) {
825
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STREAM, rootFolder).isProcessCanceled()) {
826
            return;
827
        }
828
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
829
        try {
830
            PersistentContext context = manager.getNewContext();
831
            context.setCollectErrors(true);
832
            PersistentState state = manager.loadState(in, context);
833
            try {
834
                if (rootFolder != null) {
835
                    state.derelativizeFiles(rootFolder);
836
                }
837
            } catch (Exception ex) {
838
                state.getContext().addError(ex);
839
            }
840
            this.loadFromState(state);
841
            this.unloadedObjects = getUnloadedObjects(state.getContext());
842
            this.loadErrors = state.getContext().getErrors();
843

    
844
        } catch (PersistenceException e) {
845
            LOG.info("Can't load project to stream", e);
846
        }
847
        this.fname = null;
848
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STREAM, rootFolder);
849

    
850
    }
851

    
852

    
853

    
854
    /**
855
     * @param context
856
     * @return
857
     */
858
    private Set<String> getUnloadedObjects(PersistentContext context) {
859
        Set unloadedObjects = new HashSet();
860

    
861
        Iterator statesIterator = context.iterator();
862
        String className = null;
863

    
864
        while (statesIterator.hasNext()) {
865
            PersistentState aState = (PersistentState) statesIterator.next();
866
            try {
867
                className = aState.getTheClassName();
868
                DynStruct definition = aState.getDefinition();
869
                if (definition == null) {
870
                    unloadedObjects.add(className);
871
                }
872
            } catch (Throwable e) {
873
                // do nothing
874
            }
875
        }
876

    
877
        if(unloadedObjects.isEmpty()){
878
            return null;
879
        }
880

    
881
        return unloadedObjects;
882
    }
883

    
884
    @Override
885
    public Set<String> getUnloadedObjects() {
886
        return this.unloadedObjects;
887
    }
888

    
889
    @Override
890
    public List<Exception> getLoadErrors() {
891
        return this.loadErrors;
892
    }
893
    
894
    @Override
895
    public void loadState(File in) {
896
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_FILE, in).isProcessCanceled()) {
897
            return;
898
        }
899
        FileInputStream fin;
900
        try {
901
            fin = new FileInputStream(in);
902
            loadState(fin, new File(in.getParent()));
903
        } catch (FileNotFoundException e) {
904
            LOG.info("Can't load project to stream", e);
905
        }
906
        if ("bak".equals(FilenameUtils.getExtension(in.getAbsolutePath()))) {
907
            this.fname =  null;
908
        } else {
909
            this.fname = in;
910
        }
911
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_FILE, in);
912
    }
913

    
914
    //@SuppressWarnings("unchecked")
915
    @Override
916
    public void loadFromState(PersistentState state)
917
            throws PersistenceException {
918
        this.clean();
919
        PersistentContext context = state.getContext();
920
        
921
        notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STATE, state);
922

    
923
        this.setComments(state.getString("comments"));
924
        this.setCreationDate(state.getString("creationDate"));
925
        this.setModificationDate(state.getString("modificationDate"));
926
        this.setName(state.getString("name"));
927
        this.setOwner(state.getString("owner"));
928
        this.setSelectionColor((Color) state.get("selectionColor"));
929
        this.setProjection((IProjection) state.get("projection"));
930

    
931
        this.propertiesHelper = (ExtendedPropertiesHelper) state.get("propertiesHelper");
932

    
933
        List<ProjectExtent> extents = (List<ProjectExtent>) state
934
                .get("extents");
935
        for (int i = 0; i < extents.size(); i++) {
936
            this.addExtent(extents.get(i));
937
        }
938

    
939
        List<AbstractDocument> documents = (List<AbstractDocument>) state
940
                .get("documents");
941
        for (int i = 0; i < documents.size(); i++) {
942
            AbstractDocument doc = documents.get(i);
943
            if( doc != null ) {
944
                this.add(doc);
945
            }
946
        }
947

    
948
        try {
949
            List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
950

    
951
            for (int i = 0; i < persistentWindows.size(); i++) {
952
                try {
953
                    DocumentWindowInfo persistentWindow = persistentWindows.get(i);
954
                    String docName = persistentWindow.getDocumentName();
955
                    String docType = persistentWindow.getDocumentType();
956
                    Document doc = this.getDocument(docName, docType);
957
                    IWindow win = doc.getFactory().getMainWindow(doc);
958
                    if(win!=null){
959
                        win.getWindowInfo().setWindowInfo(persistentWindow.getWindowInfo());
960
                        PluginServices.getMDIManager().addWindow(win);
961
                    }
962
                } catch(Exception ex) {
963
                    if( !context.getCollectErrors() ) {
964
                        throw ex;
965
                    }
966
                    context.addError(ex);
967
                }
968
            }
969

    
970
            if (state.hasValue("projectWindowInfo")) {
971
                WindowInfo projectWindowInfo = (WindowInfo) state.get("projectWindowInfo");
972
                SwingUtilities.invokeLater(() -> {
973
                    ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(org.gvsig.app.extension.ProjectExtension.class);
974
                    pe.setProject(this);
975
                    pe.showProjectWindow(projectWindowInfo);
976
                });
977
            }
978
        } catch(Exception ex) {
979
            if( !context.getCollectErrors() ) {
980
                throw ex;
981
            }
982
            context.addError(ex);
983
        }
984
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STATE, state);
985
    }
986

    
987
    @Override
988
    public void saveToState(PersistentState state) throws PersistenceException {
989
        state.set("version", VERSION);
990
        state.set("comments", getComments());
991
        state.set("creationDate", this.getCreationDate());
992

    
993
        state.set("modificationDate", this.getModificationDate());
994
        state.set("name", this.getName());
995
        state.set("owner", this.getOwner());
996
        state.set("selectionColor", this.getSelectionColor());
997

    
998
        state.set("projection", this.getProjection());
999

    
1000
        state.set("extents", this.extents);
1001
        List<Document> docs = this.getDocuments();
1002
        List<Document> noTempDocs = new ArrayList<>();
1003
        for (Document document : docs) {
1004
            if(!document.isTemporary()){
1005
                noTempDocs.add(document);
1006
            }
1007
        }
1008
        state.set("documents", noTempDocs);
1009

    
1010
        state.set("propertiesHelper",propertiesHelper);
1011

    
1012
        List<DocumentWindowInfo> persistentWindows = new ArrayList<>();
1013
        MDIManager mdiMan = PluginServices.getMDIManager();
1014
        IWindow[] windows = mdiMan.getOrderedWindows();
1015
        for (int i = windows.length - 1; i >= 0; i--) {
1016
            IWindow window = windows[i];
1017
            if (window instanceof IDocumentWindow) {
1018
                WindowInfo wi = mdiMan.getWindowInfo(window);
1019
                DocumentWindowInfo dwi = new DocumentWindowInfo(
1020
                        wi,
1021
                        ((IDocumentWindow) window).getDocument().getTypeName(),
1022
                        ((IDocumentWindow) window).getDocument().getName());
1023
                persistentWindows.add(dwi);
1024
            } else if (window instanceof ProjectWindow) {
1025
                state.set("projectWindowInfo", mdiMan.getWindowInfo(window));
1026
            }
1027
        }
1028
        state.set("documentWindowsInformation", persistentWindows);
1029

    
1030
    }
1031

    
1032
    @Override
1033
    @Deprecated
1034
    public Object getProperty(Object key) {
1035
        return this.propertiesHelper.getProperty(key);
1036
    }
1037

    
1038
    @Override
1039
    @Deprecated
1040
    public void setProperty(Object key, Object obj) {
1041
        this.propertiesHelper.setProperty(key, obj);
1042
    }
1043

    
1044
    @Override
1045
    @Deprecated
1046
    public Map getExtendedProperties() {
1047
        return this.propertiesHelper.getExtendedProperties();
1048
    }
1049

    
1050
    @Override
1051
    public Object getProperty(String name) {
1052
        return this.propertiesHelper.getProperty(name);
1053
    }
1054

    
1055
    @Override
1056
    public void setProperty(String name, Object value) {
1057
        this.propertiesHelper.setProperty(name, value);
1058
    }
1059

    
1060
    @Override
1061
    public Map<String, Object> getProperties() {
1062
        return this.propertiesHelper.getExtendedProperties();
1063
    }
1064

    
1065
    public static class DocumentWindowInfo implements Persistent {
1066

    
1067
        public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
1068

    
1069
        private WindowInfo windowInfo;
1070
        private String documentType;
1071
        private String documentName;
1072

    
1073
        public DocumentWindowInfo() {
1074
        }
1075

    
1076
        DocumentWindowInfo(WindowInfo wi, String docType, String docName) {
1077
            windowInfo = wi;
1078
            documentType = docType;
1079
            documentName = docName;
1080
        }
1081

    
1082
        public WindowInfo getWindowInfo() {
1083
            return windowInfo;
1084
        }
1085

    
1086
        public String getDocumentType() {
1087
            return documentType;
1088
        }
1089

    
1090
        public String getDocumentName() {
1091
            return documentName;
1092
        }
1093

    
1094
        public void saveToState(PersistentState state)
1095
                throws PersistenceException {
1096
            state.set("windowInfo", this.windowInfo);
1097
            state.set("documentType", this.documentType);
1098
            state.set("documentName", this.documentName);
1099
        }
1100

    
1101
        public void loadFromState(PersistentState state)
1102
                throws PersistenceException {
1103
            this.windowInfo = (WindowInfo) state.get("windowInfo");
1104
            this.documentType = state.getString("documentType");
1105
            this.documentName = state.getString("documentName");
1106
        }
1107

    
1108
        public static void registerPersistent() {
1109
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1110
            DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
1111
            if (definition == null) {
1112
                definition = manager.addDefinition(
1113
                        DocumentWindowInfo.class,
1114
                        PERSISTENCE_DEFINITION_NAME,
1115
                        "DocumentWindowInfo persistence definition",
1116
                        null,
1117
                        null
1118
                );
1119
                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
1120
                definition.addDynFieldString("documentType").setMandatory(true);
1121
                definition.addDynFieldString("documentName").setMandatory(true);
1122
            }
1123

    
1124
        }
1125
    }
1126

    
1127
    public static void registerPersistent() {
1128
        AbstractDocument.registerPersistent();
1129
        DocumentWindowInfo.registerPersistent();
1130
        ProjectExtent.registerPersistent();
1131

    
1132
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1133
        DynStruct definition = manager.addDefinition(DefaultProject.class,
1134
                "Project", "Project Persistence definition", null, null);
1135
        definition.addDynFieldString("version").setMandatory(true);
1136
        definition.addDynFieldString("comments").setMandatory(true);
1137
        definition.addDynFieldString("creationDate").setMandatory(true);
1138
        definition.addDynFieldString("modificationDate").setMandatory(true);
1139
        definition.addDynFieldString("name").setMandatory(true);
1140
        definition.addDynFieldString("owner").setMandatory(true);
1141

    
1142
        definition.addDynFieldObject("selectionColor")
1143
                .setClassOfValue(Color.class).setMandatory(true);
1144
        definition.addDynFieldObject("projection")
1145
                .setClassOfValue(IProjection.class).setMandatory(true);
1146

    
1147
        definition.addDynFieldList("extents")
1148
                .setClassOfItems(ProjectExtent.class).setMandatory(true);
1149

    
1150
        definition.addDynFieldList("documents").setClassOfItems(Document.class)
1151
                .setMandatory(true);
1152

    
1153
        definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
1154

    
1155
        definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
1156

    
1157

    
1158
        definition.addDynFieldObject("propertiesHelper").setClassOfValue(ExtendedPropertiesHelper.class)
1159
                        .setMandatory(false);
1160

    
1161
    }
1162

    
1163
    /**
1164
     * @deprecated use getPreferences().setDefaultSelectionColor()
1165
     */
1166
    public static void setDefaultSelectionColor(Color color) {
1167
        getPreferences().setDefaultSelectionColor(color);
1168
    }
1169

    
1170
    /**
1171
     * @deprecated use getPreferences().getDefaultSelectionColor()
1172
     */
1173
    public static Color getDefaultSelectionColor() {
1174
        return getPreferences().getDefaultSelectionColor();
1175
    }
1176

    
1177
    /**
1178
     * @deprecated use getPreferences().getDefaultMapUnits()
1179
     */
1180
    public static int getDefaultMapUnits() {
1181
        return getPreferences().getDefaultMapUnits();
1182
    }
1183

    
1184
    /**
1185
     * @deprecated use getPreferences().getDefaultDistanceUnits()
1186
     */
1187
    public static int getDefaultDistanceUnits() {
1188
        return getPreferences().getDefaultDistanceUnits();
1189
    }
1190

    
1191
    /**
1192
     * @deprecated use getPreferences().getDefaultDistanceArea()
1193
     */
1194
    public static int getDefaultDistanceArea() {
1195
        return getPreferences().getDefaultDistanceArea();
1196
    }
1197

    
1198
    /**
1199
     * @deprecated use getPreferences().setDefaultMapUnits()
1200
     */
1201
    public static void setDefaultMapUnits(int mapUnits) {
1202
        getPreferences().setDefaultMapUnits(mapUnits);
1203
    }
1204

    
1205
    /**
1206
     * @deprecated use getPreferences().setDefaultDistanceUnits()
1207
     */
1208
    public static void setDefaultDistanceUnits(int distanceUnits) {
1209
        getPreferences().setDefaultDistanceUnits(distanceUnits);
1210
    }
1211

    
1212
    /**
1213
     * @deprecated use getPreferences().setDefaultDistanceArea()
1214
     */
1215
    public static void setDefaultDistanceArea(int distanceArea) {
1216
        getPreferences().setDefaultDistanceArea(distanceArea);
1217
    }
1218

    
1219
    /**
1220
     * @deprecated use getPreferences().setDefaultProjection()
1221
     */
1222
    public static void setDefaultProjection(IProjection defaultProjection) {
1223
        getPreferences().setDefaultProjection(defaultProjection);
1224
    }
1225

    
1226
    /**
1227
     * @deprecated use getPreferences().getDefaultProjection()
1228
     */
1229
    public static IProjection getDefaultProjection() {
1230
        return getPreferences().getDefaultProjection();
1231
    }
1232

    
1233
    /**
1234
     * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
1235
     * 2.1.0
1236
     */
1237
    public void setColor(String color) {
1238
        this.setSelectionColor(StringUtilities.string2Color(color));
1239
    }
1240

    
1241
    /**
1242
     * Return the selection color
1243
     *
1244
     * @return selection color as string
1245
     * @deprecated use {@link #getSelectionColor()}
1246
     */
1247
    public String getColor() {
1248
        return StringUtilities.color2String(selectionColor);
1249
    }
1250

    
1251
    /**
1252
     * Return the list of views of the project
1253
     *
1254
     * @return views as ArrayList of ProjectDocument
1255
     *
1256
     * @deprecated see {@link #getDocumentsByType(String)}
1257
     */
1258
    public List<Document> getViews() {
1259
        return getDocuments(ViewManager.TYPENAME);
1260
    }
1261

    
1262
    /**
1263
     * Add a view to the project
1264
     *
1265
     * @deprecated see {@link #add(AbstractDocument)}
1266
     */
1267
    public void addView(DefaultViewDocument v) {
1268
        add(v);
1269
    }
1270

    
1271
    /**
1272
     * Remove a view of the project
1273
     *
1274
     * @param index of the view as integer
1275
     *
1276
     * @deprecated see {@link #remove(AbstractDocument)}
1277
     */
1278
    public void delView(int i) {
1279
        List<Document> list = getDocuments(ViewManager.TYPENAME);
1280
        remove(list.get(i));
1281
    }
1282

    
1283
    /**
1284
     * @deprecated see {@link #getDocument(String, String)}
1285
     */
1286
    public Document getProjectDocumentByName(String name, String type) {
1287
        return this.getDocument(name, type);
1288
    }
1289

    
1290
    /**
1291
     * @deprecated see {@link #getDocuments(String)}
1292
     */
1293
    public List<Document> getDocumentsByType(String type) {
1294
        return this.getDocuments(type);
1295
    }
1296

    
1297
    /**
1298
     * @deprecated aun por decidir que API darle al copy/paste
1299
     */
1300
    public String exportToXML(AbstractDocument[] selectedItems)
1301
            throws SaveException {
1302
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1303
        throw new UnsupportedOperationException("This method is not supported");
1304
    }
1305

    
1306
    /**
1307
     * @deprecated aun por decidir que API darle al copy/paste
1308
     */
1309
    public void importFromXML(String sourceString, String docType) {
1310
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1311
        throw new UnsupportedOperationException("This method is not supported");
1312
    }
1313

    
1314
    /**
1315
     * @deprecated aun por decidir que API darle al copy/paste
1316
     */
1317
    public boolean isValidXMLForImport(String sourceString, String docType) {
1318
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1319
        throw new UnsupportedOperationException("This method is not supported");
1320
    }
1321

    
1322
    @Override
1323
    public boolean canImportDocuments(String data, String doctype) {
1324
        // TODO Auto-generated method stub
1325
        return false;
1326
    }
1327

    
1328
    @Override
1329
    public String exportDocumentsAsText(List<Document> documents) {
1330
        // TODO Auto-generated method stub
1331
        return null;
1332
    }
1333

    
1334
    @Override
1335
    public void importDocuments(String data, String doctype) {
1336
        // TODO Auto-generated method stub
1337

    
1338
    }
1339

    
1340
    @Override
1341
    public Document getActiveDocument() {
1342
        return this.getActiveDocument((Class<? extends Document>)null);
1343
    }
1344

    
1345
    @Override
1346
    public Document getActiveDocument(String documentTypeName) {
1347
        ApplicationManager application = ApplicationLocator.getManager();
1348
        for (DocumentManager documentManager : application.getProjectManager().getDocumentManagers()) {
1349
            if( StringUtils.equalsIgnoreCase(documentTypeName, documentManager.getTypeName())) {
1350
                return this.getActiveDocument(documentManager.getClassOfDocument());
1351
            }
1352
        }
1353
        return null;
1354
    }
1355
    
1356
    @Override
1357
    public List<Document> getOpenDocuments(Class<? extends Document> documentClass) {
1358
        return this.getOpenDocuments((Document doc) -> {
1359
            return doc!=null && (documentClass==null || documentClass.isAssignableFrom(doc.getClass()));
1360
        });
1361
    }
1362
    
1363
    @Override
1364
    public List<Document> getOpenDocuments(String type) {
1365
        return this.getOpenDocuments((Document doc) -> {
1366
            return  doc!=null && StringUtils.equals(type, doc.getTypeName());
1367
        });
1368
    }
1369
    
1370
    @SuppressWarnings("UnnecessaryContinue")
1371
    @Override
1372
    public List<Document> getOpenDocuments(Predicate<Document>filter) {
1373
        ApplicationManager application = ApplicationLocator.getManager();
1374

    
1375
        List<Document> docs = new ArrayList<>();
1376
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1377
        for (IWindow window : windows) {
1378
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1379
                // Cogemos no la primera ventana, si no la primera
1380
                // ventana de tipo documento (SingletonWindow).
1381
                // Y si, por si las moscas, no es un documento, atrapamos
1382
                // los errores y continuamos si no puede hacer un cast
1383
                // del Model a Document
1384
                try {
1385
                    Document doc = (Document) ((SingletonWindow) window).getWindowModel();
1386
                    if (filter == null) {
1387
                        docs.add(doc);
1388
                        continue;
1389
                    }
1390
                    if ( filter.test(doc) ) {
1391
                        docs.add(doc);
1392
                        continue;
1393
                    }
1394
                    // Ojo, no debe tener en cuenta los subdocumentos.
1395
                } catch (ClassCastException e) {
1396
                    // Do nothing, skip this window
1397
                }
1398
            }
1399
        }
1400
        return docs;
1401
    }
1402

    
1403
    @Override
1404
    public Document getActiveDocument(Class<? extends Document> documentClass) {
1405
        ApplicationManager application = ApplicationLocator.getManager();
1406

    
1407
        Document document = null;
1408
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1409
        IWindow window = null;
1410
        for (int i = 0; i < windows.length; i++) {
1411
            window = windows[i];
1412
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1413
                // Cogemos no la primera ventana, si no la primera
1414
                // ventana de tipo documento (SingletonWindow).
1415
                // Y si, por si las moscas, no es un documento, atrapamos
1416
                // los errores y continuamos si no puede hacer un cast
1417
                // del Model a Document
1418
                try {
1419
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1420
                    if (documentClass == null) {
1421
                        return document;
1422
                    }
1423
                    if (documentClass.isAssignableFrom(document.getClass())) {
1424
                        return document;
1425
                    }
1426
                    if( document instanceof DocumentsContainer ) {
1427
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentClass);
1428
                        return subdoc;
1429
                    }
1430
                    return null;
1431
                } catch (ClassCastException e) {
1432
                    // Do nothing, skip this window
1433
                }
1434
            }
1435
        }
1436
        return null;
1437
    }
1438
    
1439
    @Override
1440
    public Document getFirstDocument(Class<? extends Document> documentClass) {
1441
        ApplicationManager application = ApplicationLocator.getManager();
1442

    
1443
        Document document = null;
1444
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1445
        IWindow window = null;
1446
        for (int i = 0; i < windows.length; i++) {
1447
            window = windows[i];
1448
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1449
                // Cogemos no la primera ventana, si no la primera
1450
                // ventana de tipo documento (SingletonWindow).
1451
                // Y si, por si las moscas, no es un documento, atrapamos
1452
                // los errores y continuamos si no puede hacer un cast
1453
                // del Model a Document
1454
                try {
1455
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1456
                    if (documentClass == null) {
1457
                        return document;
1458
                    }
1459
                    if (documentClass.isAssignableFrom(document.getClass())) {
1460
                        return document;
1461
                    }
1462
                    if( document instanceof DocumentsContainer ) {
1463
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentClass);
1464
                        return subdoc;
1465
                    }
1466

    
1467
                } catch (ClassCastException e) {
1468
                    // Do nothing, skip this window
1469
                }
1470
            }
1471
        }
1472
        return null;
1473
    }
1474

    
1475
    @Override
1476
    public IWindow getActiveWindow(Class<? extends Document> documentClass) {
1477
        ApplicationManager application = ApplicationLocator.getManager();
1478

    
1479
        Document document;
1480
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1481
        for (IWindow window : windows) {
1482
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1483
                // Cogemos no la primera ventana, si no la primera
1484
                // ventana de tipo documento (SingletonWindow).
1485
                // Y por si las mosca no es un documento, atrapamos
1486
                // los errores y continuamos si no puede hacer un cast
1487
                // del Model a Document
1488
                try {
1489
                    if (documentClass == null) {
1490
                        return window;
1491
                    }
1492
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1493
                    if (documentClass.isAssignableFrom(document.getClass())) {
1494
                        return window;
1495
                    }
1496
                } catch (ClassCastException e) {
1497
                    // Do nothing, skip this window
1498
                }
1499
            }
1500
        }
1501
        return null;
1502
    }
1503

    
1504
    @Override
1505
    public void addObserver(Observer o) {
1506
        observableHelper.addObserver(o);
1507
    }
1508

    
1509
    @Override
1510
    public void deleteObserver(Observer o) {
1511
        observableHelper.deleteObserver(o);
1512
    }
1513

    
1514
    @Override
1515
    public void deleteObservers() {
1516
        observableHelper.deleteObservers();
1517
    }
1518

    
1519
    private ProjectNotification notifyObservers(int type) {
1520
        return notifyObservers(new DefaultProjectNotification(type));
1521
    }
1522

    
1523
    private ProjectNotification notifyObservers(int type, Document document) {
1524
        return notifyObservers(new DefaultProjectNotification(type, document));
1525
    }
1526
    
1527
    private ProjectNotification notifyObservers(int type, PersistentState state) {
1528
        return notifyObservers(new DefaultProjectNotification(type, state));
1529
    }
1530

    
1531
    private ProjectNotification notifyObservers(int type, File file) {
1532
        return notifyObservers(new DefaultProjectNotification(type, file));
1533
    }
1534

    
1535
    private ProjectNotification notifyObservers(ProjectNotification notifycation) {
1536
        try {
1537
            observableHelper.notifyObservers(this, notifycation);
1538
        } catch (Exception ex) {
1539
            LOG.info("Can't notify observers", ex);
1540
        }
1541
        notifyProjectManagerEvent(notifycation.getNotificationType());
1542
        return notifycation;
1543
    }
1544
    
1545
    private void notifyProjectManagerEvent(int type) {
1546
        try {
1547
            ProjectManager.getInstance().notifyProjectEvent(new ProjectEventImpl(this, type));
1548
        } catch (Exception ex) {
1549
            LOG.info("Can't notify project manager events", ex);
1550
        }
1551
    }
1552
    
1553
    class DefaultProjectNotification implements ProjectNotification {
1554

    
1555
        private int type;
1556
        private Document document;
1557
        private File file;
1558
        private boolean processCanceled = false;
1559
        private PersistentState state = null;
1560

    
1561
        DefaultProjectNotification(int type) {
1562
            this.type = type;
1563
        }
1564

    
1565
        DefaultProjectNotification(int type, Document document) {
1566
            this(type);
1567
            this.document = document;
1568
        }
1569

    
1570
        DefaultProjectNotification(int type, File file) {
1571
            this(type);
1572
            this.file = file;
1573
        }
1574

    
1575
        DefaultProjectNotification(int type, PersistentState state) {
1576
            this(type);
1577
            this.state = state;
1578
        }
1579

    
1580
        @Override
1581
        public int getNotificationType() {
1582
            return type;
1583
        }
1584

    
1585
        @Override
1586
        public Document getDocument() {
1587
            return document;
1588
        }
1589

    
1590
        @Override
1591
        public void cancelProcess() {
1592
            processCanceled = true;
1593
        }
1594

    
1595
        @Override
1596
        public boolean isProcessCanceled() {
1597
            return processCanceled;
1598
        }
1599

    
1600
        @Override
1601
        public File getFile() {
1602
            return file;
1603
        }
1604

    
1605
        @Override
1606
        public PersistentState getState() {
1607
            return this.state;
1608
        }
1609

    
1610
        @Override
1611
        public Project getProject() {
1612
            return DefaultProject.this;
1613
        }
1614
    }
1615

    
1616
}