Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / project / DefaultProject.java @ 43888

History | View | Annotate | Download (39.5 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.beans.PropertyChangeEvent;
27
import java.beans.PropertyChangeListener;
28
import java.beans.PropertyChangeSupport;
29
import java.io.File;
30
import java.io.FileInputStream;
31
import java.io.FileNotFoundException;
32
import java.io.FileOutputStream;
33
import java.io.IOException;
34
import java.io.InputStream;
35
import java.io.OutputStream;
36
import java.io.Serializable;
37
import java.text.DateFormat;
38
import java.text.MessageFormat;
39
import java.util.ArrayList;
40
import java.util.Collections;
41
import java.util.Date;
42
import java.util.HashMap;
43
import java.util.HashSet;
44
import java.util.Iterator;
45
import java.util.List;
46
import java.util.Map;
47
import java.util.Set;
48
import java.util.zip.ZipException;
49
import java.util.zip.ZipFile;
50

    
51
import org.cresques.cts.IProjection;
52

    
53
import org.gvsig.andami.PluginServices;
54
import org.gvsig.andami.ui.mdiManager.IWindow;
55
import org.gvsig.andami.ui.mdiManager.MDIManager;
56
import org.gvsig.andami.ui.mdiManager.SingletonWindow;
57
import org.gvsig.andami.ui.mdiManager.WindowInfo;
58
import org.gvsig.app.ApplicationLocator;
59
import org.gvsig.app.ApplicationManager;
60
import org.gvsig.app.extension.ProjectExtension;
61
import org.gvsig.app.extension.Version;
62
import org.gvsig.app.project.ProjectManager.NewProjectEvent;
63
import org.gvsig.app.project.ProjectManager.ProjectLoadedEvent;
64
import org.gvsig.app.project.documents.AbstractDocument;
65
import org.gvsig.app.project.documents.Document;
66
import org.gvsig.app.project.documents.exceptions.SaveException;
67
import org.gvsig.app.project.documents.gui.IDocumentWindow;
68
import org.gvsig.app.project.documents.gui.ProjectWindow;
69
import org.gvsig.app.project.documents.view.DefaultViewDocument;
70
import org.gvsig.app.project.documents.view.ViewManager;
71
import org.gvsig.fmap.mapcontext.MapContext;
72
import org.gvsig.fmap.mapcontext.layers.ExtendedPropertiesHelper;
73
import org.gvsig.fmap.mapcontext.layers.FLayer;
74
import org.gvsig.fmap.mapcontext.layers.FLayers;
75
import org.gvsig.tools.ToolsLocator;
76
import org.gvsig.tools.dynobject.DynStruct;
77
import org.gvsig.tools.observer.ObservableHelper;
78
import org.gvsig.tools.observer.Observer;
79
import org.gvsig.tools.persistence.PersistenceManager;
80
import org.gvsig.tools.persistence.Persistent;
81
import org.gvsig.tools.persistence.PersistentContext;
82
import org.gvsig.tools.persistence.PersistentState;
83
import org.gvsig.tools.persistence.exception.PersistenceException;
84
import org.gvsig.utils.StringUtilities;
85

    
86
import org.slf4j.Logger;
87
import org.slf4j.LoggerFactory;
88

    
89
/**
90
 * Clase que representa un proyecto de gvSIG
91
 *
92
 */
93
public class DefaultProject implements Serializable, PropertyChangeListener,
94
        Project {
95

    
96
    private Logger LOG = LoggerFactory.getLogger(DefaultProject.class);
97
    /**
98
     * @deprecated see ApplicationLocator.getManager().getVersion()
99
     */
100
    public static String VERSION = Version.format();
101

    
102
    private ExtendedPropertiesHelper propertiesHelper = new ExtendedPropertiesHelper();
103

    
104
    private ObservableHelper observableHelper = new ObservableHelper();
105

    
106
    /**
107
     *
108
     */
109
    private static final long serialVersionUID = -4449622027521773178L;
110

    
111
    private static final Logger logger = LoggerFactory.getLogger(Project.class);
112

    
113
    private static ProjectPreferences preferences = new ProjectPreferences();
114

    
115
    /**
116
     * Index used by the generator of unique names of documents.
117
     */
118
    private Map<String, Integer> nextDocumentIndexByType = new HashMap<String, Integer>();
119

    
120
    private PropertyChangeSupport change;
121

    
122
    private boolean modified = false;
123

    
124
    private String name = null;
125

    
126
    private String creationDate = null;
127

    
128
    private String modificationDate = null;
129

    
130
    private String owner = null;
131

    
132
    private String comments = null;
133

    
134
    private Color selectionColor = null;
135

    
136
    private List<Document> documents = null;
137

    
138
    private List<ProjectExtent> extents = null;
139

    
140
    private IProjection projection;
141

    
142
    private File fname = null;
143

    
144
    private Set<String> unloadedObjects;
145
    private PersistenceException loadErrors = null;
146

    
147
    /**
148
     * Creates a new Project object.
149
     */
150
    DefaultProject() {
151
        this.change = new PropertyChangeSupport(this);
152
        this.clean();
153
        ProjectManager.getInstance().notifyProjectEvent(new NewProjectEvent() {
154
            @Override
155
            public Project getProject() {
156
                return DefaultProject.this;
157
            }
158
        });
159
    }
160

    
161
    protected void clean() {
162
        this.owner = "";
163
        this.comments = "";
164
        this.name = PluginServices.getText(this, "untitled");
165
        this.creationDate = DateFormat.getDateInstance().format(new Date());
166
        this.modificationDate = this.creationDate;
167

    
168
        this.documents = new ArrayList<Document>();
169
        this.extents = new ArrayList<ProjectExtent>();
170

    
171
        this.setSelectionColor(getPreferences().getDefaultSelectionColor());
172

    
173
        this.projection = null; // se inicializa en el getProjection()
174
    }
175

    
176
    public static ProjectPreferences getPreferences() {
177
        return preferences;
178
    }
179

    
180
    public void propertyChange(PropertyChangeEvent evt) {
181
        change.firePropertyChange(evt);
182
    }
183

    
184
    public synchronized void addPropertyChangeListener(
185
            PropertyChangeListener arg0) {
186
        change.addPropertyChangeListener(arg0);
187
    }
188

    
189
    /**
190
     * Return the creation date of the project
191
     *
192
     * @return
193
     */
194
    public String getCreationDate() {
195
        return creationDate;
196
    }
197

    
198
    protected void setCreationDate(String creationDate) {
199
        this.creationDate = creationDate;
200
        change.firePropertyChange("setCreationDate", null, null);
201
    }
202

    
203
    public Document createDocument(String type) {
204
        logger.info("createDocument('{}')", type);
205
        return ProjectManager.getInstance().createDocument(type);
206
    }
207

    
208
    /**
209
     * Return the name of the project
210
     *
211
     * @return
212
     */
213
    public String getName() {
214
        return name;
215
    }
216

    
217
    /**
218
     * Set the name of he project.
219
     *
220
     * @param string
221
     */
222
    public void setName(String name) {
223
        this.name = name;
224
        change.firePropertyChange("setName", null, null);
225
    }
226

    
227
    /**
228
     * Return the comments associateds with the project
229
     *
230
     * @return comments
231
     */
232
    public String getComments() {
233
        return comments;
234
    }
235

    
236
    /**
237
     * Set the comments associateds with the project
238
     *
239
     * @param comments as string
240
     */
241
    public void setComments(String string) {
242
        comments = string;
243
        change.firePropertyChange("setComments", null, null);
244
    }
245

    
246
    /**
247
     * Retuen the modification date of the project.
248
     *
249
     * @return modification date as string
250
     */
251
    public String getModificationDate() {
252
        return modificationDate;
253
    }
254

    
255
    protected void setModificationDate(String string) {
256
        modificationDate = string;
257
        change.firePropertyChange("setModificationDate", null, null);
258
    }
259

    
260
    /**
261
     * Return the author of the project,
262
     *
263
     * @return author as string
264
     */
265
    public String getOwner() {
266
        return owner;
267
    }
268

    
269
    /**
270
     * Sets the author of the project
271
     *
272
     * @param author name as string
273
     */
274
    public void setOwner(String owner) {
275
        this.owner = owner;
276
        change.firePropertyChange("setOwner", null, null);
277
    }
278

    
279
    /**
280
     * Obtiene el color de selecci�n que se usar� en el proyecto
281
     *
282
     * @return
283
     */
284
    public Color getSelectionColor() {
285
        if (selectionColor == null) {
286
            selectionColor = getPreferences().getDefaultSelectionColor();
287
        }
288
        return selectionColor;
289
    }
290

    
291
    /**
292
     * Sets the selecction color
293
     *
294
     * @param selection color as string
295
     */
296
    public void setSelectionColor(String selectionColor) {
297
        this.setSelectionColor(StringUtilities.string2Color(selectionColor));
298
    }
299

    
300
    /**
301
     * Sets the selecction color
302
     *
303
     * @param selection color as Color
304
     */
305
    public void setSelectionColor(Color selectionColor) {
306
        this.selectionColor = selectionColor;
307
        MapContext.setSelectionColor(selectionColor);
308
        change.firePropertyChange("selectionColor", null, selectionColor);
309
    }
310

    
311
    public IProjection getProjection() {
312
        if (projection == null) {
313
            projection = getPreferences().getDefaultProjection();
314
        }
315
        return projection;
316
    }
317

    
318
    public void setProjection(IProjection projection) {
319
        this.projection = projection;
320
    }
321

    
322
    /**
323
     * Sets the modified state of project.
324
     *
325
     * Can't set to not modified.
326
     *
327
     * @param modified as boolean
328
     */
329
    public void setModified(boolean modified) {
330
        this.modified = modified;
331
        if (modified == false) {
332
            List<Document> documents = this.getDocuments();
333
            for (int i = 0; i < documents.size(); i++) {
334
                documents.get(i).setModified(false);
335
            }
336
        }
337
    }
338

    
339
    public boolean hasChanged() {
340
                // we return true if the project is not empty (until we have a better
341
        // method...)
342
        if ((this.getDocuments().size() != 0) || modified) {
343
            return true;
344
        }
345
        return false;
346
    }
347

    
348
    /**
349
     * Return a list of documents in the project.
350
     *
351
     * @return documents as List of IProjectDocument
352
     */
353
    public List<Document> getDocuments() {
354
        return Collections.unmodifiableList(documents);
355
    }
356

    
357
    /**
358
     * Return a list with all documents of especified type.
359
     *
360
     * @param type of document
361
     *
362
     * @return List of IProjectDocument
363
     */
364
    public List<Document> getDocuments(String type) {
365
        List<Document> docs = new ArrayList<Document>();
366
        if (type != null) {
367
            for (Document document : this.documents) {
368
                if (type.equalsIgnoreCase(document.getTypeName())) {
369
                    docs.add(document);
370
                }
371
            }
372
        }
373
        return Collections.unmodifiableList(docs);
374
    }
375

    
376
    /**
377
     * Adds a document to the project
378
     *
379
     * @param document as Document
380
     */
381
    public void add(Document document) {
382
        this.addDocument(document);
383
    }
384

    
385
    public void addDocument(Document document) {
386
        logger.info("add('{}')", document.toString());
387

    
388
        if (notifyObservers(ProjectNotification.BEFORE_ADD_DOCUMENT, document).isProcessCanceled()) {
389
            return;
390
        }
391
        document.addPropertyChangeListener(this);
392
        document.setProject(this);
393
        document.setName(this.getUniqueNameForDocument(document.getTypeName(),
394
                document.getName()));
395
        documents.add(document);
396
        document.afterAdd();
397
        this.setModified(true);
398
        notifyObservers(ProjectNotification.AFTER_ADD_DOCUMENT, document);
399
        change.firePropertyChange("addDocument", null, document);
400
    }
401

    
402
    public void remove(Document doc) {
403
        this.removeDocument(doc);
404
    }
405

    
406
    public void removeDocument(Document doc) {
407
        logger.info("remove('{}')", doc.toString());
408
        if (notifyObservers(ProjectNotification.BEFORE_REMOVE_DOCUMENT, doc).isProcessCanceled()) {
409
            return;
410
        }
411
        documents.remove(doc);
412
        this.setModified(true);
413
        change.firePropertyChange("delDocument", doc, null);
414
        doc.afterRemove();
415
        notifyObservers(ProjectNotification.AFTER_REMOVE_DOCUMENT, doc);
416
    }
417

    
418
    public Iterator<Document> iterator() {
419
        return documents.iterator();
420
    }
421

    
422
    public boolean isEmpty() {
423
        return documents.isEmpty();
424
    }
425

    
426
    /**
427
     * Return the view that contains the especified layer.
428
     *
429
     * @param layer
430
     *
431
     * @return name of the view that contains the layer
432
     *
433
     * @throws RuntimeException Si la capa que se pasa como par�metro no se
434
     * encuentra en ninguna vista
435
     */
436
    public String getViewName(FLayer layer) {
437
        List<Document> views = getDocuments(ViewManager.TYPENAME);
438
        for (int v = 0; v < views.size(); v++) {
439
            DefaultViewDocument pView = (DefaultViewDocument) views.get(v);
440
            FLayers layers = pView.getMapContext().getLayers();
441
            if (isView(layers, layer)) {
442
                return pView.getName();
443
            }
444
        }
445

    
446
        throw new RuntimeException(MessageFormat.format(
447
                "The layer '{1}' is not in a view", layer.getName()));
448
    }
449

    
450
    private boolean isView(FLayers layers, FLayer layer) {
451
        for (int i = 0; i < layers.getLayersCount(); i++) {
452
            if (layers.getLayer(i) instanceof FLayers) {
453
                if (isView((FLayers) layers.getLayer(i), layer)) {
454
                    return true;
455
                }
456
            }
457
            if (layers.getLayer(i) == layer) {
458
                return true;
459
            }
460
        }
461
        return false;
462
    }
463

    
464
    public void addExtent(ProjectExtent arg1) {
465
        extents.add(arg1);
466
        change.firePropertyChange("addExtent", null, null);
467
    }
468

    
469
    public ProjectExtent removeExtent(int arg0) {
470
        change.firePropertyChange("delExtent", null, null);
471
        return extents.remove(arg0);
472
    }
473

    
474
    public ProjectExtent[] getExtents() {
475
        return (ProjectExtent[]) extents.toArray(new ProjectExtent[0]);
476
    }
477

    
478
    /**
479
     * Obtiene un documento a partir de su nombre y el nombre de registro en el
480
     * pointExtension, este �ltimo se puede obtener del
481
     * Project****Factory.registerName.
482
     *
483
     * @param name Nombre del documento
484
     * @param type nombre de registro en el extensionPoint
485
     *
486
     * @return Documento
487
     */
488
    public Document getDocument(String name, String type) {
489
        if (type == null) {
490
            for (int i = 0; i < documents.size(); i++) {
491
                Document document = documents.get(i);
492
                if ( name.equalsIgnoreCase(document.getName())) {
493
                    return document;
494
                }
495
            }
496
        } else {
497
            for (int i = 0; i < documents.size(); i++) {
498
                Document document = documents.get(i);
499
                if (type.equalsIgnoreCase(document.getTypeName())
500
                        && name.equalsIgnoreCase(document.getName())) {
501
                    return document;
502
                }
503
            }
504
        }
505
        return null;
506
    }
507

    
508
    public Document getDocument(String name) {
509
        return this.getDocument(name, null);
510
    }
511

    
512
    public String getUniqueNameForDocument(String type, String name) {
513
        Document document = getDocument(name, type);
514
        if (document == null) {
515
            return name;
516
        }
517

    
518
        String newName = null;
519
        int num = this.getNextDocumentIndex(type);
520
        while (document != null) {
521
            newName = name + " - " + num++;
522
            document = getDocument(newName, type);
523
        }
524
        this.setNextDocumentIndex(type, num);
525
        return newName;
526
    }
527

    
528
    private int getNextDocumentIndex(String type) {
529
        if (nextDocumentIndexByType.get(type) == null) {
530
            nextDocumentIndexByType.put(type, new Integer(1));
531
            return 1;
532
        }
533
        return nextDocumentIndexByType.get(type).intValue();
534
    }
535

    
536
    private void setNextDocumentIndex(String type, int newIndex) {
537
        if (nextDocumentIndexByType.get(type) == null) {
538
            nextDocumentIndexByType.put(type, new Integer(newIndex));
539
        } else {
540
            nextDocumentIndexByType.put(type, new Integer(newIndex));
541
        }
542
    }
543

    
544
    public void saveState(File out) throws PersistenceException {
545
        FileOutputStream fout;
546
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_FILE, out).isProcessCanceled()) {
547
            return;
548
        }
549
        try {
550
            fout = new FileOutputStream(out);
551
            saveState(fout, new File(out.getParent()));
552
        } catch (FileNotFoundException e) {
553
            throw new PersistenceException(e);
554
        }
555
        if( !isValidZIP(out) ) {
556
            throw new PersistenceException(new ZipException());
557
        }
558
        this.fname = out;
559
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_FILE, out);
560
    }
