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 40560 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40560 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
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 40560 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * 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 40560 jjdelcerro
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20 40435 jjdelcerro
 *
21 40560 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
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
}