Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2059 / applications / appgvSIG / src / org / gvsig / app / project / DefaultProject.java @ 39289

History | View | Annotate | Download (35.3 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.InputStream;
40
import java.io.OutputStream;
41
import java.io.Serializable;
42
import java.net.MalformedURLException;
43
import java.net.URI;
44
import java.net.URISyntaxException;
45
import java.net.URL;
46
import java.text.DateFormat;
47
import java.text.MessageFormat;
48
import java.util.ArrayList;
49
import java.util.Collections;
50
import java.util.Date;
51
import java.util.HashMap;
52
import java.util.Iterator;
53
import java.util.List;
54
import java.util.Map;
55
import java.util.regex.Pattern;
56

    
57
import org.apache.commons.io.FilenameUtils;
58
import org.cresques.cts.IProjection;
59
import org.slf4j.Logger;
60
import org.slf4j.LoggerFactory;
61

    
62
import org.gvsig.andami.PluginServices;
63
import org.gvsig.andami.ui.mdiManager.IWindow;
64
import org.gvsig.andami.ui.mdiManager.MDIManager;
65
import org.gvsig.andami.ui.mdiManager.SingletonWindow;
66
import org.gvsig.andami.ui.mdiManager.WindowInfo;
67
import org.gvsig.app.ApplicationLocator;
68
import org.gvsig.app.ApplicationManager;
69
import org.gvsig.app.extension.ProjectExtension;
70
import org.gvsig.app.extension.Version;
71
import org.gvsig.app.project.documents.AbstractDocument;
72
import org.gvsig.app.project.documents.Document;
73
import org.gvsig.app.project.documents.exceptions.SaveException;
74
import org.gvsig.app.project.documents.gui.IDocumentWindow;
75
import org.gvsig.app.project.documents.gui.ProjectWindow;
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.tools.ToolsLocator;
83
import org.gvsig.tools.dynobject.DynField;
84
import org.gvsig.tools.dynobject.DynStruct;
85
import org.gvsig.tools.persistence.PersistenceManager;
86
import org.gvsig.tools.persistence.Persistent;
87
import org.gvsig.tools.persistence.PersistentContext;
88
import org.gvsig.tools.persistence.PersistentState;
89
import org.gvsig.tools.persistence.exception.PersistenceException;
90
import org.gvsig.utils.StringUtilities;
91

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

    
102
public class DefaultProject implements Serializable, PropertyChangeListener,
103
                Project {
104

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

    
111
        /**
112
         * 
113
         */
114
        private static final long serialVersionUID = -4449622027521773178L;
115

    
116
        private static final Logger logger = LoggerFactory.getLogger(Project.class);
117

    
118
        private static ProjectPreferences preferences = new ProjectPreferences();
119

    
120
        /**
121
         * Index used by the generator of unique names of documents.
122
         */
123
        private Map<String, Integer> nextDocumentIndexByType = new HashMap<String, Integer>();
124

    
125
        private PropertyChangeSupport change;
126

    
127
        private boolean modified = false;
128

    
129
        private String name = null;
130

    
131
        private String creationDate = null;
132

    
133
        private String modificationDate = null;
134

    
135
        private String owner = null;
136

    
137
        private String comments = null;
138

    
139
        private Color selectionColor = null;
140

    
141
        private List<Document> documents = null;
142

    
143
        private List<ProjectExtent> extents = null;
144

    
145
        private IProjection projection;
146

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

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

    
162
                this.documents = new ArrayList<Document>();
163
                this.extents = new ArrayList<ProjectExtent>();
164

    
165
                this.setSelectionColor(getPreferences().getDefaultSelectionColor());
166

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

    
170
        public static ProjectPreferences getPreferences() {
171
                return preferences;
172
        }
173

    
174
        public void propertyChange(PropertyChangeEvent evt) {
175
                change.firePropertyChange(evt);
176
        }
177

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

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

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

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

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

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

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

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

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

    
250
        protected void setModificationDate(String string) {
251
                modificationDate = string;
252
                change.firePropertyChange("setModificationDate", null, null);
253
        }
254

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

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

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

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

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

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

    
316
        public void setProjection(IProjection projection) {
317
                this.projection = projection;
318
        }
319

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

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

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

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

    
376
        /**
377
         * Adds a document to the project
378
         * 
379
         * @param document
380
         *            as IProjectDocument
381
         */
382
        public void add(Document document) {
383
        logger.info("add('{}')", document.toString());
384

    
385
                document.addPropertyChangeListener(this);
386
                document.setProject(this);
387
                document.setName(this.getUniqueNameForDocument(document.getTypeName(),
388
                                document.getName()));
389
                documents.add(document);
390
                document.afterAdd();
391
                this.setModified(true);
392
        change.firePropertyChange("addDocument", null, document);
393
        }
394

    
395
        /**
396
         * Remove a document of the project
397
         * 
398
         * @param document
399
         *            as IProjectDocument
400
         */
401
        public void remove(Document doc) {
402
        logger.info("remove('{}')", doc.toString());
403
                documents.remove(doc);
404
                this.setModified(true);
405
        change.firePropertyChange("delDocument", doc, 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 view that contains the especified layer.
419
         * 
420
         * @param layer
421
         * 
422
         * @return name of the view that contains the layer
423
         * 
424
         * @throws RuntimeException
425
         *             Si la capa que se pasa como par?metro no se encuentra en
426
         *             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
476
         *            Nombre del documento
477
         * @param type
478
         *            nombre de registro en el extensionPoint
479
         * 
480
         * @return Documento
481
         */
482
        public Document getDocument(String name, String type) {
483
                if (type != null) {
484
                        for (int i = 0; i < documents.size(); i++) {
485
                                Document document = documents.get(i);
486
                                if (type.equalsIgnoreCase(document.getTypeName())
487
                                                && name.equalsIgnoreCase(document.getName())) {
488
                                        return document;
489
                                }
490
                        }
491
                }
492
                return null;
493
        }
494

    
495
        public String getUniqueNameForDocument(String type, String name) {
496
                Document document = getDocument(name, type);
497
                if (document == null) {
498
                        return name;
499
                }
500

    
501
                String newName = null;
502
                int num = this.getNextDocumentIndex(type);
503
                while (document != null) {
504
                        newName = name + " - " + num++;
505
                        document = getDocument(newName, type);
506
                }
507
                this.setNextDocumentIndex(type, num);
508
                return newName;
509
        }
510

    
511
        private int getNextDocumentIndex(String type) {
512
                if (nextDocumentIndexByType.get(type) == null) {
513
                        nextDocumentIndexByType.put(type, new Integer(1));
514
                        return 1;
515
                }
516
                return nextDocumentIndexByType.get(type).intValue();
517
        }
518

    
519
        private void setNextDocumentIndex(String type, int newIndex) {
520
                if (nextDocumentIndexByType.get(type) == null) {
521
                        nextDocumentIndexByType.put(type, new Integer(newIndex));
522
                } else {
523
                        nextDocumentIndexByType.put(type, new Integer(newIndex));
524
                }
525
        }
526

    
527
        public void saveState(File out) throws PersistenceException {
528
                FileOutputStream fout;
529
                try {
530
                        fout = new FileOutputStream(out);
531
                        saveState(fout, new File(out.getParent()));
532
                } catch (FileNotFoundException e) {
533
                        throw new PersistenceException(e);
534
                }
535
        }
536

    
537
        public void saveState(OutputStream out) throws PersistenceException {
538
                saveState(out, null);
539
        }
540

    
541
        public void saveState(OutputStream out, File rootFolder)
542
                        throws PersistenceException {
543
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
544
                PersistentState state = null;
545
                state = manager.getState(this, true);
546
                try {
547
                        if (rootFolder != null) {
548
                                relativizeFiles(state, rootFolder);
549
                        }
550
                } catch (Exception ex) {
551
                        state.getContext().addError(ex);
552
                }
553
                manager.saveState(state, out);
554
                if (state.getContext().getErrors() != null) {
555
                        throw state.getContext().getErrors();
556
                }
557
        }
558

    
559
        private void relativizeFiles(PersistentState state, File rootFolder) {
560
                PersistentContext context = state.getContext();
561

    
562
                URI cwd = new File(System.getProperty("user.dir")).toURI();
563
                @SuppressWarnings("unchecked")
564
                Iterator<PersistentState> statesIterator = context.iterator();
565
                while (statesIterator.hasNext()) {
566
                        PersistentState aState = statesIterator.next();
567
                        DynStruct definition = aState.getDefinition();
568
                        DynField[] fields = definition.getDynFields();
569
                        for (DynField field : fields) {
570
                                if (field.getType() == DataTypes.FILE
571
                                                || field.getType() == DataTypes.FOLDER) {
572
                                        try {
573
                                                File value = aState.getFile(field.getName());
574
                                                value = relativizeFile(value, rootFolder);
575
                                                aState.set(field.getName(), value);
576
                                        } catch (PersistenceException e) {
577
                                                LOG.warn(
578
                                                                "Can't relativice field '" + field.getName()
579
                                                                                + "' for class '"
580
                                                                                + definition.getName() + "'.", e);
581
                                        }
582
                                } else if (field.getType() == DataTypes.URL) {
583
                                        try {
584
                                                URL value = aState.getURL(field.getName());
585
                                                if ("FILE".equalsIgnoreCase(value.getProtocol())) {
586
                                                        File file = new File(value.toURI());
587
                                                        if (differentDrives(file, rootFolder)) {
588
                                /*
589
                                 * Different drives
590
                                 * (should happen only in Windows)
591
                                 */
592
                                value = file.toURI().toURL();
593
                                                        } else {
594
                                /*
595
                                * Both in the Same drive (C: D: etc) or Unix-style
596
                                */
597
                                file = relativizeFile(file, rootFolder);
598
                                value = new URL("file","",file.toURI().toString().substring(cwd.toString().length()));
599
                                                        }
600
                                                        aState.set(field.getName(), value);
601
                                                }
602
                                        } catch (PersistenceException e) {
603
                                                // do nothind
604
                                        } catch (MalformedURLException e) {
605
                                                // do nothind
606
                                        } catch (URISyntaxException e) {
607
                                                // do nothind
608
                                        }
609
                                } else if (field.getType() == DataTypes.URI) {
610
                                        try {
611
                                                URI value = aState.getURI(field.getName());
612
                                                if (value.getScheme() == null || "FILE".equalsIgnoreCase(value.getScheme())) {
613
                                                        File file = new File(value.getPath());
614
                                                        if (differentDrives(file, rootFolder)) {
615
                                /*
616
                                 * Different drives
617
                                 * (should happen only in Windows)
618
                                 */
619
                                value = file.toURI();
620
                                                        } else {
621
                                /*
622
                                * Both in the Same drive (C: D: etc) or Unix-style
623
                                */
624
                                file = relativizeFile(file, rootFolder);
625
                                value = new URI(file.getPath());
626
                                                        }
627
                                                        aState.set(field.getName(), value);
628
                                                }
629
                                        } catch (PersistenceException e) {
630
                                                // do nothind
631
                                        } catch (URISyntaxException e) {
632
                                                // do nothind
633
                                        }
634
                                }
635
                        }
636
                }
637
        }
638

    
639
    private boolean differentDrives(File file, File rootFolder) {
640

    
641
        if (rootFolder == null) {
642
            return false;
643
        }
644

    
645
        if (file == null) {
646
            return false;
647
        }
648
        String basePath = rootFolder.getAbsolutePath();
649
        String targetPath = file.getPath();
650
        String pathSeparator = File.separator;
651
        // We need the -1 argument to split to make sure we get a trailing
652
        // "" token if the base ends in the path separator and is therefore
653
        // a directory. We require directory paths to end in the path
654
        // separator -- otherwise they are indistinguishable from files.
655
        String[] base = basePath.split(Pattern.quote(pathSeparator), -1);
656
        String[] target = targetPath.split(Pattern.quote(pathSeparator), 0);
657
        /*
658
         * If first component is different then they are different
659
         * drives. In Unix-type file systems, the first for both
660
         * should be "" so this will not happen
661
         */
662
        return !target[0].equals(base[0]);
663
    }
664
        
665
        private File relativizeFile(File file, File rootFolder) {
666
                if (rootFolder == null) {
667
                        return file;
668
                }
669
                if (file == null) {
670
                        return null;
671
                }
672
                
673
                boolean isDir = false;
674
                // isDir = file.isDirectory();
675
                isDir = rootFolder.isDirectory();
676
                String basePath = rootFolder.getAbsolutePath();
677
                
678
                String targetPath = FilenameUtils.normalize(file.getPath());
679
                
680
                String pathSeparator = File.separator;
681
                // We need the -1 argument to split to make sure we get a trailing
682
                // "" token if the base ends in the path separator and is therefore
683
                // a directory. We require directory paths to end in the path
684
                // separator -- otherwise they are indistinguishable from files.
685
                String[] base = basePath.split(Pattern.quote(pathSeparator), -1);
686
                String[] target = targetPath.split(Pattern.quote(pathSeparator), 0);
687

    
688
                // First get all the common elements. Store them as a string,
689
                // and also count how many of them there are.
690
                String common = "";
691
                int commonIndex = 0;
692
                for (int i = 0; i < target.length && i < base.length; i++) {
693
                        if (target[i].equals(base[i])) {
694
                                common += target[i] + pathSeparator;
695
                                commonIndex++;
696
                        } else
697
                                break;
698
                }
699

    
700
                if (commonIndex == 0) {
701
                        // Whoops -- not even a single common path element. This most
702
                        // likely indicates differing drive letters, like C: and D:.
703
                        // These paths cannot be relativized. Return the target path.
704
                        return file;
705
                        // This should never happen when all absolute paths
706
                        // begin with / as in *nix.
707
                }
708

    
709
                String relative = "";
710
                if (base.length == commonIndex) {
711
                        // Comment this out if you prefer that a relative path not start
712
                        // with ./
713
                        relative = "." + pathSeparator;
714
                } else {
715
                        int numDirsUp = base.length - commonIndex - (isDir ? 0 : 1); /*
716
                                                                                                                                                 * only
717
                                                                                                                                                 * subtract
718
                                                                                                                                                 * 1 if
719
                                                                                                                                                 * it is
720
                                                                                                                                                 * a
721
                                                                                                                                                 * file.
722
                                                                                                                                                 */
723
                        // The number of directories we have to backtrack is the length of
724
                        // the base path MINUS the number of common path elements, minus
725
                        // one because the last element in the path isn't a directory.
726
                        for (int i = 1; i <= (numDirsUp); i++) {
727
                                relative += ".." + pathSeparator;
728
                        }
729
                }
730
                // if we are comparing directories then we
731
                if (targetPath.length() > common.length()) {
732
                        // it's OK, it isn't a directory
733
                        relative += targetPath.substring(common.length());
734
                }
735

    
736
                return new File(relative);
737
        }
738

    
739
        private void fixFiles(PersistentState state, File rootFolder) {
740
                PersistentContext context = state.getContext();
741
                URI cwd = new File(System.getProperty("user.dir")).toURI();
742

    
743
                @SuppressWarnings("unchecked")
744
                Iterator<PersistentState> statesIterator = context.iterator();
745
                String className = null;
746
                
747
                while (statesIterator.hasNext()) {
748
                        PersistentState aState = statesIterator.next();
749
                        try {
750
                                className = aState.getTheClassName();
751
                        } catch (Throwable e) {
752
                                className = "Unknown";
753
                        }
754
                        try {
755
                                DynStruct definition = aState.getDefinition();
756
                                DynField[] fields = definition.getDynFields();
757
                                for (DynField field : fields) {
758
                                        if (field.getType() == DataTypes.FILE
759
                                                        || field.getType() == DataTypes.FOLDER) {
760
                                                try {
761
                                                        File value = aState.getFile(field.getName());
762
                                                        value = fixFile(value, rootFolder);
763
                                                        aState.set(field.getName(), value);
764
                                                } catch (PersistenceException e) {
765
                                                        LOG.warn(
766
                                                                        "Can't fix field '" + field.getName()
767
                                                                        + "' for class '"
768
                                                                        + definition.getName() + "'.", e);
769
                                                }
770
                                        } else if (field.getType() == DataTypes.URL) {
771
                                                try {
772
                                                        URL value = aState.getURL(field.getName());
773
                                                        if ("FILE".equalsIgnoreCase(value.getProtocol())) {
774
                                                                if (!value.getFile().startsWith("/")){
775
                                                                        value = new URL("file","",cwd.getRawPath()+value.getFile());
776
                                                                        File file = new File(value.toURI().getPath().substring(cwd.getPath().length()));
777
                                                                        file = fixFile(file, rootFolder);
778
                                                                        aState.set(field.getName(), file.toURI().toURL());
779
                                                                }
780
                                                        }
781
                                                } catch (PersistenceException e) {
782
                                                        // do nothing
783
                                                } catch (MalformedURLException e) {
784
                                                        // do nothing
785
                                                } catch (URISyntaxException e) {
786
                                                        // do nothing
787
                                                }
788

    
789
                                        } else if (field.getType() == DataTypes.URI) {
790
                                                try {
791
                                                        URI value = aState.getURI(field.getName());
792
                                                        if (value.getScheme() == null || "FILE".equalsIgnoreCase(value.getScheme())) {
793
                                                                if (!value.getPath().startsWith("/")){
794
                                                                        File file = new File(value.getPath());
795
                                                                        file = fixFile(file, rootFolder);
796
                                                                        aState.set(field.getName(), file.toURI());
797
                                                                }
798
                                                        }
799
                                                } catch (PersistenceException e) {
800
                                                        // do nothing
801
                                                } 
802
                                        }
803
                                }
804
                        }catch (RuntimeException e) {
805
                                logger.info("Can't fix relative paths in " + className, e);
806
                        }
807
                }
808
        }
809

    
810
        private File fixFile(File file, File rootFolder) {
811
                if (file.isAbsolute()) {
812
                        return file;
813
                }
814
                File f = new File(rootFolder, file.getPath()).getAbsoluteFile();
815
                String targetPath = FilenameUtils.normalize(f.getPath());
816
                return new File(targetPath);
817
        }
818

    
819
        public void loadState(InputStream in) {
820
                loadState(in, null);
821
        }
822

    
823
        public void loadState(InputStream in, File rootFolder) {
824
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
825
                try {
826
                        PersistentState state = manager.loadState(in);
827
                        try {
828
                                if (rootFolder != null) {
829
                                        fixFiles(state, rootFolder);
830
                                }
831
                        } catch (Exception ex) {
832
                                state.getContext().addError(ex);
833
                        }
834
                        this.loadFromState(state);
835
                } catch (PersistenceException e) {
836
                        // TODO Auto-generated catch block
837
                        e.printStackTrace();
838
                }
839

    
840
        }
841

    
842
        public void loadState(File in) {
843
                FileInputStream fin;
844
                try {
845
                        fin = new FileInputStream(in);
846
                        loadState(fin, new File(in.getParent()));
847
                } catch (FileNotFoundException e) {
848
                        // TODO Auto-generated catch block
849
                        e.printStackTrace();
850
                }
851
        }
852

    
853
        @SuppressWarnings("unchecked")
854
        public void loadFromState(PersistentState state)
855
                        throws PersistenceException {
856
                this.clean();
857

    
858
                this.setComments(state.getString("comments"));
859
                this.setCreationDate(state.getString("creationDate"));
860
                this.setModificationDate(state.getString("modificationDate"));
861
                this.setName(state.getString("name"));
862
                this.setOwner(state.getString("owner"));
863
                this.setSelectionColor((Color) state.get("selectionColor"));
864
                this.setProjection((IProjection) state.get("projection"));
865

    
866
                List<ProjectExtent> extents = (List<ProjectExtent>) state
867
                                .get("extents");
868
                for (int i = 0; i < extents.size(); i++) {
869
                        this.addExtent(extents.get(i));
870
                }
871

    
872
                List<AbstractDocument> documents = (List<AbstractDocument>) state
873
                                .get("documents");
874
                for (int i = 0; i < documents.size(); i++) {
875
                        this.add(documents.get(i));
876
                }
877

    
878
                List<DocumentWindowInfo> persistentWindows = (List<DocumentWindowInfo>) state.get("documentWindowsInformation");
879
                                
880
                for (int i = 0; i < persistentWindows.size(); i++) {
881
                        DocumentWindowInfo persistentWindow = persistentWindows.get(i);
882
                        String docName = persistentWindow.getDocumentName();
883
                        String docType = persistentWindow.getDocumentType();
884
                        Document doc = this.getDocument(docName, docType);
885
                        IWindow win = doc.getFactory().getMainWindow(doc);
886
                        win.getWindowInfo().setWindowInfo(persistentWindow.getWindowInfo());
887
                        PluginServices.getMDIManager().addWindow(win);
888
                }
889
                
890
                if (state.hasValue("projectWindowInfo")){
891
                        WindowInfo projectWindowInfo = (WindowInfo)state.get("projectWindowInfo"); 
892
                        ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(org.gvsig.app.extension.ProjectExtension.class);
893
                        pe.setProject(this);
894
                        pe.showProjectWindow(projectWindowInfo);
895
                }
896

    
897
        }
898

    
899
        public void saveToState(PersistentState state) throws PersistenceException {
900
                state.set("version", VERSION);
901
                state.set("comments", getComments());
902
                state.set("creationDate", this.getCreationDate());
903

    
904
                state.set("modificationDate", this.getModificationDate());
905
                state.set("name", this.getName());
906
                state.set("owner", this.getOwner());
907
                state.set("selectionColor", this.getSelectionColor());
908

    
909
                state.set("projection", this.getProjection());
910

    
911
                state.set("extents", this.extents);
912
                state.set("documents", this.getDocuments());
913

    
914
                List<DocumentWindowInfo> persistentWindows = new ArrayList<DocumentWindowInfo>();
915
                MDIManager mdiMan = PluginServices.getMDIManager();
916
                IWindow[] windows = mdiMan.getOrderedWindows();
917
                for (int i = windows.length - 1; i >= 0; i--) {
918
                        IWindow window = windows[i];
919
                        if (window instanceof IDocumentWindow){
920
                                WindowInfo wi =  mdiMan.getWindowInfo(window);
921
                                DocumentWindowInfo dwi = new DocumentWindowInfo(
922
                                                wi,
923
                                                ((IDocumentWindow) window).getDocument().getTypeName(),
924
                                                ((IDocumentWindow) window).getDocument().getName());
925
                                persistentWindows.add(dwi);
926
                        } else if (window instanceof ProjectWindow){
927
                                state.set("projectWindowInfo", mdiMan.getWindowInfo(window));
928
                        }
929
                }
930
                state.set("documentWindowsInformation", persistentWindows);
931

    
932
        }
933

    
934
        public static class DocumentWindowInfo implements Persistent {
935

    
936
                public static final String PERSISTENCE_DEFINITION_NAME = "DocumentWindowInfo";
937

    
938
                private WindowInfo windowInfo;
939
                private String documentType;
940
                private String documentName;
941

    
942
                public DocumentWindowInfo(){
943
                }
944
                
945
                DocumentWindowInfo(WindowInfo wi, String docType, String docName){
946
                        windowInfo = wi;
947
                        documentType = docType;
948
                        documentName = docName;
949
                }
950

    
951
                public WindowInfo getWindowInfo() {
952
                        return windowInfo;
953
                }
954
                
955
                public String getDocumentType() {
956
                        return documentType;
957
                }
958

    
959
                public String getDocumentName() {
960
                        return documentName;
961
                }
962

    
963
                public void saveToState(PersistentState state)
964
                                throws PersistenceException {
965
                        state.set("windowInfo", this.windowInfo);
966
                        state.set("documentType", this.documentType);
967
                        state.set("documentName", this.documentName);
968
                }
969

    
970
                public void loadFromState(PersistentState state)
971
                                throws PersistenceException {
972
                        this.windowInfo = (WindowInfo) state.get("windowInfo");
973
                        this.documentType = state.getString("documentType");
974
                        this.documentName = state.getString("documentName");
975
                }
976
                
977
                public static void registerPersistent() {
978
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
979
                        DynStruct definition = manager.getDefinition(PERSISTENCE_DEFINITION_NAME);
980
                        if ( definition == null ){
981
                                definition = manager.addDefinition(
982
                                                DocumentWindowInfo.class,
983
                                                PERSISTENCE_DEFINITION_NAME,
984
                                                "DocumentWindowInfo persistence definition",
985
                                                null, 
986
                                                null
987
                                );
988
                                definition.addDynFieldObject("windowInfo").setMandatory(true).setClassOfValue(WindowInfo.class);
989
                                definition.addDynFieldString("documentType").setMandatory(true);
990
                                definition.addDynFieldString("documentName").setMandatory(true);
991
                        }
992

    
993
                }
994
        }
995
        
996
        public static void registerPersistent() {
997
                AbstractDocument.registerPersistent();
998
                DocumentWindowInfo.registerPersistent();
999
                ProjectExtent.registerPersistent();
1000

    
1001
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
1002
                DynStruct definition = manager.addDefinition(DefaultProject.class,
1003
                                "Project", "Project Persistence definition", null, null);
1004
                definition.addDynFieldString("version").setMandatory(true);
1005
                definition.addDynFieldString("comments").setMandatory(true);
1006
                definition.addDynFieldString("creationDate").setMandatory(true);
1007
                definition.addDynFieldString("modificationDate").setMandatory(true);
1008
                definition.addDynFieldString("name").setMandatory(true);
1009
                definition.addDynFieldString("owner").setMandatory(true);
1010

    
1011
                definition.addDynFieldObject("selectionColor")
1012
                                .setClassOfValue(Color.class).setMandatory(true);
1013
                definition.addDynFieldObject("projection")
1014
                                .setClassOfValue(IProjection.class).setMandatory(true);
1015

    
1016
                definition.addDynFieldList("extents")
1017
                                .setClassOfItems(ProjectExtent.class).setMandatory(true);
1018

    
1019
                definition.addDynFieldList("documents").setClassOfItems(Document.class)
1020
                                .setMandatory(true);
1021

    
1022
                definition.addDynFieldObject("projectWindowInfo").setClassOfValue(WindowInfo.class).setMandatory(false);
1023

    
1024
                definition.addDynFieldList("documentWindowsInformation").setClassOfItems(WindowInfo.class).setMandatory(false);
1025

    
1026
        }
1027

    
1028
        /**
1029
         * @deprecated use getPreferences().setDefaultSelectionColor()
1030
         */
1031
        public static void setDefaultSelectionColor(Color color) {
1032
                getPreferences().setDefaultSelectionColor(color);
1033
        }
1034

    
1035
        /**
1036
         * @deprecated use getPreferences().getDefaultSelectionColor()
1037
         */
1038

    
1039
        public static Color getDefaultSelectionColor() {
1040
                return getPreferences().getDefaultSelectionColor();
1041
        }
1042

    
1043
        /**
1044
         * @deprecated use getPreferences().getDefaultMapUnits()
1045
         */
1046
        public static int getDefaultMapUnits() {
1047
                return getPreferences().getDefaultMapUnits();
1048
        }
1049

    
1050
        /**
1051
         * @deprecated use getPreferences().getDefaultDistanceUnits()
1052
         */
1053
        public static int getDefaultDistanceUnits() {
1054
                return getPreferences().getDefaultDistanceUnits();
1055
        }
1056

    
1057
        /**
1058
         * @deprecated use getPreferences().getDefaultDistanceArea()
1059
         */
1060
        public static int getDefaultDistanceArea() {
1061
                return getPreferences().getDefaultDistanceArea();
1062
        }
1063

    
1064
        /**
1065
         * @deprecated use getPreferences().setDefaultMapUnits()
1066
         */
1067
        public static void setDefaultMapUnits(int mapUnits) {
1068
                getPreferences().setDefaultMapUnits(mapUnits);
1069
        }
1070

    
1071
        /**
1072
         * @deprecated use getPreferences().setDefaultDistanceUnits()
1073
         */
1074
        public static void setDefaultDistanceUnits(int distanceUnits) {
1075
                getPreferences().setDefaultDistanceUnits(distanceUnits);
1076
        }
1077

    
1078
        /**
1079
         * @deprecated use getPreferences().setDefaultDistanceArea()
1080
         */
1081
        public static void setDefaultDistanceArea(int distanceArea) {
1082
                getPreferences().setDefaultDistanceArea(distanceArea);
1083
        }
1084

    
1085
        /**
1086
         * @deprecated use getPreferences().setDefaultProjection()
1087
         */
1088
        public static void setDefaultProjection(IProjection defaultProjection) {
1089
                getPreferences().setDefaultProjection(defaultProjection);
1090
        }
1091

    
1092
        /**
1093
         * @deprecated use getPreferences().getDefaultProjection()
1094
         */
1095
        public static IProjection getDefaultProjection() {
1096
                return getPreferences().getDefaultProjection();
1097
        }
1098

    
1099
        /**
1100
         * @deprecated see {@link #setSelectionColor(String)}, to be remove in gvSIG
1101
         *             2.1.0
1102
         */
1103
        public void setColor(String color) {
1104
                this.setSelectionColor(StringUtilities.string2Color(color));
1105
        }
1106

    
1107
        /**
1108
         * Return the selection color
1109
         * 
1110
         * @return selection color as string
1111
         * @deprecated use {@link #getSelectionColor()}
1112
         */
1113
        public String getColor() {
1114
                return StringUtilities.color2String(selectionColor);
1115
        }
1116

    
1117
        /**
1118
         * Return the list of views of the project
1119
         * 
1120
         * @return views as ArrayList of ProjectDocument
1121
         * 
1122
         * @deprecated see {@link #getDocumentsByType(String)}
1123
         */
1124
        public List<Document> getViews() {
1125
                return getDocuments(ViewManager.TYPENAME);
1126
        }
1127

    
1128
        /**
1129
         * Add a view to the project
1130
         * 
1131
         * @deprecated see {@link #add(AbstractDocument)}
1132
         */
1133
        public void addView(DefaultViewDocument v) {
1134
                add(v);
1135
        }
1136

    
1137
        /**
1138
         * Remove a view of the project
1139
         * 
1140
         * @param index
1141
         *            of the view as integer
1142
         * 
1143
         * @deprecated see {@link #remove(AbstractDocument)}
1144
         */
1145
        public void delView(int i) {
1146
                List<Document> list = getDocuments(ViewManager.TYPENAME);
1147
                remove(list.get(i));
1148
        }
1149

    
1150
        /**
1151
         * @deprecated see {@link #getDocument(String, String)}
1152
         */
1153
        public Document getProjectDocumentByName(String name, String type) {
1154
                return this.getDocument(name, type);
1155
        }
1156

    
1157
        /**
1158
         * @deprecated see {@link #getDocuments(String)}
1159
         */
1160
        public List<Document> getDocumentsByType(String type) {
1161
                return this.getDocuments(type);
1162
        }
1163

    
1164
        /**
1165
         * @deprecated aun por decidir que API darle al copy/paste
1166
         */
1167
        public String exportToXML(AbstractDocument[] selectedItems)
1168
                        throws SaveException {
1169
                // FIXME jjdc:hay que decirdir que API darle al copy/paste
1170
                throw new UnsupportedOperationException("This method is not supported");
1171
        }
1172

    
1173
        /**
1174
         * @deprecated aun por decidir que API darle al copy/paste
1175
         */
1176
        public void importFromXML(String sourceString, String docType) {
1177
                // FIXME jjdc:hay que decirdir que API darle al copy/paste
1178
                throw new UnsupportedOperationException("This method is not supported");
1179
        }
1180

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

    
1189
        public boolean canImportDocuments(String data, String doctype) {
1190
                // TODO Auto-generated method stub
1191
                return false;
1192
        }
1193

    
1194
        public String exportDocumentsAsText(List<Document> documents) {
1195
                // TODO Auto-generated method stub
1196
                return null;
1197
        }
1198

    
1199
        public void importDocuments(String data, String doctype) {
1200
                // TODO Auto-generated method stub
1201

    
1202
        }
1203

    
1204
        public Document getActiveDocument() {
1205
                ApplicationManager application = ApplicationLocator.getManager();
1206

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