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

History | View | Annotate | Download (38.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.app.project;
24

    
25
import java.awt.Color;
26
import java.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.documents.AbstractDocument;
63
import org.gvsig.app.project.documents.Document;
64
import org.gvsig.app.project.documents.exceptions.SaveException;
65
import org.gvsig.app.project.documents.gui.IDocumentWindow;
66
import org.gvsig.app.project.documents.gui.ProjectWindow;
67
import org.gvsig.app.project.documents.view.DefaultViewDocument;
68
import org.gvsig.app.project.documents.view.ViewManager;
69
import org.gvsig.fmap.mapcontext.MapContext;
70
import org.gvsig.fmap.mapcontext.layers.ExtendedPropertiesHelper;
71
import org.gvsig.fmap.mapcontext.layers.FLayer;
72
import org.gvsig.fmap.mapcontext.layers.FLayers;
73
import org.gvsig.tools.ToolsLocator;
74
import org.gvsig.tools.dynobject.DynStruct;
75
import org.gvsig.tools.observer.ObservableHelper;
76
import org.gvsig.tools.observer.Observer;
77
import org.gvsig.tools.persistence.PersistenceManager;
78
import org.gvsig.tools.persistence.Persistent;
79
import org.gvsig.tools.persistence.PersistentContext;
80
import org.gvsig.tools.persistence.PersistentState;
81
import org.gvsig.tools.persistence.exception.PersistenceException;
82
import org.gvsig.utils.StringUtilities;
83

    
84
import org.slf4j.Logger;
85
import org.slf4j.LoggerFactory;
86

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

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

    
100
    private ExtendedPropertiesHelper propertiesHelper = new ExtendedPropertiesHelper();
101

    
102
    private ObservableHelper observableHelper = new ObservableHelper();
103

    
104
    /**
105
     *
106
     */
107
    private static final long serialVersionUID = -4449622027521773178L;
108

    
109
    private static final Logger logger = LoggerFactory.getLogger(Project.class);
110

    
111
    private static ProjectPreferences preferences = new ProjectPreferences();
112

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

    
118
    private PropertyChangeSupport change;
119

    
120
    private boolean modified = false;
121

    
122
    private String name = null;
123

    
124
    private String creationDate = null;
125

    
126
    private String modificationDate = null;
127

    
128
    private String owner = null;
129

    
130
    private String comments = null;
131

    
132
    private Color selectionColor = null;
133

    
134
    private List<Document> documents = null;
135

    
136
    private List<ProjectExtent> extents = null;
137

    
138
    private IProjection projection;
139

    
140
    private File fname = null;
141

    
142
    private Set<String> unloadedObjects;
143
    private PersistenceException loadErrors = null;
144

    
145
    /**
146
     * Creates a new Project object.
147
     */
148
    DefaultProject() {
149
        this.change = new PropertyChangeSupport(this);
150
        this.clean();
151
    }
152

    
153
    protected void clean() {
154
        this.owner = "";
155
        this.comments = "";
156
        this.name = PluginServices.getText(this, "untitled");
157
        this.creationDate = DateFormat.getDateInstance().format(new Date());
158
        this.modificationDate = this.creationDate;
159

    
160
        this.documents = new ArrayList<Document>();
161
        this.extents = new ArrayList<ProjectExtent>();
162

    
163
        this.setSelectionColor(getPreferences().getDefaultSelectionColor());
164

    
165
        this.projection = null; // se inicializa en el getProjection()
166
    }
167

    
168
    public static ProjectPreferences getPreferences() {
169
        return preferences;
170
    }
171

    
172
    public void propertyChange(PropertyChangeEvent evt) {
173
        change.firePropertyChange(evt);
174
    }
175

    
176
    public synchronized void addPropertyChangeListener(
177
            PropertyChangeListener arg0) {
178
        change.addPropertyChangeListener(arg0);
179
    }
180

    
181
    /**
182
     * Return the creation date of the project
183
     *
184
     * @return
185
     */
186
    public String getCreationDate() {
187
        return creationDate;
188
    }
189

    
190
    protected void setCreationDate(String creationDate) {
191
        this.creationDate = creationDate;
192
        change.firePropertyChange("setCreationDate", null, null);
193
    }
194

    
195
    public Document createDocument(String type) {
196
        logger.info("createDocument('{}')", type);
197
        return ProjectManager.getInstance().createDocument(type);
198
    }
199

    
200
    /**
201
     * Return the name of the project
202
     *
203
     * @return
204
     */
205
    public String getName() {
206
        return name;
207
    }
208

    
209
    /**
210
     * Set the name of he project.
211
     *
212
     * @param string
213
     */
214
    public void setName(String name) {
215
        this.name = name;
216
        change.firePropertyChange("setName", null, null);
217
    }
218

    
219
    /**
220
     * Return the comments associateds with the project
221
     *
222
     * @return comments
223
     */
224
    public String getComments() {
225
        return comments;
226
    }
227

    
228
    /**
229
     * Set the comments associateds with the project
230
     *
231
     * @param comments as string
232
     */
233
    public void setComments(String string) {
234
        comments = string;
235
        change.firePropertyChange("setComments", null, null);
236
    }
237

    
238
    /**
239
     * Retuen the modification date of the project.
240
     *
241
     * @return modification date as string
242
     */
243
    public String getModificationDate() {
244
        return modificationDate;
245
    }
246

    
247
    protected void setModificationDate(String string) {
248
        modificationDate = string;
249
        change.firePropertyChange("setModificationDate", null, null);
250
    }
251

    
252
    /**
253
     * Return the author of the project,
254
     *
255
     * @return author as string
256
     */
257
    public String getOwner() {
258
        return owner;
259
    }
260

    
261
    /**
262
     * Sets the author of the project
263
     *
264
     * @param author name as string
265
     */
266
    public void setOwner(String owner) {
267
        this.owner = owner;
268
        change.firePropertyChange("setOwner", null, null);
269
    }
270

    
271
    /**
272
     * Obtiene el color de selecci�n que se usar� en el proyecto
273
     *
274
     * @return
275
     */
276
    public Color getSelectionColor() {
277
        if (selectionColor == null) {
278
            selectionColor = getPreferences().getDefaultSelectionColor();
279
        }
280
        return selectionColor;
281
    }
282

    
283
    /**
284
     * Sets the selecction color
285
     *
286
     * @param selection color as string
287
     */
288
    public void setSelectionColor(String selectionColor) {
289
        this.setSelectionColor(StringUtilities.string2Color(selectionColor));
290
    }
291

    
292
    /**
293
     * Sets the selecction color
294
     *
295
     * @param selection color as Color
296
     */
297
    public void setSelectionColor(Color selectionColor) {
298
        this.selectionColor = selectionColor;
299
        MapContext.setSelectionColor(selectionColor);
300
        change.firePropertyChange("selectionColor", null, selectionColor);
301
    }
302

    
303
    public IProjection getProjection() {
304
        if (projection == null) {
305
            projection = getPreferences().getDefaultProjection();
306
        }
307
        return projection;
308
    }
309

    
310
    public void setProjection(IProjection projection) {
311
        this.projection = projection;
312
    }
313

    
314
    /**
315
     * Sets the modified state of project.
316
     *
317
     * Can't set to not modified.
318
     *
319
     * @param modified as boolean
320
     */
321
    public void setModified(boolean modified) {
322
        this.modified = modified;
323
        if (modified == false) {
324
            List<Document> documents = this.getDocuments();
325
            for (int i = 0; i < documents.size(); i++) {
326
                documents.get(i).setModified(false);
327
            }
328
        }
329
    }
330

    
331
    public boolean hasChanged() {
332
                // we return true if the project is not empty (until we have a better
333
        // method...)
334
        if ((this.getDocuments().size() != 0) || modified) {
335
            return true;
336
        }
337
        return false;
338
    }
339

    
340
    /**
341
     * Return a list of documents in the project.
342
     *
343
     * @return documents as List of IProjectDocument
344
     */
345
    public List<Document> getDocuments() {
346
        return Collections.unmodifiableList(documents);
347
    }
348

    
349
    /**
350
     * Return a list with all documents of especified type.
351
     *
352
     * @param type of document
353
     *
354
     * @return List of IProjectDocument
355
     */
356
    public List<Document> getDocuments(String type) {
357
        List<Document> docs = new ArrayList<Document>();
358
        if (type != null) {
359
            for (Document document : this.documents) {
360
                if (type.equalsIgnoreCase(document.getTypeName())) {
361
                    docs.add(document);
362
                }
363
            }
364
        }
365
        return Collections.unmodifiableList(docs);
366
    }
367

    
368
    /**
369
     * Adds a document to the project
370
     *
371
     * @param document as Document
372
     */
373
    public void add(Document document) {
374
        this.addDocument(document);
375
    }
376

    
377
    public void addDocument(Document document) {
378
        logger.info("add('{}')", document.toString());
379

    
380
        if (notifyObservers(ProjectNotification.BEFORE_ADD_DOCUMENT, document).isProcessCanceled()) {
381
            return;
382
        }
383
        document.addPropertyChangeListener(this);
384
        document.setProject(this);
385
        document.setName(this.getUniqueNameForDocument(document.getTypeName(),
386
                document.getName()));
387
        documents.add(document);
388
        document.afterAdd();
389
        this.setModified(true);
390
        notifyObservers(ProjectNotification.AFTER_ADD_DOCUMENT, document);
391
        change.firePropertyChange("addDocument", null, document);
392
    }
393

    
394
    public void remove(Document doc) {
395
        this.removeDocument(doc);
396
    }
397

    
398
    public void removeDocument(Document doc) {
399
        logger.info("remove('{}')", doc.toString());
400
        if (notifyObservers(ProjectNotification.BEFORE_REMOVE_DOCUMENT, doc).isProcessCanceled()) {
401
            return;
402
        }
403
        documents.remove(doc);
404
        this.setModified(true);
405
        change.firePropertyChange("delDocument", doc, null);
406
        doc.afterRemove();
407
        notifyObservers(ProjectNotification.AFTER_REMOVE_DOCUMENT, doc);
408
    }
409

    
410
    public Iterator<Document> iterator() {
411
        return documents.iterator();
412
    }
413

    
414
    public boolean isEmpty() {
415
        return documents.isEmpty();
416
    }
417

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

    
438
        throw new RuntimeException(MessageFormat.format(
439
                "The layer '{1}' is not in a view", layer.getName()));
440
    }