561

    
562
    boolean isValidZIP(final File file) {
563
        ZipFile zipfile = null;
564
        try {
565
            zipfile = new ZipFile(file);
566
            return true;
567
        } catch (IOException e) {
568
            return false;
569
        } finally {
570
            try {
571
                if (zipfile != null) {
572
                    zipfile.close();
573
                    zipfile = null;
574
                }
575
            } catch (IOException e) {
576
            }
577
        }
578
    }
579
   
580
    public File getFile() {
581
        return this.fname;
582
    }
583

    
584
    public void saveState(OutputStream out) throws PersistenceException {
585
        saveState(out, null);
586
    }
587

    
588
    public void saveState(OutputStream out, File rootFolder)
589
            throws PersistenceException {
590
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_STREAM).isProcessCanceled()) {
591
            return;
592
        }
593
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
594
        PersistentState state = null;
595
        state = manager.getState(this, true);
596
        try {
597
            if (rootFolder != null) {
598
                state.relativizeFiles(rootFolder);
599
            }
600
        } catch (Exception ex) {
601
            state.getContext().addError(ex);
602
        }
603
        manager.saveState(state, out, true);
604
        if (state.getContext().getErrors() != null) {
605
            throw state.getContext().getErrors();
606
        }
607
        this.fname = null;
