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

History | View | Annotate | Download (50.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

    
63
import org.cresques.cts.IProjection;
64

    
65
import org.gvsig.andami.PluginServices;
66
import org.gvsig.andami.ui.mdiManager.IWindow;
67
import org.gvsig.andami.ui.mdiManager.MDIManager;
68
import org.gvsig.andami.ui.mdiManager.SingletonWindow;
69
import org.gvsig.andami.ui.mdiManager.WindowInfo;
70
import org.gvsig.app.ApplicationLocator;
71
import org.gvsig.app.ApplicationManager;
72
import org.gvsig.app.extension.ProjectExtension;
73
import org.gvsig.app.extension.Version;
74
import org.gvsig.app.project.ProjectManager.ProjectEventImpl;
75
import org.gvsig.app.project.documents.AbstractDocument;
76
import org.gvsig.app.project.documents.Document;
77
import org.gvsig.app.project.documents.exceptions.SaveException;
78
import org.gvsig.app.project.documents.gui.IDocumentWindow;
79
import org.gvsig.app.project.documents.gui.ProjectWindow;
80
import org.gvsig.app.project.documents.view.DefaultViewDocument;
81
import org.gvsig.app.project.documents.view.ViewManager;
82
import org.gvsig.fmap.mapcontext.MapContext;
83
import org.gvsig.fmap.mapcontext.layers.ExtendedPropertiesHelper;
84
import org.gvsig.fmap.mapcontext.layers.FLayer;
85
import org.gvsig.fmap.mapcontext.layers.FLayers;
86
import org.gvsig.tools.ToolsLocator;
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

    
100
import org.slf4j.Logger;
101
import org.slf4j.LoggerFactory;
102

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

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

    
116
    private ExtendedPropertiesHelper propertiesHelper = new ExtendedPropertiesHelper();
117

    
118
    private ObservableHelper observableHelper = new ObservableHelper();
119

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

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

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

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

    
134
    private PropertyChangeSupport change;
135

    
136
    private boolean modified = false;
137

    
138
    private String name = null;
139

    
140
    private String creationDate = null;
141

    
142
    private String modificationDate = null;
143

    
144
    private String owner = null;
145

    
146
    private String comments = null;
147

    
148
    private Color selectionColor = null;
149

    
150
    private List<Document> documents = null;
151

    
152
    private List<ProjectExtent> extents = null;
153

    
154
    private IProjection projection;
155

    
156
    private File fname = null;
157

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
451
        if (notifyObservers(ProjectNotification.BEFORE_ADD_DOCUMENT, document).isProcessCanceled()) {
452
            return;
453
        }
454
        document.addPropertyChangeListener(this);
455
        document.setProject(this);
456
        document.setName(this.getUniqueNameForDocument(document.getTypeName(),
457
                document.getName()));
458
        documents.add(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
    }
482

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

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

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

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

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

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

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

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

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

    
580
    public Document getDocument(Predicate<Document>condition) {
581
        for (Document document : documents) {
582
            if( condition.test(document) ) {
583
                return document;
584
            }
585
        }
586
        return null;
587
    }
588

    
589
    @Override
590
    public Document getDocument(String name) {
591
        return this.getDocument(name, null);
592
    }
593

    
594
    public String getUniqueNameForDocument(String type, String name) {
595
        Document document = getDocument(name, type);
596
        if (document == null) {
597
            return name;
598
        }
599

    
600
        String newName = null;
601
        int num = this.getNextDocumentIndex(type);
602
        while (document != null) {
603
            newName = name + " - " + num++;
604
            document = getDocument(newName, type);
605
        }
606
        this.setNextDocumentIndex(type, num);
607
        return newName;
608
    }
609

    
610
    private int getNextDocumentIndex(String type) {
611
        if (nextDocumentIndexByType.get(type) == null) {
612
            nextDocumentIndexByType.put(type, new Integer(1));
613
            return 1;
614
        }
615
        return nextDocumentIndexByType.get(type).intValue();
616
    }
617

    
618
    private void setNextDocumentIndex(String type, int newIndex) {
619
        if (nextDocumentIndexByType.get(type) == null) {
620
            nextDocumentIndexByType.put(type, new Integer(newIndex));
621
        } else {
622
            nextDocumentIndexByType.put(type, new Integer(newIndex));
623
        }
624
    }
625

    
626
    @Override
627
    public void saveState(File out) throws PersistenceException {
628
        FileOutputStream fout;
629
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_FILE, out).isProcessCanceled()) {
630
            return;
631
        }