441

    
442
    private boolean isView(FLayers layers, FLayer layer) {
443
        for (int i = 0; i < layers.getLayersCount(); i++) {
444
            if (layers.getLayer(i) instanceof FLayers) {
445
                if (isView((FLayers) layers.getLayer(i), layer)) {
446
                    return true;
447
                }
448
            }
449
            if (layers.getLayer(i) == layer) {
450
                return true;
451
            }
452
        }
453
        return false;
454
    }
455

    
456
    public void addExtent(ProjectExtent arg1) {
457
        extents.add(arg1);
458
        change.firePropertyChange("addExtent", null, null);
459
    }
460

    
461
    public ProjectExtent removeExtent(int arg0) {
462
        change.firePropertyChange("delExtent", null, null);
463
        return extents.remove(arg0);
464
    }
465

    
466
    public ProjectExtent[] getExtents() {
467
        return (ProjectExtent[]) extents.toArray(new ProjectExtent[0]);
468
    }
469

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

    
500
    public Document getDocument(String name) {
501
        return this.getDocument(name, null);
502
    }
503

    
504
    public String getUniqueNameForDocument(String type, String name) {
505
        Document document = getDocument(name, type);
506
        if (document == null) {
507
            return name;
508
        }
509

    
510
        String newName = null;
511
        int num = this.getNextDocumentIndex(type);
512
        while (document != null) {
513
            newName = name + " - " + num++;
514
            document = getDocument(newName, type);
515
        }
516
        this.setNextDocumentIndex(type, num);
517
        return newName;
518
    }
