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

History | View | Annotate | Download (32.7 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 static final int TOL = 7;
102

    
103
        private LayerChangeSupport layerChangeSupport = new LayerChangeSupport();
104

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

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

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

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

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

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

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

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

    
198
        protected MetadataContainer metadataContainer;
199

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

    
209

    
210
        private ExtendedPropertiesHelper properties = new ExtendedPropertiesHelper();
211

    
212
        public FLyrDefault(MetadataContainer metadataContainer) {
213
                this.metadataContainer = metadataContainer;
214
        }
215

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

    
223

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

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

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

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

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

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

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

    
319

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

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

    
336

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

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

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

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

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

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

    
427

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
843
        @Override
844
        public Image getTocStatusImage() {
845
            return tocStatusImage;
846
        }
847

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

    
860
        public ComposedLayer newComposedLayer() {
861
                return null;
862
        }
863

    
864
        public boolean allowLinks()
865
        {
866
                return false;
867
        }
868

    
869
        public AbstractLinkProperties getLinkProperties()
870
        {
871
                return null;
872
        }
873

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

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

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

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

    
906
        public void delegate(DynObject dynObject) {
907
                this.metadataContainer.delegate(dynObject);
908
        }
909

    
910
        public DynClass getDynClass() {
911
                return this.metadataContainer.getDynClass();
912
        }
913

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

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

    
922
        public void implement(DynClass dynClass) {
923
                this.metadataContainer.implement(dynClass);
924
        }
925

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

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

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

    
941
        public long getDrawVersion() {
942
                return this.drawVersion;
943
        }
944

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

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

    
957
        public void activationChanged(LayerEvent e) {
958
        }
959

    
960
        public void drawValueChanged(LayerEvent e) {
961
                this.updateDrawVersion();
962
        }
963

    
964
        public void editionChanged(LayerEvent e) {
965

    
966
        }
967

    
968
        public void nameChanged(LayerEvent e) {
969

    
970
        }
971

    
972
        public void visibilityChanged(LayerEvent e) {
973

    
974
        }
975

    
976
        // ========================================================
977

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

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

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

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

    
1026
        }
1027
    public static class RegisterPersistence implements Callable {
1028

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

    
1060
                        return Boolean.TRUE;
1061
                }
1062
    }
1063

    
1064

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

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

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

    
1085
        public static class RegisterMetadata implements Callable {
1086

    
1087
            public Object call() {
1088
                MetadataManager metadataManager = MetadataLocator.getMetadataManager();
1089

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

    
1099
                        IProjection ipr
1100
                                = MapContextLocator.getMapContextManager().getDefaultCRS();
1101

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

    
1113
        public String toString() {
1114
                return this.getName();
1115
        }
1116

    
1117
        public boolean hidesThisArea(Envelope area) {
1118
                return false;
1119
        }
1120

    
1121
        public boolean isTemporary() {
1122
            return this.temporary;
1123
        }
1124

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