632
        try {
633
            fout = new FileOutputStream(out);
634
            saveState(fout, new File(out.getParent()));
635
        } catch (FileNotFoundException e) {
636
            createProjectCopy(true);
637
            throw new PersistenceException(e);
638
        }
639
        if( !isValidZIP(out) ) {
640
            throw new PersistenceException(new ZipException());
641
        }
642
        this.fname = out;
643
        //sacar copia al bak
644
        createProjectCopy(false);
645
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_FILE, out);
646
    }
647

    
648
    boolean isValidZIP(final File file) {
649
        ZipFile zipfile = null;
650
        try {
651
            zipfile = new ZipFile(file);
652
            return true;
653
        } catch (IOException e) {
654
            //sacar copia. 
655
            return false;
656
        } finally {
657
            try {
658
                if (zipfile != null) {
659
                    zipfile.close();
660
                    zipfile = null;
661
                }
662
            } catch (IOException e) {
663
            }
664
        }
665
    }
666
   
667
    @Override
668
    public File getFile() {
669
        return this.fname;
670
    }
671

    
672
    @Deprecated
673
    @Override
674
    public void saveState(OutputStream out) throws PersistenceException {
675
        saveState(out, null);
676
    }
677
    
678
    @Override
679
    public void saveState(File file, BufferedImage preview) {
680
        FileOutputStream fout=null;
681
        ZipOutputStream zout=null;
682
        try {
683
            fout = new FileOutputStream(file);
684
            zout = new ZipOutputStream(fout);
685
            this.saveState(zout, file.getParentFile());
686

    
687
            zout.putNextEntry(new ZipEntry("preview.jpg"));
688
            try {
689
                ImageIO.write(preview, "jpg", zout);
690
            } catch (IOException ex) {
691
                LOG.warn("Can't save preview image'.", ex);
692
            }
693
            IOUtils.closeQuietly(zout);
694
            IOUtils.closeQuietly(fout);
695

    
696
            if( !isValidZIP(file) ) {
697
                throw new ZipException("Invalid project file '"+file.getAbsolutePath()+"'");
698
            }
699
            this.fname = file;
700
            if (file.exists()) {
701
                createProjectCopy(false);
702
            }
703
            I18nManager i18n = ToolsLocator.getI18nManager();
704
            ThreadSafeDialogsManager dialog = ToolsSwingLocator.getThreadSafeDialogsManager();
705
            dialog.message(
706
                    i18n.getTranslation("wrote_project"), 
707
                    JOptionPane.INFORMATION_MESSAGE
708
            );
709
        } catch (Exception ex) {
710
            createProjectCopy(true);
711
            throw new RuntimeException("Can't write project in '" + file.getAbsolutePath() + ".", ex);
712
        } finally {
713
            IOUtils.closeQuietly(zout);
714
            IOUtils.closeQuietly(fout);
715

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

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

    
808
    @Deprecated
809
    @Override
810
    public void loadState(InputStream in) {
811
        loadState(in, null);
812
    }
813

    
814
    public void loadState(InputStream in, File rootFolder) {
815
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STREAM, rootFolder).isProcessCanceled()) {
816
            return;
817
        }
818
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
819
        try {
820
            PersistentContext context = manager.getNewContext();
821
            context.setCollectErrors(true);
822
            PersistentState state = manager.loadState(in, context);
823
            try {
824
                if (rootFolder != null) {
825
                    state.derelativizeFiles(rootFolder);
826
                }
827
            } catch (Exception ex) {
828
                state.getContext().addError(ex);
829
            }
830
            this.loadFromState(state);
831
            this.unloadedObjects = getUnloadedObjects(state.getContext());
832
            this.loadErrors = state.getContext().getErrors();
833

    
834
        } catch (PersistenceException e) {
835
            LOG.info("Can't load project to stream", e);
836
        }
837
        this.fname = null;
838
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STREAM, rootFolder);
839

    
840
    }