519

    
520
    private int getNextDocumentIndex(String type) {
521
        if (nextDocumentIndexByType.get(type) == null) {
522
            nextDocumentIndexByType.put(type, new Integer(1));
523
            return 1;
524
        }
525
        return nextDocumentIndexByType.get(type).intValue();
526
    }
527

    
528
    private void setNextDocumentIndex(String type, int newIndex) {
529
        if (nextDocumentIndexByType.get(type) == null) {
530
            nextDocumentIndexByType.put(type, new Integer(newIndex));
531
        } else {
532
            nextDocumentIndexByType.put(type, new Integer(newIndex));
533
        }
534
    }
535

    
536
    public void saveState(File out) throws PersistenceException {
537
        FileOutputStream fout;
538
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_FILE, out).isProcessCanceled()) {
539
            return;
540
        }
541
        try {
542
            fout = new FileOutputStream(out);
543
            saveState(fout, new File(out.getParent()));
544
        } catch (FileNotFoundException e) {
545
            throw new PersistenceException(e);
546
        }
547
        if( !isValidZIP(out) ) {
548
            throw new PersistenceException(new ZipException());
549
        }
550
        this.fname = out;
551
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_FILE, out);
552
    }
553

    
554
    boolean isValidZIP(final File file) {
555
        ZipFile zipfile = null;
556
        try {
557
            zipfile = new ZipFile(file);
558
            return true;
559
        } catch (IOException e) {
560
            return false;
561
        } finally {
562
            try {
563
                if (zipfile != null) {
564
                    zipfile.close();
565
                    zipfile = null;
566
                }
567
            } catch (IOException e) {
568
            }
569
        }
570
    }
