Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / layers / FLyrDefault.java @ 43979

History | View | Annotate | Download (32.6 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.fmap.mapcontext.layers;
25

    
26
import java.awt.Image;
27
import java.awt.geom.Point2D;
28
import java.io.File;
29
import java.net.URI;
30
import java.util.HashSet;
31
import java.util.List;
32
import java.util.Map;
33
import java.util.Set;
34
import org.apache.commons.lang3.StringUtils;
35

    
36
import org.cresques.cts.ICoordTrans;
37
import org.cresques.cts.IProjection;
38
import org.gvsig.fmap.dal.DataStore;
39
import org.gvsig.fmap.dal.DataTypes;
40
import org.gvsig.fmap.dal.exception.ReadException;
41
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
42
import org.gvsig.fmap.geom.primitive.Envelope;
43
import org.gvsig.fmap.mapcontext.MapContext;
44
import org.gvsig.fmap.mapcontext.MapContextLocator;
45
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
46
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
47
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
48
import org.gvsig.fmap.mapcontext.impl.DefaultMapContextManager;
49
import org.gvsig.fmap.mapcontext.layers.operations.ComposedLayer;
50
import org.gvsig.fmap.mapcontext.layers.operations.SingleLayer;
51
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
52
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
53
import org.gvsig.metadata.MetadataContainer;
54
import org.gvsig.metadata.MetadataLocator;
55
import org.gvsig.metadata.MetadataManager;
56
import org.gvsig.metadata.exceptions.MetadataException;
57
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.dispose.impl.AbstractDisposable;
59
import org.gvsig.tools.dynobject.DynClass;
60
import org.gvsig.tools.dynobject.DynObject;
61
import org.gvsig.tools.dynobject.DynStruct;
62
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
63
import org.gvsig.tools.dynobject.exception.DynMethodException;
64
import org.gvsig.tools.exception.BaseException;
65
import org.gvsig.tools.persistence.PersistenceManager;
66
import org.gvsig.tools.persistence.Persistent;
67
import org.gvsig.tools.persistence.PersistentState;
68
import org.gvsig.tools.persistence.exception.PersistenceException;
69
import org.gvsig.tools.util.Callable;
70
import org.slf4j.LoggerFactory;
71

    
72

    
73

    
74
/**
75
 * <p>Implementation of the common characteristics of all layers: visibility, activation, name, ...</p>
76
 *
77
 * <p>Represents the definition of a basic layer, implementing {@link FLayer FLayer}, and new functionality:
78
 * <ul>
79
 *  <li>Supports transparency.
80
 *  <li>Notification of evens produced using this layer.
81
 *  <li>Can have internal virtual layers.
82
 *  <li>Can have a text layer.
83
 *  <li>Supports an strategy for visit its geometries.
84
 *  <li>Can have an image in the <i>TOC (table of contents)</i> associated to the state of this layer.
85
 * </ul>
86
 * </p>
87
 *
88
 * <p>Each graphical layer will inherit from this class and adapt to its particular logic and model according
89
 *  its nature.</p>
90
 *
91
 * @see FLayer
92
 * @see FLayerStatus
93
 */
94
public abstract class FLyrDefault extends AbstractDisposable implements FLayer, FLayerHidesArea,
95
                LayerListener {
96
        /**
97
         * Useful for debug the problems during the implementation.
98
         */
99
        final static private org.slf4j.Logger logger = LoggerFactory.getLogger(FLyrDefault.class);
100

    
101
        private LayerChangeSupport layerChangeSupport = new LayerChangeSupport();
102

    
103
        /**
104
         * Flag to set the layer as a temporary layer.
105
         */
106
        private boolean temporary;
107

    
108
        /**
109
         * Path to the upper layer which this layer belongs.
110
         *
111
         * @see #getParentLayer()
112
         * @see #setParentLayer(FLayers)
113
         */
114
        private FLayers parentLayer = null;
115

    
116
        /**
117
         * Transparency level of this layer in the range 0-255. By default 255.
118
         * 0   --> Transparent
119
         * 255 --> Opaque
120
         *
121
         * @see #getTransparency()
122
         * @see #setTransparency(int)
123
         */
124
        private int transparency = 255;
125

    
126
        /**
127
         * Coordinate transformation.
128
         *
129
         * @see #getCoordTrans()
130
         * @see #setCoordTrans(ICoordTrans)
131
         */
132
        private ICoordTrans ct;
133

    
134
        /**
135
         * Minimum scale, >= 0 or -1 if not defined. By default -1.
136
         *
137
         * @see #getMinScale()
138
         * @see #setMinScale(double)
139
         */
140
        private double minScale = -1; // -1 indica que no se usa
141

    
142
        /**
143
         * Maximum scale, >= 0 or -1 if not defined. By default -1.
144
         *
145
         * @see #getMaxScale()
146
         * @see #setMaxScale(double)
147
         */
148
        private double maxScale = -1;
149
        //        private boolean isInTOC = true;
150

    
151
        /**
152
         * Array list with all listeners registered to this layer.
153
         *
154
         * @see #getLayerListeners()
155
         * @see #removeLayerListener(LayerListener)
156
         * @see #callEditionChanged(LayerEvent)
157
         */
158
        protected Set<LayerListener> layerListeners = new HashSet<>();
159

    
160
        //by default, all is active, visible and avalaible
161
        /**
162
         * Status of this layer.
163
         *
164
         * @see #getFLayerStatus()
165
         * @see #setFLayerStatus(FLayerStatus)
166
         * @see #isActive()
167
         * @see #setActive(boolean)
168
         * @see #isVisible()
169
         * @see #setVisible(boolean)
170
         * @see #visibleRequired()
171
         * @see #isEditing()
172
         * @see #setEditing(boolean)
173
         * @see #isInTOC()
174
         * @see #isCachingDrawnLayers()
175
         * @see #setCachingDrawnLayers(boolean)
176
         * @see #isDirty()
177
         * @see #setDirty(boolean)
178
         * @see #isAvailable()
179
         * @see #setAvailable(boolean)
180
         * @see #isOk()
181
         * @see #isWritable()
182
         * @see #getNumErrors()
183
         * @see #getError(int)
184
         * @see #getErrors()
185
         * @see #addError(BaseException)
186
         */
187
        private FLayerStatus status = new FLayerStatus();
188
        /**
189
         * Image drawn shown in the TOC according the status of this layer.
190
         *
191
         * @see #getTocStatusImage()
192
         * @see #setTocStatusImage(Image)
193
         */
194
        private Image tocStatusImage;
195

    
196
        protected MetadataContainer metadataContainer;
197

    
198
        /**
199
         * Draw version of the context. It's used for know when de componend has
200
         * changed any visualization property
201
         *
202
         *  @see getDrawVersion
203
         *  @see updateDrawVersion
204
         */
205
        private long drawVersion= 0L;
206

    
207

    
208
        private ExtendedPropertiesHelper properties = new ExtendedPropertiesHelper();
209

    
210
        public FLyrDefault(MetadataContainer metadataContainer) {
211
                this.metadataContainer = metadataContainer;
212
        }
213

    
214
        public FLyrDefault() {
215
                this(MetadataLocator
216
                        .getMetadataManager()
217
                                .createMetadataContainer(FLayer.METADATA_DEFINITION_NAME)
218
                );
219
        }
220

    
221

    
222
        /*
223
         * (non-Javadoc)
224
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getProperty(java.lang.Object)
225
         */
226
        public Object getProperty(Object key) {
227
                return properties.getProperty(key);
228
        }
229
        /*
230
         * (non-Javadoc)
231
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setProperty(java.lang.Object, java.lang.Object)
232
         */
233
        public void setProperty(Object key, Object val) {
234
                properties.setProperty(key, val);
235
        }
236
        /*
237
         * (non-Javadoc)
238
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getExtendedProperties()
239
         */
240
        public Map getExtendedProperties() {
241
                return properties.getExtendedProperties();
242
        }
243
        /*
244
         * (non-Javadoc)
245
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setActive(boolean)
246
         */
247
        public void setActive(boolean selected) {
248
                status.active = selected;
249
                callActivationChanged(LayerEvent.createActivationChangedEvent(this,
250
                "active"));
251
        }
252

    
253
        /*
254
         * (non-Javadoc)
255
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isActive()
256
         */
257
        public boolean isActive() {
258
                return status.active;
259
        }
260

    
261
        /*
262
         * (non-Javadoc)
263
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setName(java.lang.String)
264
         */
265
        public void setName(String name) {
266
                this.metadataContainer.setDynValue(METADATA_NAME, name);
267
                callNameChanged(LayerEvent.createNameChangedEvent(this, "name"));
268
        }
269
        
270

    
271
        /*
272
         * (non-Javadoc)
273
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getName()
274
         */
275
        public String getName() {
276
            String name = "(unknow)";
277
            try {
278
                name = (String) this.metadataContainer.getDynValue(METADATA_NAME);
279
            } catch( Throwable th) {
280
                logger.warn("Can't retrive the layer name.");
281
            }
282
            return name;
283
        }
284

    
285
        /*
286
         * (non-Javadoc)
287
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#load()
288
         */
289
    public void load() throws LoadLayerException {
290
        MetadataManager manager = MetadataLocator.getMetadataManager();
291
        try {
292
            manager.loadMetadata(this);
293
        } catch (MetadataException e) {
294
            throw new LoadLayerException("Can't load metadata.", e);
295
        }
296
        DefaultMapContextManager mcmanager = (DefaultMapContextManager) MapContextLocator.getMapContextManager();
297
        mcmanager.notifyLoadLayer(this);
298
    }
299

    
300
        /*
301
         * (non-Javadoc)
302
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setVisible(boolean)
303
         */
304
        public void setVisible(boolean visibility) {
305
                if (status.visible != visibility){
306
                        status.visible = visibility;
307
                        this.updateDrawVersion();
308

    
309
                        //                        if (this.getMapContext() != null){
310
                        //                                this.getMapContext().clearAllCachingImageDrawnLayers();
311
                        //                        }
312
                        callVisibilityChanged(LayerEvent.createVisibilityChangedEvent(this,
313
                        "visible"));
314
                }
315
        }
316

    
317

    
318
        /*
319
         * (non-Javadoc)
320
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isVisible()
321
         */
322
        public boolean isVisible() {
323
                return status.visible && status.available;
324
        }
325

    
326
        /*
327
         * (non-Javadoc)
328
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getParentLayer()
329
         */
330
        public FLayers getParentLayer() {
331
                return parentLayer;
332
        }
333

    
334

    
335
        /*
336
         * (non-Javadoc)
337
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setParentLayer(com.iver.cit.gvsig.fmap.layers.FLayers)
338
         */
339
        public void setParentLayer(FLayers root) {
340
                if (this.parentLayer != root){
341
                        this.parentLayer = root;
342
                        this.updateDrawVersion();
343
                }
344
        }
345

    
346
        /**
347
         * <p>Inserts the projection to this layer.</p>
348
         *
349
         * @param proj information about the new projection
350
         *
351
         * @see #isReprojectable()
352
         * @see #reProject(MapControl)
353
         */
354
        public void setProjection(IProjection proj) {
355
                IProjection curProj = this.getProjection();
356
                if (curProj == proj) {
357
                        return;
358
                }
359
                if (curProj != null && curProj.equals(proj)){
360
                        return;
361
                }
362
                this.updateDrawVersion();
363
                this.metadataContainer.setDynValue(METADATA_CRS, proj);
364
                // Comprobar que la proyecci?n es la misma que la de FMap
365
                // Si no lo es, es una capa que est? reproyectada al vuelo
366
                if ((proj != null) && (getMapContext() != null)) {
367
                        if (proj != getMapContext().getProjection()) {
368
                                ICoordTrans ct = proj.getCT(getMapContext().getProjection());
369
                                setCoordTrans(ct);
370
                                logger.debug("Cambio proyecci?n: FMap con "
371
                                                + getMapContext().getProjection().getAbrev() + " y capa "
372
                                                + getName() + " con " + proj.getAbrev());
373
                        }
374
                }
375
        }
376

    
377
        /*
378
         * (non-Javadoc)
379
         * @see org.cresques.geo.Projected#getProjection()
380
         */
381
        public IProjection getProjection() {
382
                return (IProjection) this.metadataContainer.getDynValue(METADATA_CRS);
383
        }
384

    
385
        /**
386
         * <p>Changes the projection of this layer.</p>
387
         * <p>This method will be overloaded in each kind of layer, according its specific nature.</p>
388
         *
389
         * @param mapC <code>MapControl</code> instance that will reproject this layer
390
         *
391
         * @return <code>true<code> if the layer has been created calling {@link FLayers#addLayer(FLayer) FLayers#addLayer}. But returns <code>false</code>
392
         *  if the load control logic of this layer is in the reprojection method
393
         *
394
         * @see #isReprojectable()
395
         * @see #setProjection(IProjection)
396
         */
397
        public void reProject(ICoordTrans arg0) {
398
        }
399

    
400
        /**
401
         * Returns the transparency level of this layer, in the range 0-255 .
402
         *
403
         * @return the transparency level
404
         *
405
         * @see #setTransparency(int)
406
         */
407
        public int getTransparency() {
408
                return transparency;
409
        }
410

    
411
        /**
412
         * Inserts the transparency level for this layer, the range allowed is 0-255 .
413
         *
414
         * @param trans the transparency level
415
         *
416
         * @see #getTransparency()
417
         */
418
        public void setTransparency(int trans) {
419
                if (this.transparency != trans){
420
                        transparency = trans;
421
                        this.updateDrawVersion();
422
                }
423
        }
424

    
425

    
426
        /*
427
         * (non-Javadoc)
428
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getMapContext()
429
         */
430
        public MapContext getMapContext() {
431
                if (getParentLayer() != null) {
432
                        return getParentLayer().getMapContext();
433
                } else {
434
                        return null;
435
                }
436
        }
437

    
438
        /*
439
         * (non-Javadoc)
440
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#addLayerListener(com.iver.cit.gvsig.fmap.layers.LayerListener)
441
         */
442
        public boolean addLayerListener(LayerListener o) {
443
            if( o == null ) {
444
                return true;
445
            }
446
            return layerListeners.add(o);
447
        }
448
        /*
449
         * (non-Javadoc)
450
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getLayerListeners()
451
         */
452
        public LayerListener[] getLayerListeners() {
453
                return (LayerListener[])layerListeners.toArray(new LayerListener[0]);
454
        }
455
        /*
456
         * (non-Javadoc)
457
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#removeLayerListener(com.iver.cit.gvsig.fmap.layers.LayerListener)
458
         */
459
        public boolean removeLayerListener(LayerListener o) {
460
                return layerListeners.remove(o);
461
        }
462
        /**
463
         *
464
         */
465
        private void callDrawValueChanged(LayerEvent e) {
466
           for (LayerListener listener : this.layerListeners) {
467
               try {
468
                   listener.drawValueChanged(e);
469
               } catch (Exception ex) {
470
                   logger.warn("Error calling listener '"+listener.toString()+"'.", ex);
471
               }
472
           }
473
        }
474
        /**
475
         * Called by the method {@linkplain #setName(String)}. Notifies all listeners associated to this layer,
476
         *  that its name has changed.
477
         *
478
         * @param e a layer event with the name of the property that has changed
479
         *
480
         * @see #setName(String)
481
         */
482
        private void callNameChanged(LayerEvent e) {
483
           for (LayerListener listener : this.layerListeners) {
484
               try {
485
                   listener.nameChanged(e);
486
               } catch (Exception ex) {
487
                   logger.warn("Error calling listener '"+listener.toString()+"'.", ex);
488
               }
489
           }
490
        }
491

    
492
        /**
493
         * Called by the method {@linkplain #setVisible(boolean)}. Notifies all listeners associated to this layer,
494
         *  that its visibility has changed.
495
         *
496
         * @param e a layer event with the name of the property that has changed
497
         *
498
         * @see #setVisible(boolean)
499
         */
500
        private void callVisibilityChanged(LayerEvent e) {
501
           for (LayerListener listener : this.layerListeners) {
502
               try {
503
                   listener.visibilityChanged(e);
504
               } catch (Exception ex) {
505
                   logger.warn("Error calling listener '"+listener.toString()+"'.", ex);
506
               }
507
           }
508
        }
509

    
510
        /**
511
         * Called by the method {@linkplain #setActive(boolean)}. Notifies all listeners associated to this layer,
512
         *  that its active state has changed.
513
         *
514
         * @param e a layer event with the name of the property that has changed
515
         *
516
         * @see #setActive(boolean)
517
         */
518
       private void callActivationChanged(LayerEvent e) {
519
           for (LayerListener listener : this.layerListeners) {
520
               try {
521
                   listener.activationChanged(e);
522
               } catch (Exception ex) {
523
                   logger.warn("Error calling listener '"+listener.toString()+"'.", ex);
524
               }
525
           }
526
       }
527

    
528
        /**
529
         * Returns the virtual layers associated to this layer.
530
         *
531
         * @return a node with the layers
532
         *
533
         * @see #setVirtualLayers(FLayers)
534
         */
535
        //        public FLayers getVirtualLayers() {
536
        //                return virtualLayers;
537
        //        }
538

    
539
        /**
540
         * Inserts virtual layers to this layer.
541
         *
542
         * @param virtualLayers a node with the layers
543
         *
544
         * @see #getVirtualLayers()
545
         */
546
        //        public void setVirtualLayers(FLayers virtualLayers) {
547
        //                this.virtualLayers = virtualLayers;
548
        //        }
549

    
550
        /**
551
         * Sets transformation coordinates for this layer.
552
         *
553
         * @param ct an object that implements the <code>ICoordTrans</code> interface, and with the transformation coordinates
554
         *
555
         * @see #getCoordTrans()
556
         */
557
        public void setCoordTrans(ICoordTrans ct) {
558
                if (this.ct == ct){
559
                        return;
560
                }
561
                if (this.ct != null && this.ct.equals(ct)){
562
                        return;
563
                }
564
                this.ct = ct;
565
                this.updateDrawVersion();
566
        }
567

    
568
        /**
569
         * Returns the transformation coordinates of this layer.
570
         *
571
         * @return an object that implements the <code>ICoordTrans</code> interface, and with the transformation coordinates
572
         *
573
         * @see #setCoordTrans(ICoordTrans)
574
         */
575
        public ICoordTrans getCoordTrans() {
576
                return ct;
577
        }
578

    
579
        /**
580
         * <p>Method called by {@link FLayers FLayers} to notify this layer that is going to be added.
581
         *  This previous notification is useful for the layers that need do something before being added. For
582
         *  example, the raster needs reopen a file that could have been closed recently.</p>
583
     * @deprecated no deberia ser necesario llamar a esto, la capa debe comportarse correctamente sin necesidad de llamarlo.
584
         */
585
        public void wakeUp() throws LoadLayerException {
586
        }
587
        /*
588
         * (non-Javadoc)
589
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getMinScale()
590
         */
591
        public double getMinScale() {
592
                return minScale;
593
        }
594

    
595
        /*
596
         * (non-Javadoc)
597
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getMaxScale()
598
         */
599
        public double getMaxScale() {
600
                return maxScale;
601
        }
602
        /*
603
         * (non-Javadoc)
604
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setMinScale(double)
605
         */
606
        public void setMinScale(double minScale) {
607
                if (this.minScale != minScale){
608
                        this.minScale = minScale;
609
                        this.updateDrawVersion();
610
                }
611
        }
612
        /*
613
         * (non-Javadoc)
614
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setMaxScale(double)
615
         */
616
        public void setMaxScale(double maxScale) {
617
                if (this.maxScale != maxScale){
618
                        this.maxScale = maxScale;
619
                        this.updateDrawVersion();
620
                }
621
        }
622
        /*
623
         * (non-Javadoc)
624
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isWithinScale(double)
625
         */
626
        public boolean isWithinScale(double scale) {
627

    
628
                boolean bVisible = true;
629
                if (getMinScale() != -1) {
630
                        if (scale < getMinScale()){
631
                                bVisible = false;
632
                        }
633
                }
634
                if (getMaxScale() != -1) {
635
                        if (scale > getMaxScale()) {
636
                                bVisible = false;
637
                        }
638
                }
639

    
640
                return bVisible;
641
        }
642
        /*
643
         * (non-Javadoc)
644
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setEditing(boolean)
645
         */
646
        public void setEditing(boolean b) throws StartEditionLayerException {
647
                status.editing = b;
648
        }
649
        /**
650
         * Called by some version of the method {@linkplain #setEditing(boolean)} overwritten. Notifies
651
         *  all listeners associated to this layer, that its edition state has changed.
652
         *
653
         * @param e a layer event with the name of the property that has changed
654
         *
655
         * @see #setEditing(boolean)
656
         */
657
        protected void callEditionChanged(LayerEvent e) {
658
           for (LayerListener listener : this.layerListeners) {
659
               try {
660
                   listener.editionChanged(e);
661
               } catch (Exception ex) {
662
                   logger.warn("Error calling listener '"+listener.toString()+"'.", ex);
663
               }
664
           }
665
        }
666

    
667
        /*
668
         * (non-Javadoc)
669
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isEditing()
670
         */
671
        public boolean isEditing() {
672
                return status.editing;
673
        }
674
        /*
675
         * (non-Javadoc)
676
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getTocImageIcon()
677
         */
678
        public String getTocImageIcon() {
679
                return "layer-icon";
680
        }
681

    
682
        /*
683
         * (non-Javadoc)
684
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isInTOC()
685
         */
686
        public boolean isInTOC() {
687
                return status.inTOC;
688
        }
689
        /*
690
         * (non-Javadoc)
691
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setInTOC(boolean)
692
         */
693
        public void setInTOC(boolean b) {
694
                status.inTOC=b;
695
        }
696
        /*
697
         * (non-Javadoc)
698
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isAvailable()
699
         */
700
        public boolean isAvailable() {
701
                return status.available;
702
        }
703
        /*
704
         * (non-Javadoc)
705
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setAvailable(boolean)
706
         */
707
        public void setAvailable(boolean available) {
708
                if (status.available != available){
709
                        status.available = available;
710
                        this.updateDrawVersion();
711
                }
712
        }
713
        /*
714
         * (non-Javadoc)
715
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#reload()
716
         */
717
        public void reload() throws ReloadLayerException {
718
            if(this.ct!=null){
719
                IProjection srcProj = this.ct.getPOrig();
720
                if(!this.getProjection().equals(srcProj)){
721
                    this.ct = this.getProjection().getCT(this.ct.getPDest());
722
                }
723
            }
724
                this.setAvailable(true);
725
        }
726

    
727
        /*
728
         * (non-Javadoc)
729
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getFLayerStatus()
730
         */
731
        public FLayerStatus getFLayerStatus(){
732
                return status.cloneStatus();
733
        }
734
        /*
735
         * (non-Javadoc)
736
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#setFLayerStatus(com.iver.cit.gvsig.fmap.layers.FLayerStatus)
737
         */
738
        public void setFLayerStatus(FLayerStatus status){
739
                if (!this.status.equals(status)){
740
                        this.status = status;
741
                        this.updateDrawVersion();
742
                }
743
        }
744

    
745
        /*
746
         * (non-Javadoc)
747
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#isOk()
748
         */
749

    
750
        public boolean isOk(){
751
                return status.isOk();
752
        }
753
        /*
754
         * (non-Javadoc)
755
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getNumErrors()
756
         */
757
        public int getNumErrors(){
758
                return status.getNumErrors();
759
        }
760

    
761
        
762
        @Override
763
        public Throwable getError(int i){
764
                return status.getError(i);
765
        }
766
        
767
        @Override
768
        public List<Throwable> getErrors(){
769
                return status.getErrors();
770
        }
771

    
772
    @Override
773
        public void addError(Throwable exception){
774
                status.addLayerError(exception);
775
        }
776

    
777
        @Override
778
        public void setError(Throwable ex) {
779
                this.status.setLayerError(ex);
780
        }
781

    
782
        @Override
783
        public boolean visibleRequired() {
784
                return status.visible;
785
        }
786

    
787
    @Override
788
        public String getInfoString() {
789
            Envelope env = null;
790
            DataStore store = null;
791
            try {
792
                env = this.getFullEnvelope();
793
            } catch (ReadException ex) {
794
            }
795

    
796
            try {
797
                store = ((SingleLayer)this).getDataStore();
798
            } catch(Throwable th) {
799
                
800
            }
801
            
802
            LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
803
            
804
            if( store!=null ) {
805
                builder.title().labelkey("Data_source");
806
                builder.property().labelkey("Source_type").value(store.getProviderName());
807
                builder.property().labelkey("origen").value(store.getFullName());
808
                if( store.getParameters() instanceof FilesystemStoreParameters ) {
809
                    File f = ((FilesystemStoreParameters) (store.getParameters())).getFile();
810
                    if( f != null && f.exists() ) {
811
                        builder.property().labelkey("_Size").value("%d bytes", f.length());
812
                    }
813
                }
814
            }
815
            
816
            builder.title().labelkey("_Coordenadas_geograficas");
817
            if( this.isAvailable() ) {
818
                builder.envelope().value(env);
819
            }
820

    
821
            builder.title().labelkey("_Projection");
822
            if( this.isAvailable() ) {
823
                builder.property().value(this.getProjection());
824
                builder.text().asWKT(this.getProjection());
825
            }
826
        
827
            return builder.toString();
828
        }
829
        
830
        @Override
831
        public boolean isWritable() {
832
                return status.writable;
833
        }
834

    
835
        @Override
836
        public FLayer cloneLayer() throws Exception {
837
                logger.warn("Use of cloneLayer and this is not implemented.");
838
                return this;
839
        }
840

    
841
        @Override
842
        public Image getTocStatusImage() {
843
            return tocStatusImage;
844
        }
845

    
846
        /**
847
         * Inserts the image icon that will be shown in the TOC next to this layer, according its status.
848
         *
849
         * @param tocStatusImage the image
850
         *
851
         * @see #getTocStatusImage()
852
         */
853
        public void setTocStatusImage(Image tocStatusImage) {
854
                this.tocStatusImage = tocStatusImage;
855
                logger.debug("setTocStatusImage " + tocStatusImage + " sobre capa " + this.getName());
856
        }
857

    
858
        public ComposedLayer newComposedLayer() {
859
                return null;
860
        }
861

    
862
        public boolean allowLinks()
863
        {
864
                return false;
865
        }
866

    
867
        public AbstractLinkProperties getLinkProperties()
868
        {
869
                return null;
870
        }
871

    
872
        public URI[] getLink(Point2D point, double tolerance) throws ReadException{
873
                return null;
874
        }
875

    
876
        public void addLegendListener(LegendListener listener) {
877
            if( listener == null ) {
878
                return ;
879
            }
880
            layerChangeSupport.addLayerListener(listener);
881
        }
882

    
883
        /**
884
     * @param e
885
         * @see LayerChangeSupport#callLegendChanged(LegendChangedEvent)
886
         */
887
        protected void callLegendChanged(LegendChangedEvent e) {
888
                layerChangeSupport.callLegendChanged(e);
889
                if(parentLayer != null) {
890
                        parentLayer.callLegendChanged(e);
891
                }
892
        }
893

    
894
        /**
895
         * @see LayerChangeSupport#removeLayerListener(LegendListener)
896
         */
897
        public void removeLegendListener(LegendListener listener) {
898
                layerChangeSupport.removeLayerListener(listener);
899
        }
900
        public String getClassName() {
901
                return this.getClass().getName();
902
        }
903

    
904
        public void delegate(DynObject dynObject) {
905
                this.metadataContainer.delegate(dynObject);
906
        }
907

    
908
        public DynClass getDynClass() {
909
                return this.metadataContainer.getDynClass();
910
        }
911

    
912
        public Object getDynValue(String name) throws DynFieldNotFoundException {
913
                return this.metadataContainer.getDynValue(name);
914
        }
915

    
916
        public boolean hasDynValue(String name) {
917
                return this.metadataContainer.hasDynValue(name);
918
        }
919

    
920
        public void implement(DynClass dynClass) {
921
                this.metadataContainer.implement(dynClass);
922
        }
923

    
924
        public Object invokeDynMethod(int code, Object[] args)
925
        throws DynMethodException {
926
                return this.metadataContainer.invokeDynMethod(this, code, args);
927
        }
928

    
929
        public Object invokeDynMethod(String name, Object[] args)
930
        throws DynMethodException {
931
                return this.metadataContainer.invokeDynMethod(this, name, args);
932
        }
933

    
934
        public void setDynValue(String name, Object value)
935
        throws DynFieldNotFoundException {
936
                this.metadataContainer.setDynValue(name, value);
937
        }
938

    
939
        public long getDrawVersion() {
940
                return this.drawVersion;
941
        }
942

    
943
        protected void updateDrawVersion(){
944
                this.drawVersion++;
945
                this.callDrawValueChanged(LayerEvent.createDrawValuesChangedEvent(this, ""));
946
                if (this.parentLayer != null){
947
                        this.parentLayer.updateDrawVersion();
948
                }
949
        }
950

    
951
        public boolean hasChangedForDrawing(long value){
952
                return this.drawVersion > value;
953
        }
954

    
955
        public void activationChanged(LayerEvent e) {
956
        }
957

    
958
        public void drawValueChanged(LayerEvent e) {
959
                this.updateDrawVersion();
960
        }
961

    
962
        public void editionChanged(LayerEvent e) {
963

    
964
        }
965

    
966
        public void nameChanged(LayerEvent e) {
967

    
968
        }
969

    
970
        public void visibilityChanged(LayerEvent e) {
971

    
972
        }
973

    
974
        // ========================================================
975

    
976
        public void saveToState(PersistentState state) throws PersistenceException {
977
            try {
978
                state.set("parentLayer", (Persistent)parentLayer);
979
                state.set("status",status);
980
                state.set("minScale", minScale);
981
                state.set("maxScale", maxScale);
982
                state.set("transparency",transparency);
983
                state.set("coordTrans",ct);
984
                state.set("name", getName());
985
                state.set("crs", getProjection());
986
                state.set("properties",properties.getExtendedProperties());
987
            } catch(PersistenceException ex) {
988
                logger.warn("Can't save to persistent state the layer '"+this.getName()+"'.");
989
                throw ex;
990
            } catch(RuntimeException ex) {
991
                logger.warn("Can't save to persistent state the layer '"+this.getName()+"'.");
992
                throw ex;
993
            }
994
        }
995

    
996
        @Override
997
        public void loadFromState(PersistentState state) throws PersistenceException {
998
                try {
999
                        String name = state.getString("name");
1000
                        if( StringUtils.isEmpty(name) ) {
1001
                                name = "Unknown";
1002
                        }
1003
                        this.setDynValue(METADATA_NAME, name);
1004
                        this.setDynValue(METADATA_CRS, state.get("crs"));
1005

    
1006
                        this.parentLayer = (FLayers) state.get("parentLayer");
1007
                        this.status = (FLayerStatus) state.get("status");
1008
                        if( this.status == null ) {
1009
                                this.status = new FLayerStatus();
1010
                                this.setAvailable(false);
1011
                                this.addError(new RuntimeException("Can't retreieve the status of the layer."));
1012
                        }
1013
                        this.minScale = state.getDouble("minScale", -1);
1014
                        this.maxScale = state.getDouble("maxScale", -1);
1015
                        this.transparency = state.getInt("transparency", 255);
1016
                        this.ct = (ICoordTrans) state.get("coordTrans");
1017

    
1018
                        this.properties.setExtendedProperties((Map) state.get("properties"));
1019
                } catch (Exception ex) {
1020
                        logger.warn("Can't load from persietent state the layer '" + this.getName() + "'.");
1021
                        throw ex;
1022
                }
1023

    
1024
        }
1025
    public static class RegisterPersistence implements Callable {
1026

    
1027
                @Override
1028
                public Object call() {
1029
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1030
                        DynStruct definition = manager.addDefinition(
1031
                                FLyrDefault.class,
1032
                                "FLyrDefault",
1033
                                "FLyrDefault Persistence definition",
1034
                                null,
1035
                                null
1036
                        );
1037
                        definition.addDynFieldString("name").setMandatory(false);
1038
                        definition.addDynFieldInt("transparency").setMandatory(true);
1039
                        definition.addDynFieldDouble("minScale").setMandatory(true);
1040
                        definition.addDynFieldDouble("maxScale").setMandatory(true);
1041
                        definition.addDynFieldObject("crs").setClassOfValue(
1042
                                IProjection.class).setMandatory(false);
1043
                        definition.addDynFieldObject("parentLayer").setClassOfValue(
1044
                                FLayers.class).setMandatory(false);
1045
                        definition.addDynFieldObject("coordTrans").setClassOfValue(
1046
                                ICoordTrans.class).setMandatory(false);
1047
                        definition.addDynFieldObject("status").setClassOfValue(
1048
                                FLayerStatus.class).setMandatory(true);
1049
                        // "properties" deberia estar declarada como un "ExtendedPropertiesHelper"
1050
                        // pero por compatibilidad con proyectos viejos lo mantenemos como un
1051
                        // Map.
1052
//                        definition.addDynFieldObject("properties").setClassOfValue(
1053
//                                ExtendedPropertiesHelper.class)
1054
//                                .setMandatory(false);
1055
                        definition.addDynFieldMap("properties").setClassOfItems(Object.class)
1056
                                .setMandatory(true);
1057

    
1058
                        return Boolean.TRUE;
1059
                }
1060
    }
1061

    
1062

    
1063
//        /**
1064
//         * Splits string into an array of strings
1065
//         * @param input input string
1066
//         * @param sep separator string
1067
//         * @return an array of strings
1068
//         */
1069
//        public static String[] splitString(String input, String sep) {
1070
//                return Pattern.compile(sep).split(input, 0);
1071
//        }
1072

    
1073
        public void clear() {
1074
                if (metadataContainer != null) {
1075
                        metadataContainer.clear();
1076
                }
1077
        }
1078

    
1079
    public String getMetadataName() throws MetadataException {
1080
        return FLayer.METADATA_DEFINITION_NAME;
1081
    }
1082

    
1083
        public static class RegisterMetadata implements Callable {
1084

    
1085
            public Object call() {
1086
                MetadataManager metadataManager = MetadataLocator.getMetadataManager();
1087

    
1088
                DynStruct metadataDefinition = metadataManager.getDefinition(FLayer.METADATA_DEFINITION_NAME);
1089
                if ( metadataDefinition == null ) {
1090
                    try {
1091
                        metadataDefinition = metadataManager.addDefinition(
1092
                                FLayer.METADATA_DEFINITION_NAME,
1093
                                FLayer.METADATA_DEFINITION_DESCRIPTION);
1094
                        metadataDefinition.addDynField(FLayer.METADATA_NAME)
1095
                                .setMandatory(true);
1096

    
1097
                        IProjection ipr
1098
                                = MapContextLocator.getMapContextManager().getDefaultCRS();
1099

    
1100
                        metadataDefinition.addDynFieldObject(FLayer.METADATA_CRS)
1101
                                .setType(DataTypes.CRS).setMandatory(true)
1102
                                .setDefaultFieldValue(ipr);
1103
                    } catch (MetadataException e) {
1104
                        logger.warn("Can't create metadata definition for 'Layer'", e);
1105
                    }
1106
                }
1107
                return Boolean.TRUE;
1108
            }
1109
        }
1110

    
1111
        public String toString() {
1112
                return this.getName();
1113
        }
1114

    
1115
        public boolean hidesThisArea(Envelope area) {
1116
                return false;
1117
        }
1118

    
1119
        public boolean isTemporary() {
1120
            return this.temporary;
1121
        }
1122

    
1123
        public void setTemporary(boolean temporary) {
1124
            this.temporary = temporary;
1125
        }
1126
        
1127
        @Override
1128
        public int getDefaultTolerance() {
1129
            return 7;
1130
        } 
1131
}