608
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_STREAM);
609
    }
610

    
611
    public void loadState(InputStream in) {
612
        loadState(in, null);
613
    }
614

    
615
    public void loadState(InputStream in, File rootFolder) {
616
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STREAM).isProcessCanceled()) {
617
            return;
618
        }
619
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
620
        try {
621
            PersistentContext context = manager.getNewContext();
622
            context.setCollectErrors(true);
623
            PersistentState state = manager.loadState(in, context);
624
            try {
625
                if (rootFolder != null) {
626
                    state.derelativizeFiles(rootFolder);
627
                }
628
            } catch (Exception ex) {
629
                state.getContext().addError(ex);
630
            }
631
            this.loadFromState(state);
632
            this.unloadedObjects = getUnloadedObjects(state.getContext());
633
            this.loadErrors = state.getContext().getErrors();
634
            ProjectManager.getInstance().notifyProjectEvent(new ProjectLoadedEvent() {
635
                @Override
636
                public Project getProject() {
637
                    return DefaultProject.this;
638
                }
639
            });
640

    
641
        } catch (PersistenceException e) {
642
            LOG.info("Can't load project to stream", e);
643
        }
644
        this.fname = null;
645
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STREAM);
646

    
647
    }
648

    
649

    
650

    
651
    /**
652
     * @param context
653
     * @return
654
     */
