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

History | View | Annotate | Download (51.9 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.layers.ExtendedPropertiesHelper;
82
import org.gvsig.fmap.mapcontext.layers.FLayer;
83
import org.gvsig.fmap.mapcontext.layers.FLayers;
84
import org.gvsig.tools.ToolsLocator;
85
import org.gvsig.tools.dispose.DisposeUtils;
86
import org.gvsig.tools.dynobject.DynStruct;
87
import org.gvsig.tools.i18n.I18nManager;
88
import org.gvsig.tools.observer.ObservableHelper;
89
import org.gvsig.tools.observer.Observer;
90
import org.gvsig.tools.persistence.PersistenceManager;
91
import org.gvsig.tools.persistence.Persistent;
92
import org.gvsig.tools.persistence.PersistentContext;
93
import org.gvsig.tools.persistence.PersistentState;
94
import org.gvsig.tools.persistence.exception.PersistenceException;
95
import org.gvsig.tools.swing.api.ToolsSwingLocator;
96
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
97
import org.gvsig.utils.StringUtilities;
98
import org.slf4j.Logger;
99
import org.slf4j.LoggerFactory;
100

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

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

    
114
    private ExtendedPropertiesHelper propertiesHelper = new ExtendedPropertiesHelper();
115

    
116
    private ObservableHelper observableHelper = new ObservableHelper();
117

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

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

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

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

    
132
    private PropertyChangeSupport change;
133

    
134
    private boolean modified = false;
135

    
136
    private String name = null;
137

    
138
    private String creationDate = null;
139

    
140
    private String modificationDate = null;
141

    
142
    private String owner = null;
143

    
144
    private String comments = null;
145

    
146
    private Color selectionColor = null;
147

    
148
    private List<Document> documents = null;
149

    
150
    private List<ProjectExtent> extents = null;
151

    
152
    private IProjection projection;
153

    
154
    private File fname = null;
155

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

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

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

    
175
        this.documents = new ArrayList<>();
176
        this.extents = new ArrayList<>();
177

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
343
    @Override
344
    public IProjection getProjection() {
345
        if (projection == null) {
346
            projection = getPreferences().getDefaultProjection();
347
        }
348
        return projection;
349
    }
350

    
351
    @Override
352
    public void setProjection(IProjection projection) {
353
        this.projection = projection;
354
    }
355

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

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

    
393
    /**
394
     * Return a list of documents in the project.
395
     *
396
     * @return documents as List of IProjectDocument
397
     */
398
    @Override
399
    public List<Document> getDocuments() {
400
        return this.getDocuments((Predicate<Document>)null);
401
    }
402

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

    
417
    @Override
418
    public List<Document> getDocuments(Class<? extends Document> documentClass) {
419
        return this.getDocuments((Document t) -> t!=null && 
420
                (documentClass==null  || documentClass.isAssignableFrom(t.getClass()))
421
        );
422
    }
423

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

    
441
    /**
442
     * Adds a document to the project
443
     *
444
     * @param document as Document
445
     */
446
    @Override
447
    public void add(Document document) {
448
        this.addDocument(document);
449
    }
450

    
451
    @Override
452
    public void addDocument(Document document) {
453
        logger.info("add('{}')", document.toString());
454

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

    
470
    @Override
471
    public void remove(Document doc) {
472
        this.removeDocument(doc);
473
    }
474

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

    
489
    @Override
490
    public Iterator<Document> iterator() {
491
        return documents.iterator();
492
    }
493

    
494
    @Override
495
    public boolean isEmpty() {
496
        return documents.isEmpty();
497
    }
498

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

    
520
        throw new RuntimeException(MessageFormat.format(
521
                "The layer '{1}' is not in a view", layer.getName()));
522
    }
523

    
524
    private boolean isView(FLayers layers, FLayer layer) {
525
        for (int i = 0; i < layers.getLayersCount(); i++) {
526
            if (layers.getLayer(i) instanceof FLayers) {
527
                if (isView((FLayers) layers.getLayer(i), layer)) {
528
                    return true;
529
                }
530
            }
531
            if (layers.getLayer(i) == layer) {
532
                return true;
533
            }
534
        }
535
        return false;
536
    }
537

    
538
    @Override
539
    public void addExtent(ProjectExtent arg1) {
540
        extents.add(arg1);
541
        change.firePropertyChange("addExtent", null, null);
542
    }
543

    
544
    @Override
545
    public ProjectExtent removeExtent(int arg0) {
546
        change.firePropertyChange("delExtent", null, null);
547
        return extents.remove(arg0);
548
    }
549

    
550
    @Override
551
    public ProjectExtent[] getExtents() {
552
        return (ProjectExtent[]) extents.toArray(new ProjectExtent[0]);
553
    }
554

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

    
592
    public Document getDocument(Predicate<Document>condition) {
593
        for (Document document : documents) {
594
            if( document == null ) {
595
                continue;
596
            }
597
            if( condition.test(document) ) {
598
                return document;
599
            }
600
        }
601
        return null;
602
    }
603

    
604
    @Override
605
    public Document getDocument(String name) {
606
        return this.getDocument(name, null);
607
    }
608

    
609
    public String getUniqueNameForDocument(String type, String name) {
610
        Document document = getDocument(name, type);
611
        if (document == null) {
612
            return name;
613
        }
614

    
615
        String newName = null;
616
        int num = this.getNextDocumentIndex(type);
617
        while (document != null) {
618
            newName = name + " - " + num++;
619
            document = getDocument(newName, type);
620
        }
621
        this.setNextDocumentIndex(type, num);
622
        return newName;
623
    }
624

    
625
    private int getNextDocumentIndex(String type) {
626
        if (nextDocumentIndexByType.get(type) == null) {
627
            nextDocumentIndexByType.put(type, 1);
628
            return 1;
629
        }
630
        return nextDocumentIndexByType.get(type);
631
    }
632

    
633
    private void setNextDocumentIndex(String type, int newIndex) {
634
        if (nextDocumentIndexByType.get(type) == null) {
635
            nextDocumentIndexByType.put(type, newIndex);
636
        } else {
637
            nextDocumentIndexByType.put(type, newIndex);
638
        }
639
    }
640

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

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

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

    
702
            zout.putNextEntry(new ZipEntry("preview.jpg"));
703
            try {
704
                ImageIO.write(preview, "jpg", zout);
705
            } catch (IOException ex) {
706
                LOG.warn("Can't save preview image'.", ex);
707
            }
708
            IOUtils.closeQuietly(zout);
709
            IOUtils.closeQuietly(fout);
710

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

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

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

    
823
    @Deprecated
824
    @Override
825
    public void loadState(InputStream in) {
826
        loadState(in, null);
827
    }
828

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

    
849
        } catch (PersistenceException e) {
850
            LOG.info("Can't load project to stream", e);
851
        }
