Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / applications / appgvSIG / src / org / gvsig / app / project / DefaultProject.java @ 36184

History | View | Annotate | Download (34.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2009 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2004-2009 IVER TI
26
 *   
27
 */
28

    
29
package org.gvsig.app.project;
30

    
31
import java.awt.Color;
32
import java.beans.PropertyChangeEvent;
33
import java.beans.PropertyChangeListener;
34
import java.beans.PropertyChangeSupport;
35
import java.io.File;
36
import java.io.FileInputStream;
37
import java.io.FileNotFoundException;
38
import java.io.FileOutputStream;
39
import java.io.IOException;
40
import java.io.InputStream;
41
import java.io.OutputStream;
42
import java.io.Serializable;
43
import java.net.MalformedURLException;
44
import java.net.URI;
45
import java.net.URISyntaxException;
46
import java.net.URL;
47
import java.text.DateFormat;
48
import java.text.MessageFormat;
49
import java.util.ArrayList;
50
import java.util.Collections;
51
import java.util.Date;
52
import java.util.HashMap;
53
import java.util.Iterator;
54
import java.util.List;
55
import java.util.Map;
56
import java.util.regex.Pattern;
57

    
58
import org.cresques.cts.IProjection;
59
import org.gvsig.andami.PluginServices;
60
import org.gvsig.andami.ui.mdiManager.IWindow;
61
import org.gvsig.andami.ui.mdiManager.SingletonWindow;
62
import org.gvsig.andami.ui.mdiManager.WindowInfo;
63
import org.gvsig.app.ApplicationLocator;
64
import org.gvsig.app.ApplicationManager;
65
import org.gvsig.app.extension.ProjectExtension;
66
import org.gvsig.app.extension.Version;
67
import org.gvsig.app.project.documents.AbstractDocument;
68
import org.gvsig.app.project.documents.Document;
69
import org.gvsig.app.project.documents.exceptions.SaveException;
70
import org.gvsig.app.project.documents.gui.IDocumentWindow;
71
import org.gvsig.app.project.documents.gui.ProjectWindow;
72
import org.gvsig.app.project.documents.layout.DefaultLayoutManager;
73
import org.gvsig.app.project.documents.layout.LayoutDocument;
74
import org.gvsig.app.project.documents.table.TableDocument;
75
import org.gvsig.app.project.documents.table.TableManager;
76
import org.gvsig.app.project.documents.view.DefaultViewDocument;
77
import org.gvsig.app.project.documents.view.ViewManager;
78
import org.gvsig.fmap.dal.DataTypes;
79
import org.gvsig.fmap.mapcontext.MapContext;
80
import org.gvsig.fmap.mapcontext.layers.FLayer;
81
import org.gvsig.fmap.mapcontext.layers.FLayers;
82
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
83
import org.gvsig.tools.ToolsLocator;
84
import org.gvsig.tools.dynobject.DynField;
85
import org.gvsig.tools.dynobject.DynStruct;
86
import org.gvsig.tools.persistence.PersistenceManager;
87
import org.gvsig.tools.persistence.Persistent;
88
import org.gvsig.tools.persistence.PersistentContext;
89
import org.gvsig.tools.persistence.PersistentState;
90
import org.gvsig.tools.persistence.exception.PersistenceException;
91
import org.gvsig.utils.StringUtilities;
92
import org.slf4j.Logger;
93
import org.slf4j.LoggerFactory;
94

    
95
/**
96
 * Clase que representa un proyecto de gvSIG
97
 * 
98
 * @author 2004-2005 Fernando Gonz?lez Cort?s
99
 * @author 2006-2009 Jose Manuel Vivo
100
 * @author 2005- Vicente Caballero
101
 * @author 2009- Joaquin del Cerro
102
 * 
103
 */
104

    
105
public class DefaultProject implements Serializable, PropertyChangeListener,
106
                Project {
107

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

    
114
        /**
115
         * 
116
         */
117
        private static final long serialVersionUID = -4449622027521773178L;
118

    
119
        // private static final Logger logger = LoggerFactory.getLogger(Project
120
        // .class);
121

    
122
        private static ProjectPreferences preferences = new ProjectPreferences();
123

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

    
129
        private PropertyChangeSupport change;
130

    
131
        private boolean modified = false;
132

    
133
        private String name = null;
134

    
135
        private String creationDate = null;
136

    
137
        private String modificationDate = null;
138

    
139
        private String owner = null;
140

    
141
        private String comments = null;
142

    
143
        private Color selectionColor = null;
144

    
145
        private List<Document> documents = null;
146

    
147
        private List<ProjectExtent> extents = null;
148

    
149
        private IProjection projection;
150

    
151
        /**
152
         * Creates a new Project object.
153
         */
154
        DefaultProject() {
155
                this.change = new PropertyChangeSupport(this);
156
                this.clean();
157
        }
158

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

    
166
                this.documents = new ArrayList<Document>();
167
                this.extents = new ArrayList<ProjectExtent>();
168

    
169
                this.setSelectionColor(getPreferences().getDefaultSelectionColor());
170

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

    
174
        public static ProjectPreferences getPreferences() {
175
                return preferences;
176
        }
177

    
178
        public void propertyChange(PropertyChangeEvent evt) {
179
                change.firePropertyChange(evt);
180
        }
181

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

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

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

    
201
    public Document createDocument(String type) {
202
        return ProjectManager.getInstance().createDocument(type);
203
    }
204

    
205
    /**
206
     * Return the name of the project
207
     * 
208
     * @return
209
     */
210
    public String getName() {
211
        return name;
212
    }
213

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

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

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

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

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

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

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

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

    
290
        /**
291
         * Sets the selecction color
292
         * 
293
         * @param selection
294
         *            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
304
         *            color as Color
305
         */
306
        public void setSelectionColor(Color selectionColor) {
307
                this.selectionColor = selectionColor;
308
                MapContext.setSelectionColor(selectionColor);
309
                change.firePropertyChange("selectionColor", null, selectionColor);
310
        }
311

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

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

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

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

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

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

    
379
        /**
380
         * Adds a document to the project
381
         * 
382
         * @param document
383
         *            as IProjectDocument
384
         */
385
        public void add(Document document) {
386
                document.addPropertyChangeListener(this);
387
                document.setProject(this);
388
                document.setName(this.getUniqueNameForDocument(document.getTypeName(),
389
                                document.getName()));
390
                documents.add(document);
391
                document.afterAdd();
392
                this.setModified(true);
393
                change.firePropertyChange("addDocument", null, null);
394
        }
395

    
396
        /**
397
         * Remove a document of the project
398
         * 
399
         * @param document
400
         *            as IProjectDocument
401
         */
402
        public void remove(Document doc) {
403
                documents.remove(doc);
404
                this.setModified(true);
405
                change.firePropertyChange("delDocument", null, null);
406
                doc.afterRemove();
407
        }
408

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

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

    
417
        /**
418
         * Return the FeatureTableDocument associated with a layer
419
         * 
420
         * @param layer
421
         * 
422
         * @return FeatureTableDocument associated with the layer.
423
         */
424
        public TableDocument getTable(FLyrVect layer) {
425
                List<Document> tables = getDocuments(TableManager.TYPENAME);
426
                for (int i = 0; i < tables.size(); i++) {
427
                        TableDocument table = (TableDocument) tables.get(i);
428
                        if (table.getStore().equals(layer.getFeatureStore())) {
429
                                return table;
430
                        }
431
                }
432

    
433
                return null;
434
        }
435

    
436
        /**
437
         * Return the view that contains the especified layer.
438
         * 
439
         * @param layer
440
         * 
441
         * @return name of the view that contains the layer
442
         * 
443
         * @throws RuntimeException
444
         *             Si la capa que se pasa como par?metro no se encuentra en
445
         *             ninguna vista
446
         */
447
        public String getViewName(FLayer layer) {
448
                List<Document> views = getDocuments(ViewManager.TYPENAME);
449
                for (int v = 0; v < views.size(); v++) {
450
                        DefaultViewDocument pView = (DefaultViewDocument) views.get(v);
451
                        FLayers layers = pView.getMapContext().getLayers();
452
                        if (isView(layers, layer)) {
453
                                return pView.getName();
454
                        }
455
                }
456

    
457
                throw new RuntimeException(MessageFormat.format(
458
                                "The layer '{1}' is not in a view", layer.getName()));
459
        }
460

    
461
        private boolean isView(FLayers layers, FLayer layer) {
462
                for (int i = 0; i < layers.getLayersCount(); i++) {
463
                        if (layers.getLayer(i) instanceof FLayers) {
464
                                if (isView((FLayers) layers.getLayer(i), layer)) {
465
                                        return true;
466
                                }
467
                        }
468
                        if (layers.getLayer(i) == layer) {
469
                                return true;
470
                        }
471
                }
472
                return false;
473
        }
474

    
475
        public void addExtent(ProjectExtent arg1) {
476
                extents.add(arg1);
477
                change.firePropertyChange("addExtent", null, null);
478
        }
479

    
480
        public ProjectExtent removeExtent(int arg0) {
481
                change.firePropertyChange("delExtent", null, null);
482
                return extents.remove(arg0);
483
        }
484

    
485
        public ProjectExtent[] getExtents() {
486
                return (ProjectExtent[]) extents.toArray(new ProjectExtent[0]);
487
        }
488

    
489
        /**
490
         * Obtiene un documento a partir de su nombre y el nombre de registro en el
491
         * pointExtension, este ?ltimo se puede obtener del
492
         * Project****Factory.registerName.
493
         * 
494
         * @param name
495
         *            Nombre del documento
496
         * @param type
497
         *            nombre de registro en el extensionPoint
498
         * 
499
         * @return Documento
500
         */
501
        public Document getDocument(String name, String type) {
502
                if (type != null) {
503
                        for (int i = 0; i < documents.size(); i++) {
504
                                Document document = documents.get(i);
505
                                if (type.equalsIgnoreCase(document.getTypeName())
506
                                                && name.equalsIgnoreCase(document.getName())) {
507
                                        return document;
508
                                }
509
                        }
510
                }
511
                return null;
512
        }
513

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

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

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

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

    
546
        public void saveState(File out) throws PersistenceException {
547
                FileOutputStream fout;
548
                try {
549
                        fout = new FileOutputStream(out);
550
                        saveState(fout, new File(out.getParent()));
551
                } catch (FileNotFoundException e) {
552
                        throw new PersistenceException(e);
553
                }
554
        }
555

    
556
        public void saveState(OutputStream out) throws PersistenceException {
557
                saveState(out, null);
558
        }
559

    
560
        public void saveState(OutputStream out, File rootFolder)
561
                        throws PersistenceException {
562
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
563
                PersistentState state = null;
564
                state = manager.getState(this, true);
565
                try {
566
                        if (rootFolder != null) {
567
                                relativizeFiles(state, rootFolder);
568
                        }
569
                } catch (Exception ex) {
570
                        state.getContext().addError(ex);
571
                }
572
                manager.saveState(state, out);
573
                if (state.getContext().getErrors() != null) {
574
                        throw state.getContext().getErrors();
575
                }
576
        }
577

    
578
        private void relativizeFiles(PersistentState state, File rootFolder) {
579
                PersistentContext context = state.getContext();
580

    
581
                URI cwd = new File(System.getProperty("user.dir")).toURI();
582
                @SuppressWarnings("unchecked")
583
                Iterator<PersistentState> statesIterator = context.iterator();
584
                while (statesIterator.hasNext()) {
585
                        PersistentState aState = statesIterator.next();
586
                        DynStruct definition = aState.getDefinition();
587
                        DynField[] fields = definition.getDynFields();
588
                        for (DynField field : fields) {
589
                                if (field.getType() == DataTypes.FILE
590
                                                || field.getType() == DataTypes.FOLDER) {
591
                                        try {
592
                                                File value = aState.getFile(field.getName());
593
                                                value = relativizeFile(value, rootFolder);
594
                                                aState.set(field.getName(), value);
595
                                        } catch (PersistenceException e) {
596
                                                LOG.warn(
597
                                                                "Can't relativice field '" + field.getName()
598
                                                                                + "' for class '"
599
                                                                                + definition.getName() + "'.", e);
600
                                        }
601
                                } else if (field.getType() == DataTypes.URL) {
602
                                        try {
603
                                                URL value = aState.getURL(field.getName());
604
                                                if ("FILE".equalsIgnoreCase(value.getProtocol())) {
605
                                                        File file = new File(value.toURI());
606
                                                        file = relativizeFile(file, rootFolder);
607
                                                        value = new URL("file","",file.toURI().toString().substring(cwd.toString().length()));
608
                                                        aState.set(field.getName(), value);
609
                                                }
610
                                        } catch (PersistenceException e) {
611
                                                // do nothind
612
                                        } catch (MalformedURLException e) {
613
                                                // do nothind
614
                                        } catch (URISyntaxException e) {
615
                                                // do nothind
616
                                        }
617
                                }
618
                        }
619
                }
620
        }
621

    
622
        private File relativizeFile(File file, File rootFolder) {
623
                if (rootFolder == null) {
624
                        return file;
625
                }
626
                if (file == null) {
627
                        return null;
628
                }
629
                boolean isDir = false;
630
                // isDir = file.isDirectory();
631
                isDir = rootFolder.isDirectory();
632
                String basePath = rootFolder.getAbsolutePath();
633
                String targetPath = file.getPath();
634
                String pathSeparator = File.separator;
635
                // We need the -1 argument to split to make sure we get a trailing
636
                // "" token if the base ends in the path separator and is therefore
637
                // a directory. We require directory paths to end in the path
638
                // separator -- otherwise they are indistinguishable from files.
639
                String[] base = basePath.split(Pattern.quote(pathSeparator), -1);
640
                String[] target = targetPath.split(Pattern.quote(pathSeparator), 0);
641

    
642
                // First get all the common elements. Store them as a string,
643
                // and also count how many of them there are.
644
                String common = "";
645
                int commonIndex = 0;
646
                for (int i = 0; i < target.length && i < base.length; i++) {
647
                        if (target[i].equals(base[i])) {
648
                                common += target[i] + pathSeparator;
649
                                commonIndex++;
650
                        } else
651
                                break;
652
                }
653

    
654
                if (commonIndex == 0) {
655
                        // Whoops -- not even a single common path element. This most
656
                        // likely indicates differing drive letters, like C: and D:.
657
                        // These paths cannot be relativized. Return the target path.
658
                        return file;
659
                        // This should never happen when all absolute paths
660
                        // begin with / as in *nix.
661
                }
662

    
663
                String relative = "";
664
                if (base.length == commonIndex) {
665
                        // Comment this out if you prefer that a relative path not start
666
                        // with ./
667
                        relative = "." + pathSeparator;
668
                } else {
669
                        int numDirsUp = base.length - commonIndex - (isDir ? 0 : 1); /*
670
                                                                                                                                                 * only
671
                                                                                                                                                 * subtract
672
                                                                                                                                                 * 1 if
673
                                                                                                                                                 * it is
674
                                                                                                                                                 * a
675
                                                                                                                                                 * file.
676
                                                                                                                                                 */
677
                        // The number of directories we have to backtrack is the length of
678
                        // the base path MINUS the number of common path elements, minus
679
                        // one because the last element in the path isn't a directory.
680
                        for (int i = 1; i <= (numDirsUp); i++) {
681
                                relative += ".." + pathSeparator;
682
                        }
683
                }
684
                // if we are comparing directories then we
685
                if (targetPath.length() > common.length()) {
686
                        // it's OK, it isn't a directory
687
                        relative += targetPath.substring(common.length());
688
                }
689

    
690
                return new File(relative);
691
        }
692

    
693
        private void fixFiles(PersistentState state, File rootFolder) {
694
                PersistentContext context = state.getContext();
695
                URI cwd = new File(System.getProperty("user.dir")).toURI();
696

    
697
                @SuppressWarnings("unchecked")
698
                Iterator<PersistentState> statesIterator = context.iterator();
699
                while (statesIterator.hasNext()) {
700
                        PersistentState aState = statesIterator.next();
701
                        DynStruct definition = aState.getDefinition();
702
                        DynField[] fields = definition.getDynFields();
703
                        for (DynField field : fields) {
704
                                if (field.getType() == DataTypes.FILE
705
                                                || field.getType() == DataTypes.FOLDER) {
706
                                        try {
707
                                                File value = aState.getFile(field.getName());
708
                                                value = fixFile(value, rootFolder);
709
                                                aState.set(field.getName(), value);
710
                                        } catch (PersistenceException e) {
711
                                                LOG.warn(
712
                                                                "Can't fix field '" + field.getName()
713
                                                                                + "' for class '"
714
                                                                                + definition.getName() + "'.", e);
715
                                        }
716
                                } else if (field.getType() == DataTypes.URL) {
717
                                        try {
718
                                                URL value = aState.getURL(field.getName());
719
                                                if ("FILE".equalsIgnoreCase(value.getProtocol())) {
720
                                                        if (!value.getFile().startsWith("/")){
721
                                                                value = new URL("file","",cwd.getRawPath()+value.getFile());
722
                                                                File file = new File(value.toURI().getPath().substring(cwd.getPath().length()));
723
                                                                file = fixFile(file, rootFolder);
724
                                                                aState.set(field.getName(), file.toURI().toURL());
725
                                                        }
726
                                                }
727
                                        } catch (PersistenceException e) {
728
                                                // do nothing
729
                                        } catch (MalformedURLException e) {
730
                                                // do nothing
731
                                        } catch (URISyntaxException e) {
732
                                                // do nothing
733
                                        }
734

    
735
                                }
736
                        }
737
                }
738
        }
739

    
740
        private File fixFile(File file, File rootFolder) {
741
                if (file.isAbsolute()) {
742
                        return file;
743
                }
744
                try {
745
                        return new File(rootFolder, file.getPath()).getCanonicalFile();
746
                } catch (IOException e) {
747
                        return new File(rootFolder, file.getPath());
748
                }
749
        }
750

    
751
        public void loadState(InputStream in) {
752
                loadState(in, null);
753
        }
754

    
755
        public void loadState(InputStream in, File rootFolder) {
756
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
757
                try {
758
                        PersistentState state = manager.loadState(in);
759
                        try {
760
                                if (rootFolder != null) {
761
                                        fixFiles(state, rootFolder);
762
                                }
763
                        } catch (Exception ex) {
764
                                state.getContext().addError(ex);
765
                        }
766
                        this.loadFromState(state);
767
                } catch (PersistenceException e) {
768
                        // TODO Auto-generated catch block
769
                        e.printStackTrace();
770
                }
771

    
772
        }
773

    
774
        public void loadState(File in) {
775
                FileInputStream fin;
776
                try {
777
                        fin = new FileInputStream(in);
778
                        loadState(fin, new File(in.getParent()));
779
                } catch (FileNotFoundException e) {
780
                        // TODO Auto-generated catch block
781
                        e.printStackTrace();
782
                }
783
        }
784

    
785
        @SuppressWarnings("unchecked")
786
        public void loadFromState(PersistentState state)
787
                        throws PersistenceException {
788
                this.clean();
789

    
790
                this.setComments(state.getString("comments"));
791
                this.setCreationDate(state.getString("creationDate"));
792
                this.setModificationDate(state.getString("modificationDate"));
793
                this.setName(state.getString("name"));
794
                this.setOwner(state.getString("owner"));
795
                this.setSelectionColor((Color) state.get("selectionColor"));
796
                this.setProjection((IProjection) state.get("projection"));
797

    
798
                List<ProjectExtent> extents = (List<ProjectExtent>) state
799
                                .get("extents");
800
                for (int i = 0; i < extents.size(); i++) {
801
                        this.addExtent(extents.get(i));
802
                }
803

    
804
                List<AbstractDocument> documents = (List<AbstractDocument>) state
805
                                .get("documents");
806
                for (int i = 0; i < documents.size(); i++) {
807
                        this.add(documents.get(i));
808
                }
809

    
810
                List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
811
                                
812
                for (int i = 0; i < persistentWindows.size(); i++) {
813
                        DocumentWindowInfo persistentWindow = persistentWindows.get(i);
814
                        String docName = persistentWindow.getDocumentName();
815
                        String docType = persistentWindow.getDocumentType();
816
                        Document doc = this.getDocument(docName, docType);
817
                        IWindow win = doc.getFactory().getMainWindow(doc);
818
                        win.getWindowInfo().setWindowInfo(persistentWindow.getWindowInfo());
819
                        PluginServices.getMDIManager().addWindow(win);
820
                }
821
                
822
                if (state.hasValue("projectWindowInfo")){
823
                        WindowInfo projectWindowInfo = (WindowInfo)state.get("projectWindowInfo"); 
824
                        ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(org.gvsig.app.extension.ProjectExtension.class);
825
                        pe.setProject(this);
826
                        pe.showProjectWindow(projectWindowInfo);
827
                }
828

    
829
        }
830

    
831
        public void saveToState(PersistentState state) throws PersistenceException {
832
                state.set("version", VERSION);
833
                state.set("comments", getComments());
834
                state.set("creationDate", this.getCreationDate());
835

    
836
                state.set("modificationDate", this.getModificationDate());
837
                state.set("name", this.getName());
838
                state.set("owner", this.getOwner());
839
                state.set("selectionColor", this.getSelectionColor());
840

    
841
                state.set("projection", this.getProjection());
842

    
843
                state.set("extents", this.extents);
844
                state.set("documents", this.getDocuments());
845

    
846
                List<DocumentWindowInfo> persistentWindows = new ArrayList<DocumentWindowInfo>();
847
                IWindow[] windows = PluginServices.getMDIManager().getOrderedWindows();
848
                for (int i = windows.length - 1; i >= 0; i--) {
849
                        IWindow window = windows[i];
850
                        if (window instanceof IDocumentWindow){
851
                                DocumentWindowInfo dwi = new DocumentWindowInfo(
852
                                                window.getWindowInfo(),
853
                                                ((IDocumentWindow) window).getDocument().getTypeName(),
854
                                                ((IDocumentWindow) window).getDocument().getName());
855
                                persistentWindows.add(dwi);
856
                        } else if (window instanceof ProjectWindow){
857
                                state.set("projectWindowInfo", ((ProjectWindow)window).getWindowInfo());
858
                        }
859
                }
860
                state.set("documentWindowsInformation", persistentWindows);
861

    
862
        }
863

    
864
        public static class DocumentWindowInfo implements Persistent {
865

    
866
                public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
867

    
868
                private WindowInfo windowInfo;
869
                private String documentType;
870
                private String documentName;
871

    
872
                public DocumentWindowInfo(){
873
                }
874
                
875
                DocumentWindowInfo(WindowInfo wi, String docType, String docName){
876
                        windowInfo = wi;
877
                        documentType = docType;
878
                        documentName = docName;
879
                }
880

    
881
                public WindowInfo getWindowInfo() {
882
                        return windowInfo;
883
                }
884
                
885
                public String getDocumentType() {
886
                        return documentType;
887
                }
888

    
889
                public String getDocumentName() {
890
                        return documentName;
891
                }
892

    
893
                public void saveToState(PersistentState state)
894
                                throws PersistenceException {
895
                        state.set("windowInfo", this.windowInfo);
896
                        state.set("documentType", this.documentType);
897
                        state.set("documentName", this.documentName);
898
                }
899

    
900
                public void loadFromState(PersistentState state)
901
                                throws PersistenceException {
902
                        this.windowInfo = (WindowInfo) state.get("windowInfo");
903
                        this.documentType = state.getString("documentType");
904
                        this.documentName = state.getString("documentName");
905
                }
906
                
907
                public static void registerPersistent() {
908
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
909
                        DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
910
                        if ( definition == null ){
911
                                definition = manager.addDefinition(
912
                                                DocumentWindowInfo.class,
913
                                                PERSISTENCE_DEFINITION_NAME,
914
                                                "DocumentWindowInfo persistence definition",
915
                                                null, 
916
                                                null
917
                                );
918
                                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
919
                                definition.addDynFieldString("documentType").setMandatory(true);
920
                                definition.addDynFieldString("documentName").setMandatory(true);
921
                        }
922

    
923
                }
924
        }
925
        
926
        public static void registerPersistent() {
927
                AbstractDocument.registerPersistent();
928
                DocumentWindowInfo.registerPersistent();
929

    
930
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
931
                DynStruct definition = manager.addDefinition(DefaultProject.class,
932
                                "Project", "Project Persistence definition", null, null);
933
                definition.addDynFieldString("version").setMandatory(true);
934
                definition.addDynFieldString("comments").setMandatory(true);
935
                definition.addDynFieldString("creationDate").setMandatory(true);
936
                definition.addDynFieldString("modificationDate").setMandatory(true);
937
                definition.addDynFieldString("name").setMandatory(true);
938
                definition.addDynFieldString("owner").setMandatory(true);
939

    
940
                definition.addDynFieldObject("selectionColor")
941
                                .setClassOfValue(Color.class).setMandatory(true);
942
                definition.addDynFieldObject("projection")
943
                                .setClassOfValue(IProjection.class).setMandatory(true);
944

    
945
                definition.addDynFieldList("extents")
946
                                .setClassOfItems(ProjectExtent.class).setMandatory(true);
947

    
948
                definition.addDynFieldList("documents").setClassOfItems(Document.class)
949
                                .setMandatory(true);
950

    
951
                definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
952

    
953
                definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
954

    
955
        }
956

    
957
        /**
958
         * @deprecated use getPreferences().setDefaultSelectionColor()
959
         */
960
        public static void setDefaultSelectionColor(Color color) {
961
                getPreferences().setDefaultSelectionColor(color);
962
        }
963

    
964
        /**
965
         * @deprecated use getPreferences().getDefaultSelectionColor()
966
         */
967

    
968
        public static Color getDefaultSelectionColor() {
969
                return getPreferences().getDefaultSelectionColor();
970
        }
971

    
972
        /**
973
         * @deprecated use getPreferences().getDefaultMapUnits()
974
         */
975
        public static int getDefaultMapUnits() {
976
                return getPreferences().getDefaultMapUnits();
977
        }
978

    
979
        /**
980
         * @deprecated use getPreferences().getDefaultDistanceUnits()
981
         */
982
        public static int getDefaultDistanceUnits() {
983
                return getPreferences().getDefaultDistanceUnits();
984
        }
985

    
986
        /**
987
         * @deprecated use getPreferences().getDefaultDistanceArea()
988
         */
989
        public static int getDefaultDistanceArea() {
990
                return getPreferences().getDefaultDistanceArea();
991
        }
992

    
993
        /**
994
         * @deprecated use getPreferences().setDefaultMapUnits()
995
         */
996
        public static void setDefaultMapUnits(int mapUnits) {
997
                getPreferences().setDefaultMapUnits(mapUnits);
998
        }
999

    
1000
        /**
1001
         * @deprecated use getPreferences().setDefaultDistanceUnits()
1002
         */
1003
        public static void setDefaultDistanceUnits(int distanceUnits) {
1004
                getPreferences().setDefaultDistanceUnits(distanceUnits);
1005
        }
1006

    
1007
        /**
1008
         * @deprecated use getPreferences().setDefaultDistanceArea()
1009
         */
1010
        public static void setDefaultDistanceArea(int distanceArea) {
1011
                getPreferences().setDefaultDistanceArea(distanceArea);
1012
        }
1013

    
1014
        /**
1015
         * @deprecated use getPreferences().setDefaultProjection()
1016
         */
1017
        public static void setDefaultProjection(IProjection defaultProjection) {
1018
                getPreferences().setDefaultProjection(defaultProjection);
1019
        }
1020

    
1021
        /**
1022
         * @deprecated use getPreferences().getDefaultProjection()
1023
         */
1024
        public static IProjection getDefaultProjection() {
1025
                return getPreferences().getDefaultProjection();
1026
        }
1027

    
1028
        /**
1029
         * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
1030
         *             2.1.0
1031
         */
1032
        public void setColor(String color) {
1033
                this.setSelectionColor(StringUtilities.string2Color(color));
1034
        }
1035

    
1036
        /**
1037
         * Return the selection color
1038
         * 
1039
         * @return selection color as string
1040
         * @deprecated use {@link #getSelectionColor()}
1041
         */
1042
        public String getColor() {
1043
                return StringUtilities.color2String(selectionColor);
1044
        }
1045

    
1046
        /**
1047
         * Devuelve a partir del nombre la tabla asociada.
1048
         * 
1049
         * @param name
1050
         *            Nombre.
1051
         * @deprecated utilizar getProjectDocumentByName(...);
1052
         * @return ProjectTable de la tabla asociada.
1053
         */
1054
        public TableDocument getTable(String name) {
1055
                return (TableDocument) this.getDocument(name, TableManager.TYPENAME);
1056
        }
1057

    
1058
        /**
1059
         * Return the list of maps of the project
1060
         * 
1061
         * @return tables as ArrayList of IProjectDocument
1062
         * 
1063
         * @deprecated see {@link #getDocumentsByType(String)}
1064
         */
1065
        public List<Document> getMaps() {
1066
                return getDocuments(DefaultLayoutManager.TYPENAME);
1067
        }
1068

    
1069
        /**
1070
         * Add a {@link LayoutDocument} to the project
1071
         * 
1072
         * @deprecated see {@link #add(Document)}
1073
         */
1074
        public void addMap(LayoutDocument m) {
1075
                add(m);
1076
        }
1077

    
1078
        /**
1079
         * Remove a map of the project
1080
         * 
1081
         * @param index
1082
         *            of the map as integer
1083
         * 
1084
         * @deprecated see {@link #remove(Document)}
1085
         */
1086
        public void delMap(int i) {
1087
                List<Document> list = getDocuments(DefaultLayoutManager.TYPENAME);
1088
                remove(list.get(i));
1089
        }
1090

    
1091
        /**
1092
         * Return the list of tables of the project
1093
         * 
1094
         * @return tables as ArrayList of ProjectDocument
1095
         * 
1096
         * @deprecated see {@link #getDocumentsByType(String)}
1097
         */
1098
        public List<Document> getTables() {
1099
                return getDocuments(TableManager.TYPENAME);
1100
        }
1101

    
1102
        /**
1103
         * Add a {@link TableDocument } to the project
1104
         * 
1105
         * @deprecated see {@link #add(AbstractDocument)}
1106
         */
1107
        public void addTable(TableDocument t) {
1108
                add(t);
1109
        }
1110

    
1111
        /**
1112
         * Remove a {@link TableDocument } of the project
1113
         * 
1114
         * @param index
1115
         *            of the table as integer
1116
         * 
1117
         * @deprecated see {@link #remove(AbstractDocument)}
1118
         */
1119
        public void delTable(int i) {
1120
                List<Document> list = getDocuments(TableManager.TYPENAME);
1121
                remove(list.get(i));
1122
        }
1123

    
1124
        /**
1125
         * Return the list of views of the project
1126
         * 
1127
         * @return views as ArrayList of ProjectDocument
1128
         * 
1129
         * @deprecated see {@link #getDocumentsByType(String)}
1130
         */
1131
        public List<Document> getViews() {
1132
                return getDocuments(ViewManager.TYPENAME);
1133
        }
1134

    
1135
        /**
1136
         * Add a view to the project
1137
         * 
1138
         * @deprecated see {@link #add(AbstractDocument)}
1139
         */
1140
        public void addView(DefaultViewDocument v) {
1141
                add(v);
1142
        }
1143

    
1144
        /**
1145
         * Remove a view of the project
1146
         * 
1147
         * @param index
1148
         *            of the view as integer
1149
         * 
1150
         * @deprecated see {@link #remove(AbstractDocument)}
1151
         */
1152
        public void delView(int i) {
1153
                List<Document> list = getDocuments(ViewManager.TYPENAME);
1154
                remove(list.get(i));
1155
        }
1156

    
1157
        /**
1158
         * @deprecated see {@link #getDocument(String, String)}
1159
         */
1160
        public Document getProjectDocumentByName(String name, String type) {
1161
                return this.getDocument(name, type);
1162
        }
1163

    
1164
        /**
1165
         * @deprecated see {@link #getDocuments(String)}
1166
         */
1167
        public List<Document> getDocumentsByType(String type) {
1168
                return this.getDocuments(type);
1169
        }
1170

    
1171
        /**
1172
         * @deprecated aun por decidir que API darle al copy/paste
1173
         */
1174
        public String exportToXML(AbstractDocument[] selectedItems)
1175
                        throws SaveException {
1176
                // FIXME jjdc:hay que decirdir que API darle al copy/paste
1177
                throw new UnsupportedOperationException("This method is not supported");
1178
        }
1179

    
1180
        /**
1181
         * @deprecated aun por decidir que API darle al copy/paste
1182
         */
1183
        public void importFromXML(String sourceString, String docType) {
1184
                // FIXME jjdc:hay que decirdir que API darle al copy/paste
1185
                throw new UnsupportedOperationException("This method is not supported");
1186
        }
1187

    
1188
        /**
1189
         * @deprecated aun por decidir que API darle al copy/paste
1190
         */
1191
        public boolean isValidXMLForImport(String sourceString, String docType) {
1192
                // FIXME jjdc:hay que decirdir que API darle al copy/paste
1193
                throw new UnsupportedOperationException("This method is not supported");
1194
        }
1195

    
1196
        public boolean canImportDocuments(String data, String doctype) {
1197
                // TODO Auto-generated method stub
1198
                return false;
1199
        }
1200

    
1201
        public String exportDocumentsAsText(List<Document> documents) {
1202
                // TODO Auto-generated method stub
1203
                return null;
1204
        }
1205

    
1206
        public void importDocuments(String data, String doctype) {
1207
                // TODO Auto-generated method stub
1208

    
1209
        }
1210

    
1211
        public Document getActiveDocument() {
1212
                ApplicationManager application = ApplicationLocator.getManager();
1213

    
1214
                Document document = null;
1215
                IWindow[] windows = application.getUIManager().getOrderedWindows();
1216
                IWindow window = null;
1217
                for (int i = 0; i < windows.length; i++) {
1218
                        if (window instanceof SingletonWindow) {
1219
                                // Cogemos no la primera ventana, si no la primera
1220
                                // ventana de tipo documento (SingletonWindow).
1221
                                // Y por si las mosca no es un documento, atrapamos
1222
                                // los errores y continuamos si no puede hacer un cast
1223
                                // del Model a Document
1224
                                try {
1225
                                        document = (Document) ((SingletonWindow) window).getWindowModel();
1226
                                        return document;
1227
                                } catch (ClassCastException e) {
1228
                                        // Do nothing, skip this window
1229
                                }
1230
                        }
1231
                }
1232
                return null;
1233
        } 
1234
}