655
    private Set<String> getUnloadedObjects(PersistentContext context) {
656
        Set unloadedObjects = new HashSet();
657

    
658
        Iterator statesIterator = context.iterator();
659
        String className = null;
660

    
661
        while (statesIterator.hasNext()) {
662
            PersistentState aState = (PersistentState) statesIterator.next();
663
            try {
664
                className = aState.getTheClassName();
665
                DynStruct definition = aState.getDefinition();
666
                if (definition == null) {
667
                    unloadedObjects.add(className);
668
                }
669
            } catch (Throwable e) {
670
                // do nothing
671
            }
672
        }
673

    
674
        if(unloadedObjects.isEmpty()){
675
            return null;
676
        }
677

    
678
        return unloadedObjects;
679
    }
680

    
681
    @Override
682
    public Set<String> getUnloadedObjects() {
683
        return this.unloadedObjects;
684
    }
685

    
686
    @Override
687
    public List<Exception> getLoadErrors() {
688
        return this.loadErrors;
689
    }
690
    
691
    @Override
692
    public void loadState(File in) {
693
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_FILE, in).isProcessCanceled()) {
694
            return;
695
        }
696
        FileInputStream fin;
697
        try {
698
            fin = new FileInputStream(in);
699
            loadState(fin, new File(in.getParent()));
700
        } catch (FileNotFoundException e) {
701
            LOG.info("Can't load project to stream", e);
702
        }