841

    
842

    
843

    
844
    /**
845
     * @param context
846
     * @return
847
     */
848
    private Set<String> getUnloadedObjects(PersistentContext context) {
849
        Set unloadedObjects = new HashSet();
850

    
851
        Iterator statesIterator = context.iterator();
852
        String className = null;
853

    
854
        while (statesIterator.hasNext()) {
855
            PersistentState aState = (PersistentState) statesIterator.next();
856
            try {
857
                className = aState.getTheClassName();
858
                DynStruct definition = aState.getDefinition();
859
                if (definition == null) {
860
                    unloadedObjects.add(className);
861
                }
862
            } catch (Throwable e) {
863
                // do nothing
864
            }
865
        }
866

    
867
        if(unloadedObjects.isEmpty()){
868
            return null;
869
        }
870

    
871
        return unloadedObjects;
872
    }
873

    
874
    @Override
875
    public Set<String> getUnloadedObjects() {
876
        return this.unloadedObjects;
877
    }
878

    
879
    @Override
880
    public List<Exception> getLoadErrors() {
881
        return this.loadErrors;
882
    }
883
    
884
    @Override
885
    public void loadState(File in) {
886
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_FILE, in).isProcessCanceled()) {
887
            return;
888
        }
889
        FileInputStream fin;
890
        try {
891
            fin = new FileInputStream(in);
892
            loadState(fin, new File(in.getParent()));
893
        } catch (FileNotFoundException e) {
894
            LOG.info("Can't load project to stream", e);
895
        }
896
        if ("bak".equals(FilenameUtils.getExtension(in.getAbsolutePath()))) {
897
            this.fname =  null;
898
        } else {
899
            this.fname = in;
900
        }
901
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_FILE, in);
902
    }
903

    
904
    //@SuppressWarnings("unchecked")
905
    @Override
906
    public void loadFromState(PersistentState state)
907
            throws PersistenceException {
908
        this.clean();
909
        PersistentContext context = state.getContext();
910
        
911
        notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STATE, state);
912

    
913
        this.setComments(state.getString("comments"));
914
        this.setCreationDate(state.getString("creationDate"));
915
        this.setModificationDate(state.getString("modificationDate"));
916
        this.setName(state.getString("name"));
917
        this.setOwner(state.getString("owner"));
918
        this.setSelectionColor((Color) state.get("selectionColor"));
919
        this.setProjection((IProjection) state.get("projection"));
920

    
921
        this.propertiesHelper = (ExtendedPropertiesHelper) state.get("propertiesHelper");
922

    
923
        List<ProjectExtent> extents = (List<ProjectExtent>) state
924
                .get("extents");
925
        for (int i = 0; i < extents.size(); i++) {
926
            this.addExtent(extents.get(i));
927
        }
928

    
929
        List<AbstractDocument> documents = (List<AbstractDocument>) state
930
                .get("documents");
931
        for (int i = 0; i < documents.size(); i++) {
932
            AbstractDocument doc = documents.get(i);
933
            if( doc != null ) {
934
                this.add(doc);
935
            }
936
        }
937

    
938
        try {
939
            List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
940

    
941
            for (int i = 0; i < persistentWindows.size(); i++) {
942
                try {
943
                    DocumentWindowInfo persistentWindow = persistentWindows.get(i);
944
                    String docName = persistentWindow.getDocumentName();
945
                    String docType = persistentWindow.getDocumentType();
946
                    Document doc = this.getDocument(docName, docType);
947
                    IWindow win = doc.getFactory().getMainWindow(doc);
948
                    if(win!=null){
949
                        win.getWindowInfo().setWindowInfo(persistentWindow.getWindowInfo());
950
                        PluginServices.getMDIManager().addWindow(win);
951
                    }
952
                } catch(Exception ex) {
953
                    if( !context.getCollectErrors() ) {
954
                        throw ex;
955
                    }
956
                    context.addError(ex);
957
                }
958
            }
959

    
960
            if (state.hasValue("projectWindowInfo")) {
961
                WindowInfo projectWindowInfo = (WindowInfo) state.get("projectWindowInfo");
962
                SwingUtilities.invokeLater(() -> {
963
                    ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(org.gvsig.app.extension.ProjectExtension.class);
964
                    pe.setProject(this);
965
                    pe.showProjectWindow(projectWindowInfo);
966
                });
967
            }
968
        } catch(Exception ex) {
969
            if( !context.getCollectErrors() ) {
970
                throw ex;
971
            }
972
            context.addError(ex);
973
        }
