Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.swing / org.gvsig.symbology.swing.api / src / main / java / org / gvsig / app / gui / styling / SymbolLibrary.java @ 40560

History | View | Annotate | Download (18.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.app.gui.styling;
25

    
26
import java.awt.Component;
27
import java.io.File;
28
import java.io.FileFilter;
29
import java.io.IOException;
30
import java.net.URI;
31
import java.net.URL;
32
import java.util.ArrayList;
33
import java.util.Arrays;
34
import java.util.Comparator;
35
import java.util.ConcurrentModificationException;
36
import java.util.HashMap;
37
import java.util.Iterator;
38
import java.util.List;
39
import java.util.Map;
40
import java.util.Vector;
41

    
42
import javax.swing.JOptionPane;
43
import javax.swing.event.TreeModelEvent;
44
import javax.swing.event.TreeModelListener;
45
import javax.swing.tree.DefaultMutableTreeNode;
46
import javax.swing.tree.DefaultTreeModel;
47
import javax.swing.tree.TreePath;
48

    
49
import org.apache.commons.io.FileUtils;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

    
53
import org.gvsig.andami.PluginServices;
54
import org.gvsig.andami.messages.NotificationManager;
55
import org.gvsig.fmap.mapcontext.MapContextLocator;
56
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
57
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
58
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
59
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolPreferences;
60
import org.gvsig.i18n.Messages;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.dataTypes.DataTypes;
63
import org.gvsig.tools.dynobject.DynField;
64
import org.gvsig.tools.dynobject.DynStruct;
65
import org.gvsig.tools.persistence.PersistenceManager;
66
import org.gvsig.tools.persistence.PersistentContext;
67
import org.gvsig.tools.persistence.PersistentState;
68
import org.gvsig.tools.persistence.spi.PersistentContextServices;
69

    
70
/**
71
 * 
72
 * SymbolLibrary.java
73
 * 
74
 * 
75
 * @author jaume dominguez faus - jaume.dominguez@iver.es Dec 7, 2007
76
 * 
77
 */
78
public class SymbolLibrary extends DefaultTreeModel implements ILibraryModel {
79
    
80
    private static Logger logger =
81
        LoggerFactory.getLogger(SymbolLibrary.class);
82
        /**
83
         * 
84
         */
85
        private static final long serialVersionUID = 6802576248214649793L;
86
        static protected String rootDirString;
87
        private File rootDir;
88
        private Vector<TreeModelListener> listeners = new Vector<TreeModelListener>();
89
        private static SymbolLibrary instance = null;
90
        private SymbolManager manager;
91

    
92
        public static SymbolLibrary getInstance() {
93
                SymbolPreferences preferences = getPreferences();
94
                if (instance == null
95
                                || !preferences.getSymbolLibraryPath().equals(rootDirString)) {
96
                        rootDirString = preferences.getSymbolLibraryPath();
97
                        instance = new SymbolLibrary(new File(rootDirString));
98
                }
99
                return instance;
100
        }
101

    
102
        private static SymbolPreferences getPreferences() {
103
                return MapContextLocator.getSymbolManager().getSymbolPreferences();
104
        }
105

    
106
        protected SymbolLibrary(File rootDir) {
107
                super(new DefaultMutableTreeNode(rootDir));
108
                rootDirString = Messages.getText("symbol_library");
109
                this.rootDir = rootDir;
110
                manager = MapContextLocator.getSymbolManager();
111
        }
112

    
113
        final class MyFile extends File {
114
                private static final long serialVersionUID = 6332989815291224773L;
115

    
116
                public MyFile(String pathname) {
117
                        super(pathname);
118
                }
119

    
120
                public String toString() {
121

    
122
                        String path = getAbsolutePath();
123
                        if (path.equals(rootDir.getAbsolutePath()))
124
                                return rootDirString;
125
                        return path.substring(path.lastIndexOf(File.separator) + 1, path
126
                                        .length());
127
                }
128
        };
129

    
130
        private FileFilter ff = new FileFilter() {
131
                public boolean accept(File pathname) {
132
                        return pathname.isDirectory();
133
                }
134
        };
135

    
136
        @Override
137
        public Object getRoot() {
138
                return new DefaultMutableTreeNode(new MyFile(rootDir.getAbsolutePath()));
139
        }
140

    
141
        private File[] listFiles(File f, FileFilter ff) {
142
                File[] files = null;
143
                if( ff == null ) {
144
                        files = f.listFiles();
145
                } else {
146
                        files = f.listFiles(ff);
147
                }
148
                if (files != null) {
149
                        Arrays.sort(files, new Comparator<File>() {
150
                                public int compare(File o1, File o2) {
151
                                        return o1.getName().compareTo(o2.getName());
152
                                }
153
                        });
154
                }
155
                return files;
156
        }
157
        
158
        private File[] listFiles(File f) {
159
                return listFiles(f,null);
160
        }
161
        
162
        private int countFiles(File f, FileFilter ff) {
163
                // No precisa ordenarlos para saber cuantos hay
164
                File[] files = f.listFiles(ff);
165
                return files == null ? 0 : files.length;
166
        }
167
        
168
        @Override
169
        public int getChildCount(Object parent) {
170
                File f = null;
171
                if (parent instanceof DefaultMutableTreeNode) {
172
                        f = (File) ((DefaultMutableTreeNode) parent).getUserObject();
173

    
174
                } else {
175
                        f = (File) parent;
176
                }
177
                return countFiles(f,ff);
178
        }
179

    
180
        @Override
181
        public boolean isLeaf(Object node) {
182
                return getChildCount(node) == 0;
183
        }
184

    
185
        @Override
186
        public void addTreeModelListener(TreeModelListener l) {
187
                listeners.add(l);
188
        }
189

    
190
        @Override
191
        public void removeTreeModelListener(TreeModelListener l) {
192
                listeners.remove(l);
193
        }
194

    
195
        @Override
196
        public void valueForPathChanged(TreePath path, Object newValue) {
197
        }
198

    
199
        @Override
200
        public Object getChild(Object parent, int index) {
201
                File file = listFiles((File) (((DefaultMutableTreeNode) parent).getUserObject()),ff)[index];
202
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(new MyFile(
203
                                file.getAbsolutePath()));
204
                node.setParent((DefaultMutableTreeNode) parent);
205
                return node;
206
        }
207

    
208
        @Override
209
        public int getIndexOfChild(Object parent, Object child) {
210
                if (parent == null)
211
                        return -1;
212
                File[] files = listFiles((File) ((DefaultMutableTreeNode) parent).getUserObject(),ff);
213
                for (int i = 0; i < files.length; i++) {
214
                        if (files[i].equals(child))
215
                                return i;
216
                }
217
                return -1;
218
        }
219

    
220
        private Object getChildFile(Object parent, int index) {
221
                File file = listFiles((File) (((DefaultMutableTreeNode) parent).getUserObject()))[index];
222
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(new MyFile(
223
                                file.getAbsolutePath()));
224
                node.setParent((DefaultMutableTreeNode) parent);
225
                return node;
226
        }
227

    
228
        private int getIndexOfChildFiles(Object parent, Object child) {
229
                if (parent == null)
230
                        return -1;
231
                File[] files = listFiles((File) ((DefaultMutableTreeNode) parent).getUserObject());
232
                for (int i = 0; files != null && i < files.length; i++) {
233
                        if (files[i].getName().equals(child))
234
                                return i;
235
                }
236
                return -1;
237
        }
238

    
239
        public Object getElement(Object containerFolder, String elementName) {
240
                if (containerFolder instanceof File) {
241
                        containerFolder = new DefaultMutableTreeNode(containerFolder);
242
                }
243
                int index = getIndexOfChildFiles(containerFolder, elementName);
244
                if (index != -1) {
245
                        return getChildFile(containerFolder, index);
246
                } else {
247
                        for (int i = 0; i < getChildCount(containerFolder); i++) {
248
                                Object o = getElement(getChildFile(containerFolder, i),
249
                                                elementName);
250
                                if (o != null) {
251
                                        return o;
252
                                }
253
                        }
254
                }
255
                return null;
256
        }
257

    
258
        public void addElement(Object element, String elementName,
259
                        Object containerFolder) {
260
                if (element instanceof ISymbol) {
261
                        ISymbol sym = (ISymbol) element;
262
                        File folder = containerFolder == null ? rootDir
263
                                        : (File) containerFolder;
264

    
265
                        // copy files and update fields
266
                        try {
267
                            sym = (ISymbol) copyFilesToFolder(
268
                                sym, folder, new HashMap());
269
                        } catch (Exception exc) {
270
                            logger.info("Error while copying symbol files.", exc);
271
                            return;
272
                        }
273

    
274
                        String fExtension = getPreferences().getSymbolFileExtension();
275
                        if (!elementName.toLowerCase().endsWith(fExtension)) {
276
                                elementName = elementName.concat(fExtension);
277
                        }
278

    
279
                        File targetFile = new File(folder, elementName);
280
                        if (targetFile.exists()) {
281
                                int resp = JOptionPane.showConfirmDialog(
282
                                                (Component) PluginServices.getMainFrame(),
283
                                                Messages.getText(
284
                                                                "fichero_ya_existe_seguro_desea_guardarlo"),
285
                                                Messages.getText("guardar"),
286
                                                JOptionPane.YES_NO_OPTION);
287
                                if (resp != JOptionPane.YES_OPTION) {
288
                                        return;
289
                                }
290
                        }
291

    
292
                        try {
293
                                MapContextLocator.getSymbolManager().saveSymbol(sym,
294
                                                elementName, folder, true);
295
                        } catch (SymbolException e) {
296
                                NotificationManager.addError(Messages.getText(
297
                                                "save_error"), e);
298
                        }
299
                } else {
300
                        throw new IllegalArgumentException(Messages.getText(
301
                                        "adding_a_non_symbol_as_element"));
302
                }
303
        }
304

    
305
        public void addFolder(Object parentFolder, String folderName) {
306
                if (parentFolder == null) {
307
                        parentFolder = rootDir;
308
                }
309
                try {
310
                        File fParentFolder = (File) ((DefaultMutableTreeNode) parentFolder)
311
                                        .getUserObject();
312
                        File f = new File(fParentFolder.getAbsolutePath() + File.separator
313
                                        + folderName);
314
                        if (!f.exists())
315
                                f.mkdir();
316
                        for (int i = 0; i < listeners.size(); i++) {
317
                                listeners.get(i).treeNodesInserted(null);
318
                        }
319
                } catch (ConcurrentModificationException cme) {
320
                        cme.printStackTrace();
321
                } catch (Exception e) {
322
                        throw new IllegalArgumentException(Messages.getText(
323
                                        "invalid_folder_name"), e);
324
                }
325
        }
326

    
327
        public void removeElement(Object element, Object containerFolder) {
328
                try {
329
                        File fParentFolder = (File) containerFolder;
330
                        File f = new File(fParentFolder.getAbsolutePath() + File.separator
331
                                        + (String) element);
332
                        if (f.exists())
333
                                deleteRecursively(f);
334

    
335
                } catch (Exception e) {
336
                        throw new IllegalArgumentException(Messages.getText(
337
                                        "invalid_folder_name"));
338
                }
339
        }
340

    
341
        private void deleteRecursively(File f) {
342
                if (f.isDirectory()) {
343
                        FileUtils.deleteQuietly(f);
344
                }
345
                f.delete();
346
        }
347

    
348
        public void removeFolder(Object folderToRemove) {
349
                try {
350
                        File f = (File) folderToRemove;
351

    
352
                        TreePath tp = treePathNode(f, rootDir);
353
                        if (f.exists())
354
                                f.delete();
355
                } catch (Exception e) {
356
                        throw new IllegalArgumentException(Messages.getText(
357
                                        "invalid_folder_name"));
358
                }
359
        }
360

    
361
        private TreePath treePathNode(File f, File startingNode) {
362
                for (int i = 0; i < getChildCount(startingNode); i++) {
363
                        File child = (File) getChild(startingNode, i);
364
                        TreePath tp = treePathNode(f, child);
365
                        if (tp == null) {
366
                                // it is not in this directory tree
367
                                continue;
368
                        } else {
369
                                if (startingNode != rootDir)
370
                                        tp = tp.pathByAddingChild(startingNode);
371
                                return tp;
372
                        }
373
                }
374

    
375
                if (f.equals(startingNode)) {
376
                        return new TreePath(f);
377
                }
378
                return null;
379
        }
380

    
381
        private void fireTreeNodesRemoved(TreePath removedObjectTreePath) {
382
                TreeModelEvent e = new TreeModelEvent(this, removedObjectTreePath);
383
                for (Iterator<TreeModelListener> iterator = listeners.iterator(); iterator
384
                                .hasNext();) {
385
                        iterator.next().treeNodesRemoved(e);
386
                }
387
        }
388
        
389
        
390
    private static Object copyFilesToFolder(
391
        Object sym,
392
        File theFolder,
393
        Map processedFilesMap
394
        // Set processedObjSet,
395
        /*int dep*/) throws Exception {
396
        
397
        PersistenceManager manager =
398
            ToolsLocator.getPersistenceManager();
399
        PersistentState state = null;
400
        state = manager.getState(sym, true);
401
        PersistentContext context = state.getContext();
402
        
403
        List<PersistentState> states_list = getList(context);
404
        int len = states_list.size();
405

    
406
        for (int i=0; i<len; i++) {
407
            
408
            PersistentState aState = states_list.get(i);
409
            DynStruct definition = aState.getDefinition();
410
            DynField[] fields = definition.getDynFields();
411
            
412
            File value_file = null;
413
            File value_file_new = null;
414
            URL value_url = null;
415
            URI value_uri = null;
416
            File donefile = null;
417
            Object value_obj = null;
418
            Object value_obj_new = null;
419
            
420
            for (DynField field : fields) {
421
                if (field.getType() == DataTypes.FILE) {
422
                    
423
                    value_file = aState.getFile(field.getName());
424
                    
425
                    donefile = (File) processedFilesMap.get(value_file);
426
                    if (donefile == null) {
427
                        /*
428
                         * It was NOT processed before
429
                         */
430
                        value_file_new = copyFile(value_file, theFolder);
431
                        aState.set(field.getName(), value_file_new);
432
                        processedFilesMap.put(value_file, value_file_new);
433
                    } else {
434
                        /*
435
                         * It was processed before
436
                         */
437
                        aState.set(field.getName(), donefile);
438
                    }
439
                    
440
                    
441
                } else if (field.getType() == DataTypes.URL) {
442
                    
443
                    value_url = aState.getURL(field.getName());
444
                    if ("FILE".equalsIgnoreCase(value_url.getProtocol())) {
445
                        
446
                        File urlfile = new File(value_url.getFile());
447
                        donefile = (File) processedFilesMap.get(urlfile);
448
                        if (donefile == null) {
449
                            value_file_new = copyFile(urlfile, theFolder);
450
                            value_url = value_file_new.toURI().toURL();
451
                            aState.set(field.getName(), value_url);
452
                            processedFilesMap.put(urlfile, value_file_new);
453
                        } else {
454
                            value_url = donefile.toURI().toURL();
455
                            aState.set(field.getName(), value_url);
456
                        }
457
                        
458
                    }
459
                    
460
                } else if (field.getType() == DataTypes.URI) {
461
                    
462
                    value_uri = aState.getURI(field.getName());
463
                    if (value_uri.getScheme() == null ||
464
                        "FILE".equalsIgnoreCase(value_uri.getScheme())) {
465
                        
466
                        File urifile = new File(value_uri.toURL().getFile());
467
                        donefile = (File) processedFilesMap.get(urifile);
468
                        if (donefile == null) {
469
                            value_file_new = copyFile(urifile, theFolder);
470
                            value_uri = value_file_new.toURI();
471
                            aState.set(field.getName(), value_uri);
472
                            processedFilesMap.put(urifile, value_file_new);
473
                        } else {
474
                            value_uri = donefile.toURI();
475
                            aState.set(field.getName(), value_uri);
476
                        }
477
                        
478
                    }
479
                }
480
            }
481
        }
482
        
483
        // ================================
484
        if (context instanceof PersistentContextServices) {
485
            /*
486
             * Ensure that previous instances are not used,
487
             * so objects are recreated
488
             */
489
            ((PersistentContextServices) context).clear();
490
        }
491
        Object resp = manager.create(state);
492
        return resp;
493
    }
494
    
495
    /**
496
     * @param context
497
     * @return
498
     */
499
    private static List<PersistentState> getList(PersistentContext context) {
500

    
501
        Iterator<PersistentState> iter = context.iterator();
502
        List<PersistentState> resp = new ArrayList<PersistentState>();
503
        while (iter.hasNext()) {
504
            resp.add(iter.next());
505
        }
506
        return resp;
507
    }
508

    
509
    /*
510
    private static Object recreate(PersistentState stat)
511
        throws Exception {
512
        
513
        File tmp = File.createTempFile("sym" + System.currentTimeMillis(), ".xml");
514
        FileOutputStream fos = new FileOutputStream(tmp);
515
        PersistenceManager mana = ToolsLocator.getPersistenceManager();
516
        mana.saveState(stat, fos);
517
        fos.flush();
518
        fos.close();
519
        FileInputStream fis = new FileInputStream(tmp);
520
        PersistentState nstat = mana.loadState(fis);
521
        fis.close();
522
        Object resp = mana.create(nstat);
523
        return resp;
524
    }
525
    */
526
    
527
    /**
528
     * Copies file to destination folder. If a file with same name
529
     * exists, destination name is changed. The final destination
530
     * file is returned.
531
     * 
532
     * @param srcfile
533
     * @param dstfolder
534
     * @return
535
     * @throws IOException
536
     */
537
    private static File copyFile(File srcfile, File dstfolder) 
538
    throws IOException {
539
        
540
        if (srcfile == null || dstfolder == null
541
            || !srcfile.isFile() || !dstfolder.isDirectory()
542
            || !srcfile.exists()) {
543
            
544
            throw new IOException("Bad parameters in copyFile method");
545
        }
546
        
547
        if (srcfile.getParentFile().equals(dstfolder)) {
548
            // already in place, nothing to do
549
            return srcfile;
550
        }
551

    
552
        if (!dstfolder.exists()) {
553
            dstfolder.mkdirs();
554
        }
555
        
556
        String checkfile = dstfolder.getCanonicalPath()
557
            + File.separator + srcfile.getName();
558
        File aux = new File(checkfile);
559
        File targetFile = null;
560
        if (aux.exists()) {
561
            // a file with that name exists and is not the same file
562
            // so we must create a new target file name
563
            targetFile = getAvailableFileName(dstfolder, srcfile.getName());
564
        } else {
565
            targetFile = aux;
566
        }
567
        
568
        FileUtils.copyFile(srcfile, targetFile);
569
        return targetFile;
570
    }
571

    
572
    /**
573
     * 
574
     * Gets an available file name in the folder, using
575
     * the name provided. It will add an index until an
576
     * unused name is found
577
     * 
578
     * @param dstfolder
579
     * @param name
580
     * @return
581
     */
582
    private static File getAvailableFileName(
583
        File dstfolder, String name) throws IOException {
584
        
585
        int index = -1;
586
        boolean exists = true;
587
        String tryname = null;
588
        String checkfile = null;
589
        File tryfile = null;
590
        
591
        while (exists) {
592
            index++;
593
            tryname = "" + index + "_" + name;
594
            checkfile = dstfolder.getCanonicalPath()
595
                + File.separator + tryname;
596
            tryfile = new File(checkfile);
597
            exists = tryfile.exists();
598
        }
599
        return tryfile;
600
    }
601
    
602
    
603
    
604

    
605

    
606
}