852
        this.fname = null;
853
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STREAM, rootFolder);
854

    
855
    }
856

    
857

    
858

    
859
    /**
860
     * @param context
861
     * @return
862
     */
863
    private Set<String> getUnloadedObjects(PersistentContext context) {
864
        Set unloadedObjects = new HashSet();
865

    
866
        Iterator statesIterator = context.iterator();
867
        String className = null;
868

    
869
        while (statesIterator.hasNext()) {
870
            PersistentState aState = (PersistentState) statesIterator.next();
871
            try {
872
                className = aState.getTheClassName();
873
                DynStruct definition = aState.getDefinition();
874
                if (definition == null) {
875
                    unloadedObjects.add(className);
876
                }
877
            } catch (Throwable e) {
878
                // do nothing
879
            }
880
        }
881

    
882
        if(unloadedObjects.isEmpty()){
883
            return null;
884
        }
885

    
886
        return unloadedObjects;
887
    }
888

    
889
    @Override
890
    public Set<String> getUnloadedObjects() {
891
        return this.unloadedObjects;
892
    }
893

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

    
919
    //@SuppressWarnings("unchecked")
920
    @Override
921
    public void loadFromState(PersistentState state)
922
            throws PersistenceException {
923
        this.clean();
924
        PersistentContext context = state.getContext();
925
        
926
        notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STATE, state);
927

    
928
        this.setComments(state.getString("comments"));
929
        this.setCreationDate(state.getString("creationDate"));
930
        this.setModificationDate(state.getString("modificationDate"));
931
        this.setName(state.getString("name"));
932
        this.setOwner(state.getString("owner"));
933
        this.setSelectionColor((Color) state.get("selectionColor"));
934
        this.setProjection((IProjection) state.get("projection"));
935

    
936
        this.propertiesHelper = (ExtendedPropertiesHelper) state.get("propertiesHelper");
937

    
938
        List<ProjectExtent> extents = (List<ProjectExtent>) state
939
                .get("extents");
940
        for (int i = 0; i < extents.size(); i++) {
941
            this.addExtent(extents.get(i));
942
        }
943

    
944
        List<AbstractDocument> documents = (List<AbstractDocument>) state
945
                .get("documents");