974
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STATE, state);
975
    }
976

    
977
    @Override
978
    public void saveToState(PersistentState state) throws PersistenceException {
979
        state.set("version", VERSION);
980
        state.set("comments", getComments());
981
        state.set("creationDate", this.getCreationDate());
982

    
983
        state.set("modificationDate", this.getModificationDate());
984
        state.set("name", this.getName());
985
        state.set("owner", this.getOwner());
986
        state.set("selectionColor", this.getSelectionColor());
987

    
988
        state.set("projection", this.getProjection());
989

    
990
        state.set("extents", this.extents);
991
        List<Document> docs = this.getDocuments();
992
        List<Document> noTempDocs = new ArrayList<>();
993
        for (Document document : docs) {
994
            if(!document.isTemporary()){
995
                noTempDocs.add(document);
996
            }
997
        }
998
        state.set("documents", noTempDocs);
999

    
1000
        state.set("propertiesHelper",propertiesHelper);
1001

    
1002
        List<DocumentWindowInfo> persistentWindows = new ArrayList<>();
1003
        MDIManager mdiMan = PluginServices.getMDIManager();
1004
        IWindow[] windows = mdiMan.getOrderedWindows();
1005
        for (int i = windows.length - 1; i >= 0; i--) {
1006
            IWindow window = windows[i];
1007
            if (window instanceof IDocumentWindow) {
1008
                WindowInfo wi = mdiMan.getWindowInfo(window);
1009
                DocumentWindowInfo dwi = new DocumentWindowInfo(
1010
                        wi,
1011
                        ((IDocumentWindow) window).getDocument().getTypeName(),
1012
                        ((IDocumentWindow) window).getDocument().getName());
1013
                persistentWindows.add(dwi);
1014
            } else if (window instanceof ProjectWindow) {
1015
                state.set("projectWindowInfo", mdiMan.getWindowInfo(window));
1016
            }
1017
        }
1018
        state.set("documentWindowsInformation", persistentWindows);
1019

    
1020
    }
1021

    
1022
    @Override
1023
    @Deprecated
1024
    public Object getProperty(Object key) {
1025
        return this.propertiesHelper.getProperty(key);
1026
    }
1027

    
1028
    @Override
1029
    @Deprecated
1030
    public void setProperty(Object key, Object obj) {
1031
        this.propertiesHelper.setProperty(key, obj);
1032
    }
1033

    
1034
    @Override
1035
    @Deprecated
1036
    public Map getExtendedProperties() {
1037
        return this.propertiesHelper.getExtendedProperties();
1038
    }
1039

    
1040
    @Override
1041
    public Object getProperty(String name) {
1042
        return this.propertiesHelper.getProperty(name);
1043
    }
1044

    
1045
    @Override
1046
    public void setProperty(String name, Object value) {
1047
        this.propertiesHelper.setProperty(name, value);
1048
    }
1049

    
1050
    @Override
1051
    public Map<String, Object> getProperties() {
1052
        return this.propertiesHelper.getExtendedProperties();
1053
    }