571
   
572
    public File getFile() {
573
        return this.fname;
574
    }
575

    
576
    public void saveState(OutputStream out) throws PersistenceException {
577
        saveState(out, null);
578
    }
579

    
580
    public void saveState(OutputStream out, File rootFolder)
581
            throws PersistenceException {
582
        if (notifyObservers(ProjectNotification.BEFORE_SAVE_TO_STREAM).isProcessCanceled()) {
583
            return;
584
        }
585
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
586
        PersistentState state = null;
587
        state = manager.getState(this, true);
588
        try {
589
            if (rootFolder != null) {
590
                state.relativizeFiles(rootFolder);
591
            }
592
        } catch (Exception ex) {
593
            state.getContext().addError(ex);
594
        }
595
        manager.saveState(state, out, true);
596
        if (state.getContext().getErrors() != null) {
597
            throw state.getContext().getErrors();
598
        }
599
        this.fname = null;
600
        notifyObservers(ProjectNotification.AFTER_SAVE_TO_STREAM);
601
    }
602

    
603
    public void loadState(InputStream in) {
604
        loadState(in, null);
605
    }
606

    
607
    public void loadState(InputStream in, File rootFolder) {
608
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_STREAM).isProcessCanceled()) {
609
            return;
610
        }
611
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
612
        try {
613
            PersistentContext context = manager.getNewContext();
614
            context.setCollectErrors(true);
615
            PersistentState state = manager.loadState(in, context);
616
            try {
617
                if (rootFolder != null) {
618
                    state.derelativizeFiles(rootFolder);
619
                }
620
            } catch (Exception ex) {
621
                state.getContext().addError(ex);
622
            }
623
            this.loadFromState(state);
624
            this.unloadedObjects = getUnloadedObjects(state.getContext());
625
            this.loadErrors = state.getContext().getErrors();
626
        } catch (PersistenceException e) {
627
            LOG.info("Can't load project to stream", e);
628
        }
629
        this.fname = null;
630
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_STREAM);
631

    
632
    }
633

    
634

    
635

    
636
    /**
637
     * @param context
638
     * @return
639
     */
640
    private Set<String> getUnloadedObjects(PersistentContext context) {
641
        Set unloadedObjects = new HashSet();
642

    
643
        Iterator statesIterator = context.iterator();
644
        String className = null;
645

    
646
        while (statesIterator.hasNext()) {
647
            PersistentState aState = (PersistentState) statesIterator.next();
648
            try {
649
                className = aState.getTheClassName();
650
                DynStruct definition = aState.getDefinition();
651
                if (definition == null) {
652
                    unloadedObjects.add(className);
653
                }
654
            } catch (Throwable e) {
655
                // do nothing
656
            }
657
        }
658

    
659
        if(unloadedObjects.isEmpty()){
660
            return null;
661
        }
662

    
663
        return unloadedObjects;
664
    }
665

    
666
    @Override
667
    public Set<String> getUnloadedObjects() {
668
        return this.unloadedObjects;
669
    }
670

    
671
    @Override
672
    public List<Exception> getLoadErrors() {
673
        return this.loadErrors;
674
    }
675
    
676
    @Override
677
    public void loadState(File in) {
678
        if (notifyObservers(ProjectNotification.BEFORE_LOAD_FROM_FILE, in).isProcessCanceled()) {
679
            return;
680
        }
681
        FileInputStream fin;
682
        try {
683
            fin = new FileInputStream(in);
684
            loadState(fin, new File(in.getParent()));
685
        } catch (FileNotFoundException e) {
686
            LOG.info("Can't load project to stream", e);
687
        }
688
        this.fname = in;
689
        notifyObservers(ProjectNotification.AFTER_LOAD_FROM_FILE, in);
690
    }
691

    
692
    @SuppressWarnings("unchecked")
693
    public void loadFromState(PersistentState state)