703
        this.fname = in;
704
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_FILE, in);
705
    }
706

    
707
    @SuppressWarnings("unchecked")
708
    public void loadFromState(PersistentState state)
709
            throws PersistenceException {
710
        this.clean();
711

    
712
        this.setComments(state.getString("comments"));
713
        this.setCreationDate(state.getString("creationDate"));
714
        this.setModificationDate(state.getString("modificationDate"));
715
        this.setName(state.getString("name"));
716
        this.setOwner(state.getString("owner"));
717
        this.setSelectionColor((Color) state.get("selectionColor"));
718
        this.setProjection((IProjection) state.get("projection"));
719

    
720
        this.propertiesHelper = (ExtendedPropertiesHelper) state.get("propertiesHelper");
721

    
722
        List<ProjectExtent> extents = (List<ProjectExtent>) state
723
                .get("extents");
724
        for (int i = 0; i < extents.size(); i++) {
725
            this.addExtent(extents.get(i));
726
        }
727

    
728
        List<AbstractDocument> documents = (List<AbstractDocument>) state
729
                .get("documents");
730
        for (int i = 0; i < documents.size(); i++) {
731
            this.add(documents.get(i));
732
        }
733

    
734
        List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
735

    
736
        for (int i = 0; i < persistentWindows.size(); i++) {
737
            DocumentWindowInfo persistentWindow = persistentWindows.get(i);
738
            String docName = persistentWindow.getDocumentName();
739
            String docType = persistentWindow.getDocumentType();
740
            Document doc = this.getDocument(docName, docType);
741
            IWindow win = doc.getFactory().getMainWindow(doc);
742
            if(win!=null){
743
                win.getWindowInfo().setWindowInfo(persistentWindow.getWindowInfo());
744
                PluginServices.getMDIManager().addWindow(win);
745
            }
746
        }
747

    
748
        if (state.hasValue("projectWindowInfo")) {
749
            WindowInfo projectWindowInfo = (WindowInfo) state.get("projectWindowInfo");
750
            ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(org.gvsig.app.extension.ProjectExtension.class);
751
            pe.setProject(this);
752
            pe.showProjectWindow(projectWindowInfo);
753
        }
754

    
755
    }
756

    
757
    public void saveToState(PersistentState state) throws PersistenceException {
758
        state.set("version", VERSION);
759
        state.set("comments", getComments());
760
        state.set("creationDate", this.getCreationDate());
761

    
762
        state.set("modificationDate", this.getModificationDate());
763
        state.set("name", this.getName());
764
        state.set("owner", this.getOwner());
765
        state.set("selectionColor", this.getSelectionColor());
766

    
767
        state.set("projection", this.getProjection());
768

    
769
        state.set("extents", this.extents);
770
        List<Document> docs = this.getDocuments();
771
        List<Document> noTempDocs = new ArrayList<Document>();
772
        for (Iterator iterator = docs.iterator(); iterator.hasNext();) {
773
            Document document = (Document) iterator.next();
774
            if(!document.isTemporary()){
775
                noTempDocs.add(document);
776
            }
777
        }
778
        state.set("documents", noTempDocs);
779

    
780
        state.set("propertiesHelper",propertiesHelper);
781

    
782
        List<DocumentWindowInfo> persistentWindows = new ArrayList<DocumentWindowInfo>();
783
        MDIManager mdiMan = PluginServices.getMDIManager();
784
        IWindow[] windows = mdiMan.getOrderedWindows();
785
        for (int i = windows.length - 1; i >= 0; i--) {
786
            IWindow window = windows[i];
787
            if (window instanceof IDocumentWindow) {
788
                WindowInfo wi = mdiMan.getWindowInfo(window);
789
                DocumentWindowInfo dwi = new DocumentWindowInfo(
790
                        wi,
791
                        ((IDocumentWindow) window).getDocument().getTypeName(),
792
                        ((IDocumentWindow) window).getDocument().getName());
793
                persistentWindows.add(dwi);
794
            } else if (window instanceof ProjectWindow) {
795
                state.set("projectWindowInfo", mdiMan.getWindowInfo(window));
796
            }
797
        }
798
        state.set("documentWindowsInformation", persistentWindows);
799

    
800
    }