1054

    
1055
    public static class DocumentWindowInfo implements Persistent {
1056

    
1057
        public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
1058

    
1059
        private WindowInfo windowInfo;
1060
        private String documentType;
1061
        private String documentName;
1062

    
1063
        public DocumentWindowInfo() {
1064
        }
1065

    
1066
        DocumentWindowInfo(WindowInfo wi, String docType, String docName) {
1067
            windowInfo = wi;
1068
            documentType = docType;
1069
            documentName = docName;
1070
        }
1071

    
1072
        public WindowInfo getWindowInfo() {
1073
            return windowInfo;
1074
        }
1075

    
1076
        public String getDocumentType() {
1077
            return documentType;
1078
        }
1079

    
1080
        public String getDocumentName() {
1081
            return documentName;
1082
        }
1083

    
1084
        public void saveToState(PersistentState state)
1085
                throws PersistenceException {
1086
            state.set("windowInfo", this.windowInfo);
1087
            state.set("documentType", this.documentType);
1088
            state.set("documentName", this.documentName);
1089
        }
1090

    
1091
        public void loadFromState(PersistentState state)
1092
                throws PersistenceException {
1093
            this.windowInfo = (WindowInfo) state.get("windowInfo");
1094
            this.documentType = state.getString("documentType");
1095
            this.documentName = state.getString("documentName");
1096
        }
1097

    
1098
        public static void registerPersistent() {
1099
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1100
            DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
1101
            if (definition == null) {
1102
                definition = manager.addDefinition(
1103
                        DocumentWindowInfo.class,
1104
                        PERSISTENCE_DEFINITION_NAME,
1105
                        "DocumentWindowInfo persistence definition",
1106
                        null,
1107
                        null
1108
                );
1109
                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
1110
                definition.addDynFieldString("documentType").setMandatory(true);
1111
                definition.addDynFieldString("documentName").setMandatory(true);
1112
            }
1113

    
1114
        }
1115
    }
1116

    
1117
    public static void registerPersistent() {
1118
        AbstractDocument.registerPersistent();
1119
        DocumentWindowInfo.registerPersistent();
1120
        ProjectExtent.registerPersistent();
1121

    
1122
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1123
        DynStruct definition = manager.addDefinition(DefaultProject.class,
1124
                "Project", "Project Persistence definition", null, null);
1125
        definition.addDynFieldString("version").setMandatory(true);
1126
        definition.addDynFieldString("comments").setMandatory(true);
1127
        definition.addDynFieldString("creationDate").setMandatory(true);
1128
        definition.addDynFieldString("modificationDate").setMandatory(true);
1129
        definition.addDynFieldString("name").setMandatory(true);
1130
        definition.addDynFieldString("owner").setMandatory(true);
1131

    
1132
        definition.addDynFieldObject("selectionColor")
1133
                .setClassOfValue(Color.class).setMandatory(true);
1134
        definition.addDynFieldObject("projection")
1135
                .setClassOfValue(IProjection.class).setMandatory(true);
1136

    
1137
        definition.addDynFieldList("extents")
1138
                .setClassOfItems(ProjectExtent.class).setMandatory(true);
1139

    
1140
        definition.addDynFieldList("documents").setClassOfItems(Document.class)
1141
                .setMandatory(true);
1142

    
1143
        definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
1144

    
1145
        definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
1146

    
1147

    
1148
        definition.addDynFieldObject("propertiesHelper").setClassOfValue(ExtendedPropertiesHelper.class)
1149
                        .setMandatory(false);
1150

    
1151
    }
1152

    
1153
    /**
1154
     * @deprecated use getPreferences().setDefaultSelectionColor()
1155
     */
1156
    public static void setDefaultSelectionColor(Color color) {
1157
        getPreferences().setDefaultSelectionColor(color);
1158
    }
1159

    
1160
    /**
1161
     * @deprecated use getPreferences().getDefaultSelectionColor()
1162
     */
1163
    public static Color getDefaultSelectionColor() {
1164
        return getPreferences().getDefaultSelectionColor();
1165
    }
1166

    
1167
    /**
1168
     * @deprecated use getPreferences().getDefaultMapUnits()
1169
     */
1170
    public static int getDefaultMapUnits() {
1171
        return getPreferences().getDefaultMapUnits();
1172
    }
1173

    
1174
    /**
1175
     * @deprecated use getPreferences().getDefaultDistanceUnits()
1176
     */
1177
    public static int getDefaultDistanceUnits() {
1178
        return getPreferences().getDefaultDistanceUnits();
1179
    }
1180

    
1181
    /**
1182
     * @deprecated use getPreferences().getDefaultDistanceArea()
1183
     */