946
        for (int i = 0; i < documents.size(); i++) {
947
            AbstractDocument doc = documents.get(i);
948
            if( doc != null ) {
949
                this.add(doc);
950
            }
951
        }
952

    
953
        try {
954
            List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
955

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

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

    
992
    @Override
993
    public void saveToState(PersistentState state) throws PersistenceException {
994
        state.set("version", VERSION);
995
        state.set("comments", getComments());
996
        state.set("creationDate", this.getCreationDate());
997

    
998
        state.set("modificationDate", this.getModificationDate());
999
        state.set("name", this.getName());
1000
        state.set("owner", this.getOwner());
1001
        state.set("selectionColor", this.getSelectionColor());
1002

    
1003
        state.set("projection", this.getProjection());
1004

    
1005
        state.set("extents", this.extents);
1006
        List<Document> docs = this.getDocuments();
1007
        List<Document> noTempDocs = new ArrayList<>();
1008
        for (Document document : docs) {
1009
            if(!document.isTemporary()){
1010
                noTempDocs.add(document);
1011
            }
1012
        }
1013
        state.set("documents", noTempDocs);
1014

    
1015
        state.set("propertiesHelper",propertiesHelper);
1016

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

    
1035
    }
1036

    
1037
    @Override
1038
    @Deprecated
1039
    public Object getProperty(Object key) {
1040
        return this.propertiesHelper.getProperty(key);
1041
    }
1042

    
1043
    @Override
1044
    @Deprecated
1045
    public void setProperty(Object key, Object obj) {
1046
        this.propertiesHelper.setProperty(key, obj);
1047
    }
1048

    
1049
    @Override
1050
    @Deprecated
1051
    public Map getExtendedProperties() {
1052
        return this.propertiesHelper.getExtendedProperties();
1053
    }
1054

    
1055
    @Override
1056
    public Object getProperty(String name) {
1057
        return this.propertiesHelper.getProperty(name);
1058
    }
1059

    
1060
    @Override
1061
    public void setProperty(String name, Object value) {
1062
        this.propertiesHelper.setProperty(name, value);
1063
    }
1064

    
1065
    @Override
1066
    public Map<String, Object> getProperties() {
1067
        return this.propertiesHelper.getExtendedProperties();
1068
    }
1069

    
1070
    public static class DocumentWindowInfo implements Persistent {
1071

    
1072
        public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
1073

    
1074
        private WindowInfo windowInfo;
1075
        private String documentType;
1076
        private String documentName;
1077

    
1078
        public DocumentWindowInfo() {
1079
        }
1080

    
1081
        DocumentWindowInfo(WindowInfo wi, String docType, String docName) {
1082
            windowInfo = wi;
1083
            documentType = docType;
1084
            documentName = docName;
1085
        }
1086

    
1087
        public WindowInfo getWindowInfo() {
1088
            return windowInfo;
1089
        }
1090

    
1091
        public String getDocumentType() {
1092
            return documentType;
1093
        }
1094

    
1095
        public String getDocumentName() {
1096
            return documentName;
1097
        }
1098

    
1099
        @Override
1100
        public void saveToState(PersistentState state)
1101
                throws PersistenceException {
1102
            state.set("windowInfo", this.windowInfo);
1103
            state.set("documentType", this.documentType);
1104
            state.set("documentName", this.documentName);
1105
        }
1106

    
1107
        @Override
1108
        public void loadFromState(PersistentState state)
1109
                throws PersistenceException {
1110
            this.windowInfo = (WindowInfo) state.get("windowInfo");
1111
            this.documentType = state.getString("documentType");
1112
            this.documentName = state.getString("documentName");
1113
        }
1114

    
1115
        public static void registerPersistent() {
1116
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1117
            DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
1118
            if (definition == null) {
1119
                definition = manager.addDefinition(
1120
                        DocumentWindowInfo.class,
1121
                        PERSISTENCE_DEFINITION_NAME,
1122
                        "DocumentWindowInfo persistence definition",
1123
                        null,
1124
                        null
1125
                );
1126
                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
1127
                definition.addDynFieldString("documentType").setMandatory(true);
1128
                definition.addDynFieldString("documentName").setMandatory(true);
1129
            }
1130

    
1131
        }
1132
    }
1133

    
1134
    public static void registerPersistent() {
1135
        AbstractDocument.registerPersistent();
1136
        DocumentWindowInfo.registerPersistent();
1137
        ProjectExtent.registerPersistent();
1138

    
1139
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1140
        DynStruct definition = manager.addDefinition(DefaultProject.class,
1141
                "Project", "Project Persistence definition", null, null);
1142
        definition.addDynFieldString("version").setMandatory(true);
1143
        definition.addDynFieldString("comments").setMandatory(true);
1144
        definition.addDynFieldString("creationDate").setMandatory(true);
1145
        definition.addDynFieldString("modificationDate").setMandatory(true);
1146
        definition.addDynFieldString("name").setMandatory(true);
1147
        definition.addDynFieldString("owner").setMandatory(true);
1148

    
1149
        definition.addDynFieldObject("selectionColor")
1150
                .setClassOfValue(Color.class).setMandatory(true);
1151
        definition.addDynFieldObject("projection")
1152
                .setClassOfValue(IProjection.class).setMandatory(true);
1153

    
1154
        definition.addDynFieldList("extents")
1155
                .setClassOfItems(ProjectExtent.class).setMandatory(true);
1156

    
1157
        definition.addDynFieldList("documents").setClassOfItems(Document.class)
1158
                .setMandatory(true);
1159

    
1160
        definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
1161

    
1162
        definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
1163

    
1164

    
1165
        definition.addDynFieldObject("propertiesHelper").setClassOfValue(ExtendedPropertiesHelper.class)
1166
                        .setMandatory(false);
1167

    
1168
    }
1169

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

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

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

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

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

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

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

    
1219
    /**
1220
     * @deprecated use getPreferences().setDefaultDistanceArea()
1221
     */
1222
    public static void setDefaultDistanceArea(int distanceArea) {
1223
        getPreferences().setDefaultDistanceArea(distanceArea);
1224
    }
1225

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

    
1233
    /**
1234
     * @deprecated use getPreferences().getDefaultProjection()
1235
     */
1236
    public static IProjection getDefaultProjection() {
1237
        return getPreferences().getDefaultProjection();
1238
    }
1239

    
1240
    /**
1241
     * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
1242
     * 2.1.0
1243
     */
1244
    public void setColor(String color) {
1245
        this.setSelectionColor(StringUtilities.string2Color(color));
1246
    }
1247

    
1248
    /**
1249
     * Return the selection color
1250
     *
1251
     * @return selection color as string
1252
     * @deprecated use {@link #getSelectionColor()}
1253
     */
1254
    public String getColor() {
1255
        return StringUtilities.color2String(selectionColor);
1256
    }
1257

    
1258
    /**
1259
     * Return the list of views of the project
1260
     *
1261
     * @return views as ArrayList of ProjectDocument
1262
     *
1263
     * @deprecated see {@link #getDocumentsByType(String)}
1264
     */
1265
    public List<Document> getViews() {
1266
        return getDocuments(ViewManager.TYPENAME);
1267
    }
1268

    
1269
    /**
1270
     * Add a view to the project
1271
     *
1272
     * @deprecated see {@link #add(AbstractDocument)}
1273
     */
1274
    public void addView(DefaultViewDocument v) {
1275
        add(v);
1276
    }
1277

    
1278
    /**
1279
     * Remove a view of the project
1280
     *
1281
     * @param index of the view as integer
1282
     *
1283
     * @deprecated see {@link #remove(AbstractDocument)}
1284
     */
1285
    public void delView(int i) {
1286
        List<Document> list = getDocuments(ViewManager.TYPENAME);
1287
        remove(list.get(i));
1288
    }
1289

    
1290
    /**
1291
     * @deprecated see {@link #getDocument(String, String)}
1292
     */
1293
    public Document getProjectDocumentByName(String name, String type) {
1294
        return this.getDocument(name, type);
1295
    }
1296

    
1297
    /**
1298
     * @deprecated see {@link #getDocuments(String)}
1299
     */
1300
    public List<Document> getDocumentsByType(String type) {
1301
        return this.getDocuments(type);
1302
    }
1303

    
1304
    /**
1305
     * @deprecated aun por decidir que API darle al copy/paste
1306
     */
1307
    public String exportToXML(AbstractDocument[] selectedItems)
1308
            throws SaveException {
1309
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1310
        throw new UnsupportedOperationException("This method is not supported");
1311
    }
1312

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

    
1321
    /**
1322
     * @deprecated aun por decidir que API darle al copy/paste
1323
     */
1324
    public boolean isValidXMLForImport(String sourceString, String docType) {
1325
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1326
        throw new UnsupportedOperationException("This method is not supported");
1327
    }
1328

    
1329
    @Override
1330
    public boolean canImportDocuments(String data, String doctype) {
1331
        // TODO Auto-generated method stub
1332
        return false;
1333
    }
1334

    
1335
    @Override
1336
    public String exportDocumentsAsText(List<Document> documents) {
1337
        // TODO Auto-generated method stub
1338
        return null;
1339
    }
1340

    
1341
    @Override
1342
    public void importDocuments(String data, String doctype) {
1343
        // TODO Auto-generated method stub
1344

    
1345
    }
1346

    
1347
    @Override
1348
    public Document getActiveDocument() {
1349
        return this.getActiveDocument((Class<? extends Document>)null);
1350
    }
1351

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

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

    
1410
    @Override
1411
    public Document getActiveDocument(Class<? extends Document> documentClass) {
1412
        ApplicationManager application = ApplicationLocator.getManager();
1413

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

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

    
1474
                } catch (ClassCastException e) {
1475
                    // Do nothing, skip this window
1476
                }
1477
            }