801

    
802
    public Object getProperty(Object key) {
803
        return this.propertiesHelper.getProperty(key);
804
    }
805

    
806
    public void setProperty(Object key, Object obj) {
807
        this.propertiesHelper.setProperty(key, obj);
808
    }
809

    
810
    public Map getExtendedProperties() {
811
        return this.propertiesHelper.getExtendedProperties();
812
    }
813

    
814
    public static class DocumentWindowInfo implements Persistent {
815

    
816
        public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
817

    
818
        private WindowInfo windowInfo;
819
        private String documentType;
820
        private String documentName;
821

    
822
        public DocumentWindowInfo() {
823
        }
824

    
825
        DocumentWindowInfo(WindowInfo wi, String docType, String docName) {
826
            windowInfo = wi;
827
            documentType = docType;
828
            documentName = docName;
829
        }
830

    
831
        public WindowInfo getWindowInfo() {
832
            return windowInfo;
833
        }
834

    
835
        public String getDocumentType() {
836
            return documentType;
837
        }
838

    
839
        public String getDocumentName() {
840
            return documentName;
841
        }
842

    
843
        public void saveToState(PersistentState state)
844
                throws PersistenceException {
845
            state.set("windowInfo", this.windowInfo);
846
            state.set("documentType", this.documentType);
847
            state.set("documentName", this.documentName);
848
        }
849

    
850
        public void loadFromState(PersistentState state)
851
                throws PersistenceException {
852
            this.windowInfo = (WindowInfo) state.get("windowInfo");
853
            this.documentType = state.getString("documentType");
854
            this.documentName = state.getString("documentName");
855
        }
856

    
857
        public static void registerPersistent() {
858
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
859
            DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
860
            if (definition == null) {
861
                definition = manager.addDefinition(
862
                        DocumentWindowInfo.class,
863
                        PERSISTENCE_DEFINITION_NAME,
864
                        "DocumentWindowInfo persistence definition",
865
                        null,
866
                        null
867
                );
868
                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
869
                definition.addDynFieldString("documentType").setMandatory(true);
870
                definition.addDynFieldString("documentName").setMandatory(true);
871
            }
872

    
873
        }
874
    }
875

    
876
    public static void registerPersistent() {
877
        AbstractDocument.registerPersistent();
878
        DocumentWindowInfo.registerPersistent();
879
        ProjectExtent.registerPersistent();
880

    
881
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
882
        DynStruct definition = manager.addDefinition(DefaultProject.class,
883
                "Project", "Project Persistence definition", null, null);
884
        definition.addDynFieldString("version").setMandatory(true);
885
        definition.addDynFieldString("comments").setMandatory(true);
886
        definition.addDynFieldString("creationDate").setMandatory(true);
887
        definition.addDynFieldString("modificationDate").setMandatory(true);
888
        definition.addDynFieldString("name").setMandatory(true);
889
        definition.addDynFieldString("owner").setMandatory(true);
890

    
891
        definition.addDynFieldObject("selectionColor")
892
                .setClassOfValue(Color.class).setMandatory(true);
893
        definition.addDynFieldObject("projection")
894
                .setClassOfValue(IProjection.class).setMandatory(true);
895

    
896
        definition.addDynFieldList("extents")
897
                .setClassOfItems(ProjectExtent.class).setMandatory(true);
898

    
899
        definition.addDynFieldList("documents").setClassOfItems(Document.class)
900
                .setMandatory(true);
901

    
902
        definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
903

    
904
        definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
905

    
906

    
907
        definition.addDynFieldObject("propertiesHelper").setClassOfValue(ExtendedPropertiesHelper.class)
908
                        .setMandatory(false);
909

    
910
    }
911

    
912
    /**
913
     * @deprecated use getPreferences().setDefaultSelectionColor()
914
     */
915
    public static void setDefaultSelectionColor(Color color) {
916
        getPreferences().setDefaultSelectionColor(color);
917
    }
918

    
919
    /**
920
     * @deprecated use getPreferences().getDefaultSelectionColor()
921
     */
922
    public static Color getDefaultSelectionColor() {
923
        return getPreferences().getDefaultSelectionColor();
924
    }
925

    
926
    /**
927
     * @deprecated use getPreferences().getDefaultMapUnits()
928
     */
929
    public static int getDefaultMapUnits() {
930
        return getPreferences().getDefaultMapUnits();
931
    }