694
            throws PersistenceException {
695
        this.clean();
696

    
697
        this.setComments(state.getString("comments"));
698
        this.setCreationDate(state.getString("creationDate"));
699
        this.setModificationDate(state.getString("modificationDate"));
700
        this.setName(state.getString("name"));
701
        this.setOwner(state.getString("owner"));
702
        this.setSelectionColor((Color) state.get("selectionColor"));
703
        this.setProjection((IProjection) state.get("projection"));
704

    
705
        this.propertiesHelper = (ExtendedPropertiesHelper) state.get("propertiesHelper");
706

    
707
        List<ProjectExtent> extents = (List<ProjectExtent>) state
708
                .get("extents");
709
        for (int i = 0; i < extents.size(); i++) {
710
            this.addExtent(extents.get(i));
711
        }
712

    
713
        List<AbstractDocument> documents = (List<AbstractDocument>) state
714
                .get("documents");
715
        for (int i = 0; i < documents.size(); i++) {
716
            this.add(documents.get(i));
717
        }
718

    
719
        List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
720

    
721
        for (int i = 0; i < persistentWindows.size(); i++) {
722
            DocumentWindowInfo persistentWindow = persistentWindows.get(i);
723
            String docName = persistentWindow.getDocumentName();
724
            String docType = persistentWindow.getDocumentType();
725
            Document doc = this.getDocument(docName, docType);
726
            IWindow win = doc.getFactory().getMainWindow(doc);
727
            if(win!=null){
728
                win.getWindowInfo().setWindowInfo(persistentWindow.getWindowInfo());
729
                PluginServices.getMDIManager().addWindow(win);
730
            }
731
        }
732

    
733
        if (state.hasValue("projectWindowInfo")) {
734
            WindowInfo projectWindowInfo = (WindowInfo) state.get("projectWindowInfo");
735
            ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(org.gvsig.app.extension.ProjectExtension.class);
736
            pe.setProject(this);
737
            pe.showProjectWindow(projectWindowInfo);
738
        }
739

    
740
    }
741

    
742
    public void saveToState(PersistentState state) throws PersistenceException {
743
        state.set("version", VERSION);
744
        state.set("comments", getComments());
745
        state.set("creationDate", this.getCreationDate());
746

    
747
        state.set("modificationDate", this.getModificationDate());
748
        state.set("name", this.getName());
749
        state.set("owner", this.getOwner());
750
        state.set("selectionColor", this.getSelectionColor());
751

    
752
        state.set("projection", this.getProjection());
753

    
754
        state.set("extents", this.extents);
755
        List<Document> docs = this.getDocuments();
756
        List<Document> noTempDocs = new ArrayList<Document>();
757
        for (Iterator iterator = docs.iterator(); iterator.hasNext();) {
758
            Document document = (Document) iterator.next();
759
            if(!document.isTemporary()){
760
                noTempDocs.add(document);
761
            }
762
        }
763
        state.set("documents", noTempDocs);
764

    
765
        state.set("propertiesHelper",propertiesHelper);
766

    
767
        List<DocumentWindowInfo> persistentWindows = new ArrayList<DocumentWindowInfo>();
768
        MDIManager mdiMan = PluginServices.getMDIManager();
769
        IWindow[] windows = mdiMan.getOrderedWindows();
770
        for (int i = windows.length - 1; i >= 0; i--) {
771
            IWindow window = windows[i];
772
            if (window instanceof IDocumentWindow) {
773
                WindowInfo wi = mdiMan.getWindowInfo(window);
774
                DocumentWindowInfo dwi = new DocumentWindowInfo(
775
                        wi,
776
                        ((IDocumentWindow) window).getDocument().getTypeName(),
777
                        ((IDocumentWindow) window).getDocument().getName());
778
                persistentWindows.add(dwi);
779
            } else if (window instanceof ProjectWindow) {
780
                state.set("projectWindowInfo", mdiMan.getWindowInfo(window));
781
            }
782
        }
783
        state.set("documentWindowsInformation", persistentWindows);
784

    
785
    }
786

    
787
    public Object getProperty(Object key) {
788
        return this.propertiesHelper.getProperty(key);
789
    }
790

    
791
    public void setProperty(Object key, Object obj) {
792
        this.propertiesHelper.setProperty(key, obj);
793
    }
794

    
795
    public Map getExtendedProperties() {
796
        return this.propertiesHelper.getExtendedProperties();
797
    }