1184
    public static int getDefaultDistanceArea() {
1185
        return getPreferences().getDefaultDistanceArea();
1186
    }
1187

    
1188
    /**
1189
     * @deprecated use getPreferences().setDefaultMapUnits()
1190
     */
1191
    public static void setDefaultMapUnits(int mapUnits) {
1192
        getPreferences().setDefaultMapUnits(mapUnits);
1193
    }
1194

    
1195
    /**
1196
     * @deprecated use getPreferences().setDefaultDistanceUnits()
1197
     */
1198
    public static void setDefaultDistanceUnits(int distanceUnits) {
1199
        getPreferences().setDefaultDistanceUnits(distanceUnits);
1200
    }
1201

    
1202
    /**
1203
     * @deprecated use getPreferences().setDefaultDistanceArea()
1204
     */
1205
    public static void setDefaultDistanceArea(int distanceArea) {
1206
        getPreferences().setDefaultDistanceArea(distanceArea);
1207
    }
1208

    
1209
    /**
1210
     * @deprecated use getPreferences().setDefaultProjection()
1211
     */
1212
    public static void setDefaultProjection(IProjection defaultProjection) {
1213
        getPreferences().setDefaultProjection(defaultProjection);
1214
    }
1215

    
1216
    /**
1217
     * @deprecated use getPreferences().getDefaultProjection()
1218
     */
1219
    public static IProjection getDefaultProjection() {
1220
        return getPreferences().getDefaultProjection();
1221
    }
1222

    
1223
    /**
1224
     * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
1225
     * 2.1.0
1226
     */
1227
    public void setColor(String color) {
1228
        this.setSelectionColor(StringUtilities.string2Color(color));
1229
    }
1230

    
1231
    /**
1232
     * Return the selection color
1233
     *
1234
     * @return selection color as string
1235
     * @deprecated use {@link #getSelectionColor()}
1236
     */
1237
    public String getColor() {
1238
        return StringUtilities.color2String(selectionColor);
1239
    }
1240

    
1241
    /**
1242
     * Return the list of views of the project
1243
     *
1244
     * @return views as ArrayList of ProjectDocument
1245
     *
1246
     * @deprecated see {@link #getDocumentsByType(String)}
1247
     */
1248
    public List<Document> getViews() {
1249
        return getDocuments(ViewManager.TYPENAME);
1250
    }
1251

    
1252
    /**
1253
     * Add a view to the project
1254
     *
1255
     * @deprecated see {@link #add(AbstractDocument)}
1256
     */
1257
    public void addView(DefaultViewDocument v) {
1258
        add(v);
1259
    }
1260

    
1261
    /**
1262
     * Remove a view of the project
1263
     *
1264
     * @param index of the view as integer
1265
     *
1266
     * @deprecated see {@link #remove(AbstractDocument)}
1267
     */
1268
    public void delView(int i) {
1269
        List<Document> list = getDocuments(ViewManager.TYPENAME);
1270
        remove(list.get(i));
1271
    }
1272

    
1273
    /**
1274
     * @deprecated see {@link #getDocument(String, String)}
1275
     */
1276
    public Document getProjectDocumentByName(String name, String type) {
1277
        return this.getDocument(name, type);
1278
    }
1279

    
1280
    /**
1281
     * @deprecated see {@link #getDocuments(String)}
1282
     */
1283
    public List<Document> getDocumentsByType(String type) {
1284
        return this.getDocuments(type);
1285
    }
1286

    
1287
    /**
1288
     * @deprecated aun por decidir que API darle al copy/paste
1289
     */
1290
    public String exportToXML(AbstractDocument[] selectedItems)
1291
            throws SaveException {
1292
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1293
        throw new UnsupportedOperationException("This method is not supported");
1294
    }
1295

    
1296
    /**
1297
     * @deprecated aun por decidir que API darle al copy/paste
1298
     */
1299
    public void importFromXML(String sourceString, String docType) {
1300
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1301
        throw new UnsupportedOperationException("This method is not supported");
1302
    }
1303

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

    
1312
    @Override