932

    
933
    /**
934
     * @deprecated use getPreferences().getDefaultDistanceUnits()
935
     */
936
    public static int getDefaultDistanceUnits() {
937
        return getPreferences().getDefaultDistanceUnits();
938
    }
939

    
940
    /**
941
     * @deprecated use getPreferences().getDefaultDistanceArea()
942
     */
943
    public static int getDefaultDistanceArea() {
944
        return getPreferences().getDefaultDistanceArea();
945
    }
946

    
947
    /**
948
     * @deprecated use getPreferences().setDefaultMapUnits()
949
     */
950
    public static void setDefaultMapUnits(int mapUnits) {
951
        getPreferences().setDefaultMapUnits(mapUnits);
952
    }
953

    
954
    /**
955
     * @deprecated use getPreferences().setDefaultDistanceUnits()
956
     */
957
    public static void setDefaultDistanceUnits(int distanceUnits) {
958
        getPreferences().setDefaultDistanceUnits(distanceUnits);
959
    }
960

    
961
    /**
962
     * @deprecated use getPreferences().setDefaultDistanceArea()
963
     */
964
    public static void setDefaultDistanceArea(int distanceArea) {
965
        getPreferences().setDefaultDistanceArea(distanceArea);
966
    }
967

    
968
    /**
969
     * @deprecated use getPreferences().setDefaultProjection()
970
     */
971
    public static void setDefaultProjection(IProjection defaultProjection) {
972
        getPreferences().setDefaultProjection(defaultProjection);
973
    }
974

    
975
    /**
976
     * @deprecated use getPreferences().getDefaultProjection()
977
     */
978
    public static IProjection getDefaultProjection() {
979
        return getPreferences().getDefaultProjection();
980
    }
981

    
982
    /**
983
     * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
984
     * 2.1.0
985
     */
986
    public void setColor(String color) {
987
        this.setSelectionColor(StringUtilities.string2Color(color));
988
    }
989

    
990
    /**
991
     * Return the selection color
992
     *
993
     * @return selection color as string
994
     * @deprecated use {@link #getSelectionColor()}
995
     */
996
    public String getColor() {
997
        return StringUtilities.color2String(selectionColor);
998
    }
999

    
1000
    /**
1001
     * Return the list of views of the project
1002
     *
1003
     * @return views as ArrayList of ProjectDocument
1004
     *
1005
     * @deprecated see {@link #getDocumentsByType(String)}
1006
     */
1007
    public List<Document> getViews() {
1008
        return getDocuments(ViewManager.TYPENAME);
1009
    }
1010

    
1011
    /**
1012
     * Add a view to the project
1013
     *
1014
     * @deprecated see {@link #add(AbstractDocument)}
1015
     */
1016
    public void addView(DefaultViewDocument v) {
1017
        add(v);
1018
    }
1019

    
1020
    /**
1021
     * Remove a view of the project
1022
     *
1023
     * @param index of the view as integer
1024
     *
1025
     * @deprecated see {@link #remove(AbstractDocument)}
1026
     */
1027
    public void delView(int i) {
1028
        List<Document> list = getDocuments(ViewManager.TYPENAME);
1029
        remove(list.get(i));
1030
    }
1031

    
1032
    /**
1033
     * @deprecated see {@link #getDocument(String, String)}
1034
     */
1035
    public Document getProjectDocumentByName(String name, String type) {
1036
        return this.getDocument(name, type);
1037
    }
1038

    
1039
    /**
1040
     * @deprecated see {@link #getDocuments(String)}
1041
     */
1042
    public List<Document> getDocumentsByType(String type) {
1043
        return this.getDocuments(type);
1044
    }
1045

    
1046
    /**
1047
     * @deprecated aun por decidir que API darle al copy/paste
1048
     */
1049
    public String exportToXML(AbstractDocument[] selectedItems)
1050
            throws SaveException {
1051
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1052
        throw new UnsupportedOperationException("This method is not supported");
1053
    }
1054

    
1055
    /**
1056
     * @deprecated aun por decidir que API darle al copy/paste
1057
     */
1058
    public void importFromXML(String sourceString, String docType) {
1059
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1060
        throw new UnsupportedOperationException("This method is not supported");
1061
    }
1062

    
1063
    /**
1064
     * @deprecated aun por decidir que API darle al copy/paste
1065
     */
1066
    public boolean isValidXMLForImport(String sourceString, String docType) {
1067
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1068
        throw new UnsupportedOperationException("This method is not supported");
1069
    }
1070

    
1071
    public boolean canImportDocuments(String data, String doctype) {
1072
        // TODO Auto-generated method stub
1073
        return false;
1074
    }
1075

    
1076
    public String exportDocumentsAsText(List<Document> documents) {
1077
        // TODO Auto-generated method stub
1078
        return null;
1079
    }
1080

    
1081
    public void importDocuments(String data, String doctype) {
1082
        // TODO Auto-generated method stub
1083

    
1084
    }
1085

    
1086
    public Document getActiveDocument() {
1087
        return this.getActiveDocument((Class<? extends Document>)null);
1088
    }