798

    
799
    public static class DocumentWindowInfo implements Persistent {
800

    
801
        public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
802

    
803
        private WindowInfo windowInfo;
804
        private String documentType;
805
        private String documentName;
806

    
807
        public DocumentWindowInfo() {
808
        }
809

    
810
        DocumentWindowInfo(WindowInfo wi, String docType, String docName) {
811
            windowInfo = wi;
812
            documentType = docType;
813
            documentName = docName;
814
        }
815

    
816
        public WindowInfo getWindowInfo() {
817
            return windowInfo;
818
        }
819

    
820
        public String getDocumentType() {
821
            return documentType;
822
        }
823

    
824
        public String getDocumentName() {
825
            return documentName;
826
        }
827

    
828
        public void saveToState(PersistentState state)
829
                throws PersistenceException {
830
            state.set("windowInfo", this.windowInfo);
831
            state.set("documentType", this.documentType);
832
            state.set("documentName", this.documentName);
833
        }
834

    
835
        public void loadFromState(PersistentState state)
836
                throws PersistenceException {
837
            this.windowInfo = (WindowInfo) state.get("windowInfo");
838
            this.documentType = state.getString("documentType");
839
            this.documentName = state.getString("documentName");
840
        }
841

    
842
        public static void registerPersistent() {
843
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
844
            DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
845
            if (definition == null) {
846
                definition = manager.addDefinition(
847
                        DocumentWindowInfo.class,
848
                        PERSISTENCE_DEFINITION_NAME,
849
                        "DocumentWindowInfo persistence definition",
850
                        null,
851
                        null
852
                );
853
                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
854
                definition.addDynFieldString("documentType").setMandatory(true);
855
                definition.addDynFieldString("documentName").setMandatory(true);
856
            }
857

    
858
        }
859
    }
860

    
861
    public static void registerPersistent() {
862
        AbstractDocument.registerPersistent();
863
        DocumentWindowInfo.registerPersistent();
864
        ProjectExtent.registerPersistent();
865

    
866
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
867
        DynStruct definition = manager.addDefinition(DefaultProject.class,
868
                "Project", "Project Persistence definition", null, null);
869
        definition.addDynFieldString("version").setMandatory(true);
870
        definition.addDynFieldString("comments").setMandatory(true);
871
        definition.addDynFieldString("creationDate").setMandatory(true);
872
        definition.addDynFieldString("modificationDate").setMandatory(true);
873
        definition.addDynFieldString("name").setMandatory(true);
874
        definition.addDynFieldString("owner").setMandatory(true);
875

    
876
        definition.addDynFieldObject("selectionColor")
877
                .setClassOfValue(Color.class).setMandatory(true);
878
        definition.addDynFieldObject("projection")
879
                .setClassOfValue(IProjection.class).setMandatory(true);
880

    
881
        definition.addDynFieldList("extents")
882
                .setClassOfItems(ProjectExtent.class).setMandatory(true);
883

    
884
        definition.addDynFieldList("documents").setClassOfItems(Document.class)
885
                .setMandatory(true);
886

    
887
        definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
888

    
889
        definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
890

    
891

    
892
        definition.addDynFieldObject("propertiesHelper").setClassOfValue(ExtendedPropertiesHelper.class)
893
                        .setMandatory(false);
894

    
895
    }
896

    
897
    /**
898
     * @deprecated use getPreferences().setDefaultSelectionColor()
899
     */
900
    public static void setDefaultSelectionColor(Color color) {
901
        getPreferences().setDefaultSelectionColor(color);
902
    }
903

    
904
    /**
905
     * @deprecated use getPreferences().getDefaultSelectionColor()
906
     */
907
    public static Color getDefaultSelectionColor() {
908
        return getPreferences().getDefaultSelectionColor();
909
    }
910

    
911
    /**
912
     * @deprecated use getPreferences().getDefaultMapUnits()
913
     */
914
    public static int getDefaultMapUnits() {
915
        return getPreferences().getDefaultMapUnits();
916
    }
917

    
918
    /**
919
     * @deprecated use getPreferences().getDefaultDistanceUnits()
920
     */
921
    public static int getDefaultDistanceUnits() {
922
        return getPreferences().getDefaultDistanceUnits();
923
    }
924

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

    
932
    /**
933
     * @deprecated use getPreferences().setDefaultMapUnits()
934
     */
935
    public static void setDefaultMapUnits(int mapUnits) {
936
        getPreferences().setDefaultMapUnits(mapUnits);
937
    }
938

    
939
    /**
940
     * @deprecated use getPreferences().setDefaultDistanceUnits()
941
     */
942
    public static void setDefaultDistanceUnits(int distanceUnits) {
943
        getPreferences().setDefaultDistanceUnits(distanceUnits);
944
    }
