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 @ 43215

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

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

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

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

    
316

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

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

    
333

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

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

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

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

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

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

    
424

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
839
        @Override
840
        public Image getTocStatusImage() {
841
            return tocStatusImage;
842
        }
843

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

    
856
        public ComposedLayer newComposedLayer() {
857
                return null;
858
        }
859

    
860
        public boolean allowLinks()
861
        {
862
                return false;
863
        }
864

    
865
        public AbstractLinkProperties getLinkProperties()
866
        {
867
                return null;
868
        }
869

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

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

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

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

    
902
        public void delegate(DynObject dynObject) {
903
                this.metadataContainer.delegate(dynObject);
904
        }
905

    
906
        public DynClass getDynClass() {
907
                return this.metadataContainer.getDynClass();
908
        }
909

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

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

    
918
        public void implement(DynClass dynClass) {
919
                this.metadataContainer.implement(dynClass);
920
        }
921

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

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

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

    
937
        public long getDrawVersion() {
938
                return this.drawVersion;
939
        }
940

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

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

    
953
        public void activationChanged(LayerEvent e) {
954
        }
955

    
956
        public void drawValueChanged(LayerEvent e) {
957
                this.updateDrawVersion();
958
        }
959

    
960
        public void editionChanged(LayerEvent e) {
961

    
962
        }
963

    
964
        public void nameChanged(LayerEvent e) {
965

    
966
        }
967

    
968
        public void visibilityChanged(LayerEvent e) {
969

    
970
        }
971

    
972
        // ========================================================
973

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

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

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

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

    
1022
        }
1023
    public static class RegisterPersistence implements Callable {
1024

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

    
1056
                        return Boolean.TRUE;
1057
                }
1058
    }
1059

    
1060

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

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

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

    
1081
        public static class RegisterMetadata implements Callable {
1082

    
1083
            public Object call() {
1084
                MetadataManager metadataManager = MetadataLocator.getMetadataManager();
1085

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

    
1095
                        IProjection ipr
1096
                                = MapContextLocator.getMapContextManager().getDefaultCRS();
1097

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

    
1109
        public String toString() {
1110
                return this.getName();
1111
        }
1112

    
1113
        public boolean hidesThisArea(Envelope area) {
1114
                return false;
1115
        }
1116

    
1117
        public boolean isTemporary() {
1118
            return this.temporary;
1119
        }
1120

    
1121
        public void setTemporary(boolean temporary) {
1122
            this.temporary = temporary;
1123
        }
1124
}