1089

    
1090
    public Document getActiveDocument(String documentTypeName) {
1091
        ApplicationManager application = ApplicationLocator.getManager();
1092

    
1093
        Document document = null;
1094
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1095
        IWindow window = null;
1096
        for (int i = 0; i < windows.length; i++) {
1097
            window = windows[i];
1098
            if (window instanceof SingletonWindow) {
1099
                // Cogemos no la primera ventana, si no la primera
1100
                // ventana de tipo documento (SingletonWindow).
1101
                // Y por si las mosca no es un documento, atrapamos
1102
                // los errores y continuamos si no puede hacer un cast
1103
                // del Model a Document
1104
                try {
1105
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1106
                    if (documentTypeName == null) {
1107
                        return document;
1108
                    }
1109
                    if( document.getTypeName().equalsIgnoreCase(documentTypeName) ) {
1110
                        return document;
1111
                    }
1112
                    if( document instanceof DocumentsContainer ) {
1113
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentTypeName);
1114
                        return subdoc;
1115
                    }
1116

    
1117
                } catch (ClassCastException e) {
1118
                    // Do nothing, skip this window
1119
                }
1120
            }
1121
        }
1122
        return null;
1123
    }
1124

    
1125
    public Document getActiveDocument(Class<? extends Document> documentClass) {
1126
        ApplicationManager application = ApplicationLocator.getManager();
1127

    
1128
        Document document = null;
1129
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1130
        IWindow window = null;
1131
        for (int i = 0; i < windows.length; i++) {
1132
            window = windows[i];
1133
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1134
                // Cogemos no la primera ventana, si no la primera
1135
                // ventana de tipo documento (SingletonWindow).
1136
                // Y por si las mosca no es un documento, atrapamos
1137
                // los errores y continuamos si no puede hacer un cast
1138
                // del Model a Document
1139
                try {
1140
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1141
                    if (documentClass == null) {
1142
                        return document;
1143
                    }
1144
                    if (documentClass.isAssignableFrom(document.getClass())) {
1145
                        return document;
1146
                    }
1147
                    if( document instanceof DocumentsContainer ) {
1148
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentClass);
1149
                        return subdoc;
1150
                    }
1151

    
1152
                } catch (ClassCastException e) {
1153
                    // Do nothing, skip this window
1154
                }
1155
            }
1156
        }
1157
        return null;
1158
    }
1159

    
1160
    public void addObserver(Observer o) {
1161
        observableHelper.addObserver(o);
1162
    }
1163

    
1164
    public void deleteObserver(Observer o) {
1165
        observableHelper.deleteObserver(o);
1166
    }
1167

    
1168
    public void deleteObservers() {
1169
        observableHelper.deleteObservers();
1170
    }
1171

    
1172
//        private void notifyObservers(ProjectNotifycation notifycation) {
1173
//                observableHelper.notifyObservers(this, notifycation);
1174
//        }
1175
    private ProjectNotification notifyObservers(int type) {
1176
        DefaultProjectNotification notifycation
1177
                = new DefaultProjectNotification(type, null, null);
1178
        try {
1179
            observableHelper.notifyObservers(this, notifycation);
1180
        } catch (Exception ex) {
1181
            LOG.info("Can't notify observers", ex);
1182
        }
1183
        return notifycation;
1184
    }
1185

    
1186
    private ProjectNotification notifyObservers(int type, Document document) {
1187
        DefaultProjectNotification notifycation
1188
                = new DefaultProjectNotification(type, document, null);
1189
        try {
1190
            observableHelper.notifyObservers(this, notifycation);
1191
        } catch (Exception ex) {
1192
            LOG.info("Can't notify observers", ex);
1193
        }
1194
        return notifycation;
1195
    }
1196

    
1197
    private ProjectNotification notifyObservers(int type, File file) {
1198
        DefaultProjectNotification notifycation
1199
                = new DefaultProjectNotification(type, null, file);
1200
        try {
1201
            observableHelper.notifyObservers(this, notifycation);
1202
        } catch (Exception ex) {
1203
            LOG.info("Can't notify observers", ex);
1204
        }
1205
        return notifycation;
1206
    }
1207

    
1208
    class DefaultProjectNotification implements ProjectNotification {
1209

    
1210
        private int type;
1211
        private Document document;
1212
        private File file;
1213
        private boolean processCanceled = false;
1214

    
1215
        DefaultProjectNotification(int type, Document document, File file) {
1216
            this.type = type;
1217
            this.document = document;
1218
            this.file = file;
1219
        }
1220

    
1221
        public int getNotificationType() {
1222
            return type;
1223
        }
1224

    
1225
        public Document getDocument() {
1226
            return document;
1227
        }
1228

    
1229
        public void cancelProcess() {
1230
            processCanceled = true;
1231
        }
1232

    
1233
        public boolean isProcessCanceled() {
1234
            return processCanceled;
1235
        }
1236

    
1237
        public File getFile() {
1238
            return file;
1239
        }
1240

    
1241
    }
1242

    
1243
}