945

    
946
    /**
947
     * @deprecated use getPreferences().setDefaultDistanceArea()
948
     */
949
    public static void setDefaultDistanceArea(int distanceArea) {
950
        getPreferences().setDefaultDistanceArea(distanceArea);
951
    }
952

    
953
    /**
954
     * @deprecated use getPreferences().setDefaultProjection()
955
     */
956
    public static void setDefaultProjection(IProjection defaultProjection) {
957
        getPreferences().setDefaultProjection(defaultProjection);
958
    }
959

    
960
    /**
961
     * @deprecated use getPreferences().getDefaultProjection()
962
     */
963
    public static IProjection getDefaultProjection() {
964
        return getPreferences().getDefaultProjection();
965
    }
966

    
967
    /**
968
     * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
969
     * 2.1.0
970
     */
971
    public void setColor(String color) {
972
        this.setSelectionColor(StringUtilities.string2Color(color));
973
    }
974

    
975
    /**
976
     * Return the selection color
977
     *
978
     * @return selection color as string
979
     * @deprecated use {@link #getSelectionColor()}
980
     */
981
    public String getColor() {
982
        return StringUtilities.color2String(selectionColor);
983
    }
984

    
985
    /**
986
     * Return the list of views of the project
987
     *
988
     * @return views as ArrayList of ProjectDocument
989
     *
990
     * @deprecated see {@link #getDocumentsByType(String)}
991
     */
992
    public List<Document> getViews() {
993
        return getDocuments(ViewManager.TYPENAME);
994
    }
995

    
996
    /**
997
     * Add a view to the project
998
     *
999
     * @deprecated see {@link #add(AbstractDocument)}
1000
     */
1001
    public void addView(DefaultViewDocument v) {
1002
        add(v);
1003
    }
1004

    
1005
    /**
1006
     * Remove a view of the project
1007
     *
1008
     * @param index of the view as integer
1009
     *
1010
     * @deprecated see {@link #remove(AbstractDocument)}
1011
     */
1012
    public void delView(int i) {
1013
        List<Document> list = getDocuments(ViewManager.TYPENAME);
1014
        remove(list.get(i));
1015
    }
1016

    
1017
    /**
1018
     * @deprecated see {@link #getDocument(String, String)}
1019
     */
1020
    public Document getProjectDocumentByName(String name, String type) {
1021
        return this.getDocument(name, type);
1022
    }
1023

    
1024
    /**
1025
     * @deprecated see {@link #getDocuments(String)}
1026
     */
1027
    public List<Document> getDocumentsByType(String type) {
1028
        return this.getDocuments(type);
1029
    }
1030

    
1031
    /**
1032
     * @deprecated aun por decidir que API darle al copy/paste
1033
     */
1034
    public String exportToXML(AbstractDocument[] selectedItems)
1035
            throws SaveException {
1036
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1037
        throw new UnsupportedOperationException("This method is not supported");
1038
    }
1039

    
1040
    /**
1041
     * @deprecated aun por decidir que API darle al copy/paste
1042
     */
1043
    public void importFromXML(String sourceString, String docType) {
1044
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1045
        throw new UnsupportedOperationException("This method is not supported");
1046
    }
1047

    
1048
    /**
1049
     * @deprecated aun por decidir que API darle al copy/paste
1050
     */
1051
    public boolean isValidXMLForImport(String sourceString, String docType) {
1052
        // FIXME jjdc:hay que decirdir que API darle al copy/paste
1053
        throw new UnsupportedOperationException("This method is not supported");
1054
    }
1055

    
1056
    public boolean canImportDocuments(String data, String doctype) {
1057
        // TODO Auto-generated method stub
1058
        return false;
1059
    }
1060

    
1061
    public String exportDocumentsAsText(List<Document> documents) {
1062
        // TODO Auto-generated method stub
1063
        return null;
1064
    }
1065

    
1066
    public void importDocuments(String data, String doctype) {
1067
        // TODO Auto-generated method stub
1068

    
1069
    }
1070

    
1071
    public Document getActiveDocument() {
1072
        return this.getActiveDocument((Class<? extends Document>)null);
1073
    }