1313
    public boolean canImportDocuments(String data, String doctype) {
1314
        // TODO Auto-generated method stub
1315
        return false;
1316
    }
1317

    
1318
    @Override
1319
    public String exportDocumentsAsText(List<Document> documents) {
1320
        // TODO Auto-generated method stub
1321
        return null;
1322
    }
1323

    
1324
    @Override
1325
    public void importDocuments(String data, String doctype) {
1326
        // TODO Auto-generated method stub
1327

    
1328
    }
1329

    
1330
    @Override
1331
    public Document getActiveDocument() {
1332
        return this.getActiveDocument((Class<? extends Document>)null);
1333
    }
1334

    
1335
    @Override
1336
    public Document getActiveDocument(String documentTypeName) {
1337
        ApplicationManager application = ApplicationLocator.getManager();
1338

    
1339
        Document document = null;
1340
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1341
        IWindow window = null;
1342
        for (int i = 0; i < windows.length; i++) {
1343
            window = windows[i];
1344
            if (window instanceof SingletonWindow) {
1345
                // Cogemos no la primera ventana, si no la primera
1346
                // ventana de tipo documento (SingletonWindow).
1347
                // Y por si las mosca no es un documento, atrapamos
1348
                // los errores y continuamos si no puede hacer un cast
1349
                // del Model a Document
1350
                try {
1351
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1352
                    if (documentTypeName == null) {
1353
                        return document;
1354
                    }
1355
                    if( document.getTypeName().equalsIgnoreCase(documentTypeName) ) {
1356
                        return document;
1357
                    }
1358
                    if( document instanceof DocumentsContainer ) {
1359
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentTypeName);
1360
                        return subdoc;
1361
                    }
1362

    
1363
                } catch (ClassCastException e) {
1364
                    // Do nothing, skip this window
1365
                }
1366
            }
1367
        }
1368
        return null;
1369
    }
1370
    
1371
    @Override
1372
    public List<Document> getOpenDocuments(Class<? extends Document> documentClass) {
1373
        return this.getOpenDocuments((Document doc) -> {
1374
            return doc!=null && (documentClass==null || documentClass.isAssignableFrom(doc.getClass()));
1375
        });
1376
    }
1377
    
1378
    @Override
1379
    public List<Document> getOpenDocuments(String type) {
1380
        return this.getOpenDocuments((Document doc) -> {
1381
            return  doc!=null && StringUtils.equals(type, doc.getTypeName());
1382
        });
1383
    }
1384
    
1385
    @SuppressWarnings("UnnecessaryContinue")
1386
    @Override
1387
    public List<Document> getOpenDocuments(Predicate<Document>filter) {
1388
        ApplicationManager application = ApplicationLocator.getManager();
1389

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

    
1418
    @Override
1419
    public Document getActiveDocument(Class<? extends Document> documentClass) {
1420
        ApplicationManager application = ApplicationLocator.getManager();
1421

    
1422
        Document document = null;
1423
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1424
        IWindow window = null;
1425
        for (int i = 0; i < windows.length; i++) {
1426
            window = windows[i];
1427
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1428
                // Cogemos no la primera ventana, si no la primera
1429
                // ventana de tipo documento (SingletonWindow).
1430
                // Y por si las mosca no es un documento, atrapamos
1431
                // los errores y continuamos si no puede hacer un cast
1432
                // del Model a Document
1433
                try {
1434
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1435
                    if (documentClass == null) {
1436
                        return document;
1437
                    }
1438
                    if (documentClass.isAssignableFrom(document.getClass())) {
1439
                        return document;
1440
                    }
1441
                    if( document instanceof DocumentsContainer ) {
1442
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentClass);
1443
                        return subdoc;
1444
                    }
1445

    
1446
                } catch (ClassCastException e) {
1447
                    // Do nothing, skip this window
1448
                }
1449
            }
1450
        }
1451
        return null;
1452
    }
1453

    
1454
    @Override