1478
        }
1479
        return null;
1480
    }
1481

    
1482
    @Override
1483
    public IWindow getActiveWindow(Class<? extends Document> documentClass) {
1484
        ApplicationManager application = ApplicationLocator.getManager();
1485

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

    
1511
    @Override
1512
    public void addObserver(Observer o) {
1513
        observableHelper.addObserver(o);
1514
    }
1515

    
1516
    @Override
1517
    public void deleteObserver(Observer o) {
1518
        observableHelper.deleteObserver(o);
1519
    }
1520

    
1521
    @Override
1522
    public void deleteObservers() {
1523
        observableHelper.deleteObservers();
1524
    }
1525

    
1526
    private ProjectNotification notifyObservers(int type) {
1527
        return notifyObservers(new DefaultProjectNotification(type));
1528
    }
1529

    
1530
    private ProjectNotification notifyObservers(int type, Document document) {
1531
        return notifyObservers(new DefaultProjectNotification(type, document));
1532
    }
1533
    
1534
    private ProjectNotification notifyObservers(int type, PersistentState state) {
1535
        return notifyObservers(new DefaultProjectNotification(type, state));
1536
    }
1537

    
1538
    private ProjectNotification notifyObservers(int type, File file) {
1539
        return notifyObservers(new DefaultProjectNotification(type, file));
1540
    }
1541

    
1542
    private ProjectNotification notifyObservers(ProjectNotification notifycation) {
1543
        try {
1544
            observableHelper.notifyObservers(this, notifycation);
1545
        } catch (Exception ex) {
1546
            LOG.info("Can't notify observers", ex);
1547
        }
1548
        notifyProjectManagerEvent(notifycation.getNotificationType());
1549
        return notifycation;
1550
    }
1551
    
1552
    private void notifyProjectManagerEvent(int type) {
1553
        try {
1554
            ProjectManager.getInstance().notifyProjectEvent(new ProjectEventImpl(this, type));
1555
        } catch (Exception ex) {
1556
            LOG.info("Can't notify project manager events", ex);
1557
        }
1558
    }
1559
    
1560
    class DefaultProjectNotification implements ProjectNotification {
1561

    
1562
        private int type;
1563
        private Document document;
1564
        private File file;
1565
        private boolean processCanceled = false;
1566
        private PersistentState state = null;
1567

    
1568
        DefaultProjectNotification(int type) {
1569
            this.type = type;
1570
        }
1571

    
1572
        DefaultProjectNotification(int type, Document document) {
1573
            this(type);
1574
            this.document = document;
1575
        }
1576

    
1577
        DefaultProjectNotification(int type, File file) {
1578
            this(type);
1579
            this.file = file;
1580
        }
1581

    
1582
        DefaultProjectNotification(int type, PersistentState state) {
1583
            this(type);
1584
            this.state = state;
1585
        }
1586

    
1587
        @Override
1588
        public int getNotificationType() {
1589
            return type;
1590
        }
1591

    
1592
        @Override
1593
        public Document getDocument() {
1594
            return document;
1595
        }
1596

    
1597
        @Override
1598
        public void cancelProcess() {
1599
            processCanceled = true;
1600
        }
1601

    
1602
        @Override
1603
        public boolean isProcessCanceled() {
1604
            return processCanceled;
1605
        }
1606

    
1607
        @Override
1608
        public File getFile() {
1609
            return file;
1610
        }
1611

    
1612
        @Override
1613
        public PersistentState getState() {
1614
            return this.state;
1615
        }
1616

    
1617
        @Override
1618
        public Project getProject() {
1619
            return DefaultProject.this;
1620
        }
1621
    }
1622

    
1623
}