1074

    
1075
    public Document getActiveDocument(String documentTypeName) {
1076
        ApplicationManager application = ApplicationLocator.getManager();
1077

    
1078
        Document document = null;
1079
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1080
        IWindow window = null;
1081
        for (int i = 0; i < windows.length; i++) {
1082
            window = windows[i];
1083
            if (window instanceof SingletonWindow) {
1084
                // Cogemos no la primera ventana, si no la primera
1085
                // ventana de tipo documento (SingletonWindow).
1086
                // Y por si las mosca no es un documento, atrapamos
1087
                // los errores y continuamos si no puede hacer un cast
1088
                // del Model a Document
1089
                try {
1090
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1091
                    if (documentTypeName == null) {
1092
                        return document;
1093
                    }
1094
                    if( document.getTypeName().equalsIgnoreCase(documentTypeName) ) {
1095
                        return document;
1096
                    }
1097
                    if( document instanceof DocumentsContainer ) {
1098
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentTypeName);
1099
                        return subdoc;
1100
                    }
1101

    
1102
                } catch (ClassCastException e) {
1103
                    // Do nothing, skip this window
1104
                }
1105
            }
1106
        }
1107
        return null;
1108
    }
1109

    
1110
    public Document getActiveDocument(Class<? extends Document> documentClass) {
1111
        ApplicationManager application = ApplicationLocator.getManager();
1112

    
1113
        Document document = null;
1114
        IWindow[] windows = application.getUIManager().getOrderedWindows();
1115
        IWindow window = null;
1116
        for (int i = 0; i < windows.length; i++) {
1117
            window = windows[i];
1118
            if (window instanceof SingletonWindow && window instanceof IDocumentWindow) {
1119
                // Cogemos no la primera ventana, si no la primera
1120
                // ventana de tipo documento (SingletonWindow).
1121
                // Y por si las mosca no es un documento, atrapamos
1122
                // los errores y continuamos si no puede hacer un cast
1123
                // del Model a Document
1124
                try {
1125
                    document = (Document) ((SingletonWindow) window).getWindowModel();
1126
                    if (documentClass == null) {
1127
                        return document;
1128
                    }
1129
                    if (documentClass.isAssignableFrom(document.getClass())) {
1130
                        return document;
1131
                    }
1132
                    if( document instanceof DocumentsContainer ) {
1133
                        Document subdoc = ((DocumentsContainer)document).getActiveDocument(documentClass);
1134
                        return subdoc;
1135
                    }
1136

    
1137
                } catch (ClassCastException e) {
1138
                    // Do nothing, skip this window
1139
                }
1140
            }
1141
        }
1142
        return null;
1143
    }
1144

    
1145
    public void addObserver(Observer o) {
1146
        observableHelper.addObserver(o);
1147
    }
1148

    
1149
    public void deleteObserver(Observer o) {
1150
        observableHelper.deleteObserver(o);
1151
    }
1152

    
1153
    public void deleteObservers() {
1154
        observableHelper.deleteObservers();
1155
    }
1156

    
1157
//        private void notifyObservers(ProjectNotifycation notifycation) {
1158
//                observableHelper.notifyObservers(this, notifycation);
1159
//        }
1160
    private ProjectNotification notifyObservers(int type) {
1161
        DefaultProjectNotification notifycation
1162
                = new DefaultProjectNotification(type, null, null);
1163
        try {
1164
            observableHelper.notifyObservers(this, notifycation);
1165
        } catch (Exception ex) {
1166
            LOG.info("Can't notify observers", ex);
1167
        }
1168
        return notifycation;
1169
    }
1170

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

    
1182
    private ProjectNotification notifyObservers(int type, File file) {
1183
        DefaultProjectNotification notifycation
1184
                = new DefaultProjectNotification(type, null, file);
1185
        try {
1186
            observableHelper.notifyObservers(this, notifycation);
1187
        } catch (Exception ex) {
1188
            LOG.info("Can't notify observers", ex);
1189
        }
1190
        return notifycation;
1191
    }
1192

    
1193
    class DefaultProjectNotification implements ProjectNotification {
1194

    
1195
        private int type;
1196
        private Document document;
1197
        private File file;
1198
        private boolean processCanceled = false;
1199

    
1200
        DefaultProjectNotification(int type, Document document, File file) {
1201
            this.type = type;
1202
            this.document = document;
1203
            this.file = file;
1204
        }
1205

    
1206
        public int getNotificationType() {
1207
            return type;
1208
        }
1209

    
1210
        public Document getDocument() {
1211
            return document;
1212
        }
1213

    
1214
        public void cancelProcess() {
1215
            processCanceled = true;
1216
        }
1217

    
1218
        public boolean isProcessCanceled() {
1219
            return processCanceled;
1220
        }
1221

    
1222
        public File getFile() {
1223
            return file;
1224
        }
1225

    
1226
    }
1227

    
1228
}