1455
    public IWindow getActiveWindow(Class<? extends Document> documentClass) {
1456
        ApplicationManager application = ApplicationLocator.getManager();
1457

    
1458
        Document document;
1459
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1460
        for (IWindow window : windows) {
1461
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1462
                // Cogemos no la primera ventana, si no la primera
1463
                // ventana de tipo documento (SingletonWindow).
1464
                // Y por si las mosca no es un documento, atrapamos
1465
                // los errores y continuamos si no puede hacer un cast
1466
                // del Model a Document
1467
                try {
1468
                    if (documentClass == null) {
1469
                        return window;
1470
                    }
1471
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1472
                    if (documentClass.isAssignableFrom(document.getClass())) {
1473
                        return window;
1474
                    }
1475
                } catch (ClassCastException e) {
1476
                    // Do nothing, skip this window
1477
                }
1478
            }
1479
        }
1480
        return null;
1481
    }
1482

    
1483
    @Override
1484
    public void addObserver(Observer o) {
1485
        observableHelper.addObserver(o);
1486
    }
1487

    
1488
    @Override
1489
    public void deleteObserver(Observer o) {
1490
        observableHelper.deleteObserver(o);
1491
    }
1492

    
1493
    @Override
1494
    public void deleteObservers() {
1495
        observableHelper.deleteObservers();
1496
    }
1497

    
1498
    private ProjectNotification notifyObservers(int type) {
1499
        return notifyObservers(new DefaultProjectNotification(type));
1500
    }
1501

    
1502
    private ProjectNotification notifyObservers(int type, Document document) {
1503
        return notifyObservers(new DefaultProjectNotification(type, document));
1504
    }
1505
    
1506
    private ProjectNotification notifyObservers(int type, PersistentState state) {
1507
        return notifyObservers(new DefaultProjectNotification(type, state));
1508
    }
1509

    
1510
    private ProjectNotification notifyObservers(int type, File file) {
1511
        return notifyObservers(new DefaultProjectNotification(type, file));
1512
    }
1513

    
1514
    private ProjectNotification notifyObservers(ProjectNotification notifycation) {
1515
        try {
1516
            observableHelper.notifyObservers(this, notifycation);
1517
        } catch (Exception ex) {
1518
            LOG.info("Can't notify observers", ex);
1519
        }
1520
        notifyProjectManagerEvent(notifycation.getNotificationType());
1521
        return notifycation;
1522
    }
1523
    
1524
    private void notifyProjectManagerEvent(int type) {
1525
        try {
1526
            ProjectManager.getInstance().notifyProjectEvent(new ProjectEventImpl(this, type));
1527
        } catch (Exception ex) {
1528
            LOG.info("Can't notify project manager events", ex);
1529
        }
1530
    }
1531
    
1532
    class DefaultProjectNotification implements ProjectNotification {
1533

    
1534
        private int type;
1535
        private Document document;
1536
        private File file;
1537
        private boolean processCanceled = false;
1538
        private PersistentState state = null;
1539

    
1540
        DefaultProjectNotification(int type) {
1541
            this.type = type;
1542
        }
1543

    
1544
        DefaultProjectNotification(int type, Document document) {
1545
            this(type);
1546
            this.document = document;
1547
        }
1548

    
1549
        DefaultProjectNotification(int type, File file) {
1550
            this(type);
1551
            this.file = file;
1552
        }
1553

    
1554
        DefaultProjectNotification(int type, PersistentState state) {
1555
            this(type);
1556
            this.state = state;
1557
        }
1558

    
1559
        @Override
1560
        public int getNotificationType() {
1561
            return type;
1562
        }
1563

    
1564
        @Override
1565
        public Document getDocument() {
1566
            return document;
1567
        }
1568

    
1569
        @Override
1570
        public void cancelProcess() {
1571
            processCanceled = true;
1572
        }
1573

    
1574
        @Override
1575
        public boolean isProcessCanceled() {
1576
            return processCanceled;
1577
        }
1578

    
1579
        @Override
1580
        public File getFile() {
1581
            return file;
1582
        }
1583

    
1584
        @Override
1585
        public PersistentState getState() {
1586
            return this.state;
1587
        }
1588

    
1589
        @Override
1590
        public Project getProject() {
1591
            return DefaultProject.this;
1592
        }
1593
    }
1594

    
1595
}