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 / vectorial / FLyrVect.java @ 47518

History | View | Annotate | Download (54.2 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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.mapcontext.layers.vectorial;
24

    
25
import java.awt.Graphics2D;
26
import java.awt.Point;
27
import java.awt.geom.Point2D;
28
import java.awt.image.BufferedImage;
29
import java.io.File;
30
import java.util.Iterator;
31
import java.util.Set;
32
import java.util.TreeSet;
33
import org.cresques.cts.ICoordTrans;
34
import org.cresques.cts.IProjection;
35
import org.gvsig.compat.print.PrintAttributes;
36
import org.gvsig.fmap.dal.DALLocator;
37
import org.gvsig.fmap.dal.DataManager;
38
import org.gvsig.fmap.dal.DataStore;
39
import org.gvsig.fmap.dal.DataStoreParameters;
40
import org.gvsig.fmap.dal.exception.DataException;
41
import org.gvsig.fmap.dal.exception.InitializeException;
42
import org.gvsig.fmap.dal.exception.ReadException;
43
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
44
import org.gvsig.fmap.dal.feature.FeatureQuery;
45
import org.gvsig.fmap.dal.feature.FeatureSet;
46
import org.gvsig.fmap.dal.feature.FeatureStore;
47
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
48
import org.gvsig.fmap.dal.feature.FeatureType;
49
import org.gvsig.fmap.dal.feature.OpenFeatureStoreParameters;
50
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
51
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
54
import org.gvsig.fmap.geom.Geometry.TYPES;
55
import org.gvsig.fmap.geom.GeometryLocator;
56
import org.gvsig.fmap.geom.GeometryManager;
57
import org.gvsig.fmap.geom.primitive.Circle;
58
import org.gvsig.fmap.geom.primitive.Envelope;
59
import org.gvsig.fmap.geom.type.GeometryType;
60
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
61
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
62
import org.gvsig.fmap.mapcontext.MapContext;
63
import org.gvsig.fmap.mapcontext.MapContextLocator;
64
import org.gvsig.fmap.mapcontext.MapContextManager;
65
import org.gvsig.fmap.mapcontext.ViewPort;
66
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
67
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
68
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
69
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
70
import org.gvsig.fmap.mapcontext.layers.FLayer;
71
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
72
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
73
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
74
import org.gvsig.fmap.mapcontext.layers.LayerListener;
75
import org.gvsig.fmap.mapcontext.layers.SelectionEvent;
76
import org.gvsig.fmap.mapcontext.layers.SelectionListener;
77
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
78
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
79
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
80
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
81
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
82
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
83
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
84
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
85
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
86
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
87
import org.gvsig.metadata.exceptions.MetadataException;
88
import org.gvsig.tools.ToolsLocator;
89
import org.gvsig.tools.dynobject.DynObjectManager;
90
import org.gvsig.tools.dynobject.DynObjectSet;
91
import org.gvsig.tools.dynobject.DynStruct;
92
import org.gvsig.tools.dynobject.Tags;
93
import org.gvsig.tools.evaluator.Evaluator;
94
import org.gvsig.tools.exception.BaseException;
95
import org.gvsig.tools.locator.LocatorException;
96
import org.gvsig.tools.observer.Observable;
97
import org.gvsig.tools.observer.Observer;
98
import org.gvsig.tools.persistence.PersistenceManager;
99
import org.gvsig.tools.persistence.PersistentState;
100
import org.gvsig.tools.persistence.exception.PersistenceException;
101
import org.gvsig.tools.task.Cancellable;
102
import org.gvsig.tools.util.Callable;
103
import org.slf4j.LoggerFactory;
104

    
105
/**
106
 * Capa b?sica Vectorial.
107
 *
108
 */
109
@SuppressWarnings("UseSpecificCatch")
110
public class FLyrVect
111
        extends FLyrDefault
112
        implements VectorLayer,
113
        LegendContentsChangedListener, Observer {
114

    
115
    public static final String TAG_LAYERVECT_MAXSCALE = "layervect.scale.max";
116
    public static final String TAG_LAYERVECT_MINSCALE = "layervect.scale.min";
117
    
118
    final static private org.slf4j.Logger logger
119
            = LoggerFactory.getLogger(FLyrVect.class);
120
    private final GeometryManager geomManager
121
            = GeometryLocator.getGeometryManager();
122

    
123
    /**
124
     * Leyenda de la capa vectorial
125
     */
126
    private IVectorLegend legend;
127
    private int typeShape = -1;
128
    private FeatureStore featureStore = null;
129
    private DataStoreParameters dataStoreParameters;
130
    private SpatialCache spatialCache = new SpatialCache();
131

    
132
    /**
133
     * An implementation of gvSIG spatial index
134
     */
135
    // protected ISpatialIndex spatialIndex = null;
136
    private IVectorLegend loadLegend = null;
137

    
138
    private boolean isLabeled;
139
    protected ILabelingStrategy strategy;
140
//        private ReprojectDefaultGeometry reprojectTransform;
141
    private FeatureQuery baseQuery = null;
142

    
143
    public FLyrVect() {
144
        super();
145
    }
146

    
147
    @Override
148
    public String getTocImageIcon() {
149
        if( this.featureStore==null && this.dataStoreParameters!=null ) {
150
            return MapContextLocator.getMapContextManager().getIconLayer(this.dataStoreParameters.getProviderName());
151
        }
152
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
153
    }
154

    
155
    /**
156
     * Return the store associated to the layer.
157
     *
158
     * @return the store
159
     */
160
    @Override
161
    public DataStore getDataStore() {
162
        return featureStore;
163
    }
164

    
165
    /**
166
     * Asigna el data-store a la capa. Esta operacion no se deneria poder hacer
167
     * desde fuera de la clase.
168
     *
169
     * @param dataStore
170
     * @throws LoadLayerException
171
     * @deprecated use {@link #bindToDataStore(DataStore)}
172
     */
173
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
174
        bindToDataStore(dataStore);
175
    }
176

    
177
    public void setDataStoreParameters(DataStoreParameters parameters) {
178
        this.dataStoreParameters = parameters;
179
    }
180

    
181
    @Override
182
    public void setVisible(boolean visibility) {
183
        if( visibility && this.featureStore==null && this.dataStoreParameters!=null )  {
184
            try {
185
                DataManager dataManager = DALLocator.getDataManager();
186
                DataStore dataStore = dataManager.openStore(
187
                        this.dataStoreParameters.getProviderName(),
188
                        this.dataStoreParameters
189
                );
190
                this.bindToDataStore(dataStore);
191
                IProjection projection = (IProjection) dataStore.getDynValue(FeatureStore.METADATA_CRS);
192
                if (projection != null) {
193
                    this.setProjection(projection);
194
                }
195
                if (projection != null && this.getMapContext() != null) {
196
                    IProjection mapContextProj = this.getMapContext().getProjection();
197
                    if (!projection.getAbrev().equals(mapContextProj.getAbrev())) {
198
                        ICoordTrans ct = projection.getCT(mapContextProj);
199
                        this.setCoordTrans(ct);
200
                    } else {
201
                        this.setCoordTrans(null);
202
                    }
203
                }
204

    
205
            } catch (Exception ex) {
206
                throw new RuntimeException("Can't set visibility to layer", ex);
207
            }
208
        }
209
        super.setVisible(visibility);         
210
    }
211
    
212
    /**
213
     * Enlaza la capa con el DataStore indicado.
214
     *
215
     * @param dataStore
216
     * @throws LoadLayerException
217
     */
218
    protected void bindToDataStore(DataStore dataStore) throws LoadLayerException {
219
        if (this.featureStore != null && this.featureStore != dataStore) {
220
            this.featureStore.deleteObserver(this);
221
        }
222

    
223
        featureStore = (FeatureStore) dataStore;
224
        if( this.dataStoreParameters==null ) {
225
            this.dataStoreParameters = this.featureStore.getParameters();
226
        }
227
        
228
        MapContextManager mapContextManager
229
                = MapContextLocator.getMapContextManager();
230

    
231
        //Set the legend
232
        IVectorLegend legend
233
                = (IVectorLegend) mapContextManager.getLegend(dataStore);
234

    
235
        if (legend == null) {
236
            throw new LegendLayerException(this.getName());
237
        }
238

    
239
        this.setLegend(legend);
240

    
241
        //Set the labeling strategy
242
        ILabelingStrategy labeler
243
                = (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
244

    
245
        if (labeler != null) {
246
            labeler.setLayer(this);
247
            this.setLabelingStrategy(labeler);
248
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
249
            // etiquetes?????
250
        }
251

    
252
        this.delegate(dataStore);
253

    
254
        dataStore.addObserver(this);
255
        
256
        FeatureType featureType = featureStore.getDefaultFeatureTypeQuietly();
257
        if( featureType!=null ) {
258
            Tags tags = featureType.getTags();
259
            if( tags.has(TAG_LAYERVECT_MAXSCALE) ) {
260
                this.setMaxScale(tags.getInt(TAG_LAYERVECT_MAXSCALE, -1));
261
            }
262
            if( tags.has(TAG_LAYERVECT_MINSCALE) ) {
263
                this.setMinScale(tags.getInt(TAG_LAYERVECT_MINSCALE, -1));
264
            }
265
        }
266

    
267
        ToolsLocator.getDisposableManager().bind(dataStore);
268
    }
269
    
270
    
271

    
272
    public Envelope getFullEnvelope() throws ReadException {
273
        Envelope rAux;
274
        if (getFeatureStore() == null) {
275
            return null;
276
        }
277
        try {
278
            rAux = getFeatureStore().getEnvelope();
279
        } catch (BaseException e) {
280
            throw new ReadException(getName(), e);
281
        }
282

    
283
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
284
        // y alto 0.
285
        if (rAux == null || rAux.isEmpty() ) {
286
            return rAux;
287
        }
288
        // Si existe reproyecci?n, reproyectar el extent
289
        ICoordTrans ct = getCoordTrans();
290
        if (ct != null) {
291
            rAux = rAux.convert(ct);
292
            if (rAux==null || rAux.isEmpty() ) {
293
                try {
294
                    this.setAvailable(false);
295
                    throw new EnvelopeCantBeInitializedException();
296
                } catch (EnvelopeCantBeInitializedException e) {
297
                    this.addError(e);
298
                }
299
            }
300
        }
301
        return rAux;
302

    
303
    }
304

    
305
    public void setBaseQuery(FeatureQuery baseQuery) {
306
        this.baseQuery = baseQuery;
307
    }
308

    
309
    @Override
310
    public FeatureQuery getBaseQuery() {
311
        return this.baseQuery;
312
    }
313

    
314
    public void addBaseFilter(Evaluator filter) {
315
        if (this.baseQuery == null) {
316
            this.baseQuery = this.getFeatureStore().createFeatureQuery();
317
        }
318
        this.baseQuery.addFilter(filter);
319
    }
320

    
321
    public void addBaseFilter(String filter) {
322
        try {
323
            this.addBaseFilter(DALLocator.getDataManager().createExpresion(filter));
324
        } catch (InitializeException ex) {
325
            throw new RuntimeException("Can't create filter with '" + filter + "'", ex);
326
        }
327
    }
328

    
329
    /**
330
     * Draws using IFeatureIterator. This method will replace the old draw(...)
331
     * one.
332
     *
333
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
334
     * @param image
335
     * @param g
336
     * @param viewPort
337
     * @param cancel
338
     * @param scale
339
     * @throws ReadDriverException
340
     */
341
    public void draw(BufferedImage image,
342
            Graphics2D g,
343
            ViewPort viewPort,
344
            Cancellable cancel,
345
            double scale) throws ReadException {
346

    
347
        if (legend == null) {
348
            return;
349
        }
350

    
351
        if (!this.isWithinScale(scale)) {
352
            return;
353
        }
354
        if (cancel.isCanceled()) {
355
            return;
356
        }
357

    
358
        if (spatialCache.isEnabled()) {
359
            spatialCache.removeAll();
360
            legend.addDrawingObserver(this);
361
        }
362

    
363
        FeatureQuery featureQuery = createFeatureQuery();
364

    
365
        try {
366
            FeatureAttributeDescriptor featureAttributeDescriptor
367
                    = getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
368

    
369
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)) {
370
                IntersectsTimeEvaluator intersectsTimeEvaluator
371
                        = new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
372
                featureQuery.addFilter(intersectsTimeEvaluator);
373
            }
374
        } catch (DataException e1) {
375
            logger.error("Impossible to get the temporal filter", e1);
376
        }
377

    
378
        try {
379

    
380
            long tini = System.currentTimeMillis();
381

    
382
            legend.draw(image,
383
                    g,
384
                    viewPort,
385
                    cancel,
386
                    scale,
387
                    null,
388
                    getCoordTrans(),
389
                    getFeatureStore(),
390
                    featureQuery);
391

    
392
            logger.debug("Layer " + this.getName() + " drawn in "
393
                    + (System.currentTimeMillis() - tini) + " ms ("+this.getFeatureStore().getFullName()+").");
394

    
395
        } catch (LegendException e) {
396
            this.setAvailable(false);
397
            this.setError(e);
398
            throw new ReadException(getName(), e);
399
        } finally {
400
            if (spatialCache.isEnabled()) {
401
                legend.deleteDrawingObserver(this);
402
            }
403
        }
404
    }
405

    
406
    public void print(Graphics2D g,
407
            ViewPort viewPort,
408
            Cancellable cancel,
409
            double scale,
410
            PrintAttributes properties) throws ReadException {
411
        if (!this.isWithinScale(scale)) {
412
            return;
413
        }
414
        if (cancel.isCanceled()) {
415
            return;
416
        }
417
        FeatureQuery featureQuery = createFeatureQuery();
418

    
419
        try {
420
            legend.print(g,
421
                    viewPort,
422
                    cancel,
423
                    scale,
424
                    null,
425
                    getCoordTrans(),
426
                    getFeatureStore(),
427
                    featureQuery,
428
                    properties);
429

    
430
        } catch (LegendException e) {
431
            this.setVisible(false);
432
            this.setActive(false);
433
            throw new ReadException(getName(), e);
434
        }
435
    }
436

    
437
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
438
        if (this.legend == legend) {
439
            return;
440
        }
441
        if (this.legend != null && this.legend.equals(legend)) {
442
            return;
443
        }
444
        IVectorLegend oldLegend = this.legend;
445
        this.legend = legend;
446
        if (oldLegend != null) {
447
            oldLegend.removeLegendListener(this);
448
            oldLegend.deleteDrawingObserver(this);
449
        }
450
        if (legend != null) {
451
            this.legend.addDrawingObserver(this);
452
            this.legend.addLegendListener(this);
453
        }
454
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
455
        e.setLayer(this);
456
        updateDrawVersion();
457
        callLegendChanged(e);
458
    }
459

    
460
    /**
461
     * Devuelve la Leyenda de la capa.
462
     *
463
     * @return Leyenda.
464
     */
465
    public ILegend getLegend() {
466
        return legend;
467
    }
468

    
469
    public int getShapeType() throws ReadException {
470
        if (typeShape == -1) {
471
            FeatureType featureType = null;
472
            try {
473
                if (getDataStore() != null) {
474
                    featureType
475
                            = (((FeatureStore) getDataStore()).getDefaultFeatureType());
476
                }
477
            } catch (DataException e) {
478
                throw new ReadException(getName(), e);
479
            }
480
            if (featureType != null) {
481
                int indexGeom = featureType.getDefaultGeometryAttributeIndex();
482
                typeShape
483
                        = featureType.getAttributeDescriptor(indexGeom).getGeometryType();
484
            }
485
        }
486
        return typeShape;
487
    }
488

    
489
    /**
490
     * Returns the layer's geometry type
491
     *
492
     * @return the geometry type
493
     *
494
     * @throws ReadException if there is an error getting the geometry type
495
     */
496
    public GeometryType getGeometryType() throws ReadException {
497
        FeatureType featureType = null;
498
        try {
499
            if (getDataStore() != null) {
500
                featureType
501
                        = (((FeatureStore) getDataStore()).getDefaultFeatureType());
502
            }
503
        } catch (DataException e) {
504
            throw new ReadException(getName(), e);
505
        }
506
        return featureType == null ? null : featureType
507
                .getDefaultGeometryAttribute().getGeomType();
508
    }
509

    
510
    public void saveToState(PersistentState state) throws PersistenceException {
511

    
512
        FeatureStore featureStore = null;
513

    
514
        if (!this.isAvailable()) {
515
            logger.info("The '" + this.getName() + "' layer is not available, it will persist not.");
516
            return;
517
        }
518

    
519
        try {
520
            super.saveToState(state);
521

    
522
            if (getLegend() != null) {
523
                state.set("legend", getLegend());
524
            }
525

    
526
            featureStore = getFeatureStore();
527

    
528
            if (featureStore != null) {
529
                state.set("featureStore", featureStore);
530
            }
531
            if( this.dataStoreParameters!=null ) {
532
                state.set("featureStoreParameters", dataStoreParameters);
533
            }
534

    
535
            state.set("isLabeled", isLabeled);
536

    
537
            if (strategy != null) {
538
                state.set("labelingStrategy", strategy);
539
            }
540

    
541
            if (getLinkProperties() != null) {
542
                state.set("linkProperties", getLinkProperties());
543
            }
544

    
545
            state.set("typeShape", typeShape);
546
        } catch (PersistenceException ex) {
547
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
548
            throw ex;
549
        } catch (RuntimeException ex) {
550
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
551
            throw ex;
552
        }
553

    
554
    }
555

    
556
    @Override
557
    public void loadFromState(PersistentState state) throws PersistenceException {
558

    
559
        FeatureStore store = null;
560
        try {
561
            super.loadFromState(state);
562

    
563
            this.setIsLabeled(false);
564
            this.setLabelingStrategy(null);
565

    
566
            typeShape = state.getInt("typeShape", Geometry.TYPES.GEOMETRY);
567

    
568
            this.dataStoreParameters = (DataStoreParameters) state.get("featureStoreParameters");
569

    
570
            store = (FeatureStore) state.get("featureStore");
571
            if (store == null) { 
572
                if( this.dataStoreParameters == null ) {
573
                    this.setAvailable(false);
574
                    this.addError(new RuntimeException("Can't retrieve store information."));
575
                } else {
576
                    if( this.isVisible() ) {
577
                        try {
578
                            DataManager dataManager = DALLocator.getDataManager();
579
                            store = (FeatureStore) dataManager.openStore(
580
                                    this.dataStoreParameters.getProviderName(),
581
                                    this.dataStoreParameters
582
                            );
583
                            this.bindToDataStore(store);
584
                        } catch (Exception ex) {
585
                            this.setAvailable(false);
586
                            this.addError(ex);
587
                        }
588
                    }
589
                }
590
            } else {
591
                if (store.isBroken()) {
592
                    this.setAvailable(false);
593
                    this.addError(store.getBreakingsCause());
594
                }
595
                try {
596
                    this.bindToDataStore(store);
597
                } catch (Exception ex) {
598
                    this.setAvailable(false);
599
                    this.addError(ex);
600
                }
601
            }
602

    
603
            try {
604
                IVectorLegend vectorLegend = (IVectorLegend) state.get("legend");
605
                if( vectorLegend!=null ) {
606
                    this.setLegend(vectorLegend);
607
                }
608
            } catch (Exception ex) {
609
                this.setAvailable(false);
610
                this.addError(ex);
611
            }
612

    
613
            try {
614
                if (state.getBoolean("isLabeled", false)) {
615
                    this.setIsLabeled(true);
616
                    ILabelingStrategy labelingStrategy = (ILabelingStrategy) state.get("labelingStrategy");
617
                    this.setLabelingStrategy(labelingStrategy);
618
                }
619
            } catch (Exception ex) {
620
                this.setAvailable(false);
621
                this.addError(ex);
622
            }
623
            MapContext mc = this.getMapContext();
624
            if(mc != null){
625
                mc.addSelectionListener(this);
626
            }
627

    
628
        } catch (Throwable e) {
629
            String storeName = (store == null) ? "unknow" : store.getFullName();
630
            logger.warn("can't load layer '" + this.getName() + "' (store=" + storeName + ") from persisted state.", e);
631
            this.setAvailable(false);
632
            this.addError(e);
633
        }
634

    
635
    }
636

    
637
    /**
638
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
639
     * identifiquen la capa.
640
     *
641
     * @return DOCUMENT ME!
642
     */
643
    public String toString() {
644
        /*
645
         * Se usa internamente para que la parte de datos identifique de forma
646
         * un?voca las tablas
647
         */
648
        String ret = super.toString();
649

    
650
        return ret; //"layer" + ret.substring(ret.indexOf('@') + 1);
651
    }
652

    
653
    public boolean isEditing() {
654
        FeatureStore fs = getFeatureStore();
655
        if (fs == null) {
656
            /*
657
             * This happens when layer is not available, for example,
658
             * it was not possible to load from persistence
659
             */
660
            return false;
661
        } else {
662
            return fs.isEditing();
663
        }
664
    }
665

    
666
    public void setEditing(boolean b) throws StartEditionLayerException {
667

    
668
        try {
669
            throw new RuntimeException();
670
        } catch (Throwable th) {
671
            logger.info("This method is deprecated. ", th);
672
        }
673

    
674
        if (b == super.isEditing()) {
675
            return;
676
        }
677

    
678
        super.setEditing(b);
679
        FeatureStore fs = getFeatureStore();
680
        if (b) {
681
            try {
682
                fs.edit();
683
            } catch (DataException e) {
684
                throw new StartEditionLayerException(getName(), e);
685
            }
686
        }
687
        getSpatialCache().setEnabled("editing", b);
688
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
689
    }
690

    
691
    /**
692
     * @deprecated Use {@link #getSpatialCache()}
693
     */
694
    public void clearSpatialCache() {
695
        spatialCache.removeAll();
696
    }
697

    
698
    /**
699
     * @deprecated Use {@link #getSpatialCache()}
700
     */
701
    public boolean isSpatialCacheEnabled() {
702
        return spatialCache.isEnabled();
703
    }
704

    
705
    /**
706
     * @deprecated Use {@link #getSpatialCache()}
707
     */
708
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
709
        spatialCache.setEnabled(spatialCacheEnabled);
710
    }
711

    
712
    public SpatialCache getSpatialCache() {
713
        return spatialCache;
714
    }
715
    
716
    public void refreshSpatialCache(Envelope envelope) {
717
        if( this.featureStore==null) {
718
            return;
719
        }
720
        SpatialCache sc = this.getSpatialCache();
721
        sc.refresh(this.getName(), this.getFeatureStore(), envelope, this.getProjection());
722
    }
723

    
724
    /**
725
     * Siempre es un numero mayor de 1000
726
     *
727
     * @param maxFeatures
728
     */
729
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
730
        if (maxFeatures > spatialCache.getMaxFeatures()) {
731
            spatialCache.setMaxFeatures(maxFeatures);
732
        }
733

    
734
    }
735

    
736
    /**
737
     * This method returns a boolean that is used by the FPopMenu to make
738
     * visible the properties menu or not. It is visible by default, and if a
739
     * later don't have to show this menu only has to override this method.
740
     *
741
     * @return If the properties menu is visible (or not)
742
     */
743
    public boolean isPropertiesMenuVisible() {
744
        return true;
745
    }
746

    
747
    public void reload() throws ReloadLayerException {
748
        super.reload();
749
        try {
750
            getFeatureStore().refresh();
751
        } catch (Exception e) {
752
            throw new ReloadLayerException(getName(), e);
753
        }
754
    }
755

    
756
    protected void setLoadSelection(Object xml) {
757
        // this.loadSelection = xml;
758
    }
759

    
760
    protected void setLoadLegend(IVectorLegend legend) {
761
        this.loadLegend = legend;
762
    }
763

    
764
    protected void putLoadSelection() {
765
        // if (this.loadSelection == null) return;
766
        // try {
767
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
768
        // } catch (ReadDriverException e) {
769
        // throw new XMLException(e);
770
        // }
771
        // this.loadSelection = null;
772

    
773
    }
774

    
775
    protected void putLoadLegend() throws LegendLayerException {
776
        if (this.loadLegend == null) {
777
            return;
778
        }
779
        this.setLegend(this.loadLegend);
780
        this.loadLegend = null;
781
    }
782

    
783
    protected void cleanLoadOptions() {
784
        this.loadLegend = null;
785
    }
786

    
787
    public boolean isWritable() {
788
        return getFeatureStore().allowWrite();
789
    }
790

    
791
    public FLayer cloneLayer() throws Exception {
792
        FLyrVect clonedLayer = new FLyrVect();
793
        if( this.dataStoreParameters!=null ) {
794
            clonedLayer.dataStoreParameters = (DataStoreParameters) this.dataStoreParameters.getCopy();
795
        }
796
        if( this.featureStore!=null ) {
797
            clonedLayer.featureStore = this.featureStore;
798
            ToolsLocator.getDisposableManager().bind(clonedLayer.featureStore);
799
            clonedLayer.delegate(clonedLayer.featureStore);
800
            clonedLayer.featureStore.addObserver(clonedLayer);
801
        }
802
        clonedLayer.setVisible(isVisible());
803
        clonedLayer.setName(getName());
804
        clonedLayer.setCoordTrans(getCoordTrans());
805

    
806
        if( this.getLegend()!=null ) {
807
            clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
808
        }
809

    
810
        clonedLayer.setIsLabeled(isLabeled());
811
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
812
        if (labelingStrategy != null) {
813
            clonedLayer.setLabelingStrategy(labelingStrategy);
814
        }
815

    
816
        clonedLayer.setMaxScale(this.getMaxScale());
817
        clonedLayer.setMinScale(this.getMinScale());
818
        return clonedLayer;
819
    }
820

    
821
    public boolean isLabeled() {
822
        return isLabeled;
823
    }
824

    
825
    public void setIsLabeled(boolean isLabeled) {
826
        this.isLabeled = isLabeled;
827
    }
828

    
829
    public ILabelingStrategy getLabelingStrategy() {
830
        return strategy;
831
    }
832

    
833
    public void setLabelingStrategy(ILabelingStrategy strategy) {
834
        this.strategy = strategy;
835
        if (strategy == null) {
836
            return;
837
        }
838
        strategy.setLayer(this);
839
        updateDrawVersion();
840
    }
841

    
842
    public void drawLabels(BufferedImage image,
843
            Graphics2D g,
844
            ViewPort viewPort,
845
            Cancellable cancel,
846
            double scale,
847
            double dpi) throws ReadException {
848
        if (strategy != null && isWithinScale(scale)) {
849
            strategy.draw(image, g, scale, viewPort, cancel, dpi);
850
        }
851
    }
852

    
853
    public void printLabels(Graphics2D g,
854
            ViewPort viewPort,
855
            Cancellable cancel,
856
            double scale,
857
            PrintAttributes properties) throws ReadException {
858
        if (strategy != null) {
859
            strategy.print(g, scale, viewPort, cancel, properties);
860
        }
861
    }
862

    
863
    /**
864
     * Return true, because a Vectorial Layer supports HyperLink
865
     *
866
     * @deprecated the hiperlink functionaliti is out the layer now
867
     */
868
    public boolean allowLinks() {
869
        return false;
870
    }
871

    
872
    public void load() throws LoadLayerException {
873
        super.load();
874
    }
875

    
876
    public FeatureStore getFeatureStore() {
877
        return (FeatureStore) getDataStore();
878
    }
879

    
880
    public FeatureQuery createFeatureQuery() {
881
        if (this.baseQuery == null) {
882
            return this.getFeatureStore().createFeatureQuery();
883
        }
884
        try {
885
            return (FeatureQuery) baseQuery.clone();
886
        } catch (CloneNotSupportedException ex) {
887
            throw new RuntimeException(ex);
888
        }
889
    }
890

    
891
    /**
892
     * @deprecated use instead
893
     * {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
894
     */
895
    public FeatureSet queryByPoint(Point2D mapPoint,
896
            double tol,
897
            FeatureType featureType) throws DataException {
898
        logger.warn("Deprecated use of queryByPoint.");
899
        GeometryManager manager = GeometryLocator.getGeometryManager();
900
        org.gvsig.fmap.geom.primitive.Point center;
901
        try {
902
            center
903
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
904
                            SUBTYPES.GEOM2D);
905
            center.setX(mapPoint.getX());
906
            center.setY(mapPoint.getY());
907
            Circle circle
908
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
909
            circle.setPoints(center, tol);
910
            return queryByGeometry(circle, featureType);
911
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
912
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
913
        }
914
    }
915

    
916
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
917
            double tol,
918
            FeatureType featureType) throws DataException {
919
        GeometryManager manager = GeometryLocator.getGeometryManager();
920
        try {
921
            Circle circle
922
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
923
            circle.setPoints(point, tol);
924
            return queryByGeometry(circle, featureType);
925
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
926
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
927
        }
928
    }
929

    
930
    public FeatureQuery createQueryByPoint(double x, double y,
931
            double tol,
932
            FeatureType featureType) throws DataException {
933
        GeometryManager manager = GeometryLocator.getGeometryManager();
934
        org.gvsig.fmap.geom.primitive.Point center;
935
        try {
936
            center
937
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
938
                            SUBTYPES.GEOM2D);
939
            center.setX(x);
940
            center.setY(y);
941
            Circle circle
942
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
943
            circle.setPoints(center, tol);
944
            return createQueryByGeometry(circle, featureType);
945
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
946
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
947
        }
948
    }
949

    
950
    /**
951
     * Input geom must be in the CRS of the view.
952
     *
953
     * @param geom
954
     * @param featureType
955
     * @return
956
     * @throws DataException
957
     */
958
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
959
        FeatureQuery featureQuery = createFeatureQuery();
960
        featureQuery.setFeatureType(featureType);
961

    
962
        Geometry query_geo = this.transformToSourceCRS(geom, true);
963
        IProjection query_proj = getMapContext().getProjection();
964
        if (this.getCoordTrans() != null) {
965
            query_proj = this.getCoordTrans().getPOrig();
966
        }
967
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
968
                query_geo,
969
                query_proj,
970
                featureStore
971
        );
972
        featureQuery.setFilter(iee);
973
        featureQuery.setAttributeNames(null);
974
        return getFeatureStore().getFeatureSet(featureQuery);
975

    
976
    }
977
    
978
    public FeatureQuery createQueryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
979
        FeatureQuery featureQuery = createFeatureQuery();
980
        featureQuery.setFeatureType(featureType);
981

    
982
        Geometry query_geo = this.transformToSourceCRS(geom, true);
983
        IProjection query_proj = getMapContext().getProjection();
984
        if (this.getCoordTrans() != null) {
985
            query_proj = this.getCoordTrans().getPOrig();
986
        }
987
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
988
                query_geo,
989
                query_proj,
990
                featureStore
991
        );
992
        featureQuery.setFilter(iee);
993
        featureQuery.setAttributeNames(null);
994
        return featureQuery;
995

    
996
    }
997
    
998
    public FeatureSet queryByContainedInGeometry(Geometry geom, FeatureType featureType) throws DataException {
999
        FeatureQuery featureQuery = createFeatureQuery();
1000
        featureQuery.setFeatureType(featureType);
1001

    
1002
        Geometry query_geo = this.transformToSourceCRS(geom, true);
1003
        IProjection query_proj = getMapContext().getProjection();
1004
        if (this.getCoordTrans() != null) {
1005
            query_proj = this.getCoordTrans().getPOrig();
1006
        }
1007
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
1008
                query_geo,
1009
                query_proj,
1010
                featureStore
1011
        );
1012
        featureQuery.setFilter(iee);
1013
        featureQuery.setAttributeNames(null);
1014
        return getFeatureStore().getFeatureSet(featureQuery);
1015

    
1016
    }
1017
    /**
1018
     * It return the {@link FeatureSet} that intersects with the envelope.
1019
     *
1020
     * @param envelope envelope that defines the area for the query.
1021
     * @param featureType only the features with this feature type are used in
1022
     * the query.
1023
     * @return the set of features that intersect with the envelope.
1024
     * @throws DataException
1025
     */
1026
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1027
        return queryByEnvelope(envelope, featureType, null);
1028
    }
1029

    
1030
    /**
1031
     * It return the {@link FeatureSet} that intersects with the envelope.
1032
     *
1033
     * @param envelope envelope that defines the area for the query in viewport
1034
     * CRS
1035
     * @param featureType only the features with this feature type are used in
1036
     * the query.
1037
     * @param names the feature attributes that have to be checked.
1038
     * @return the set of features that intersect with the envelope.
1039
     * @throws DataException
1040
     */
1041
    public FeatureSet queryByEnvelope(Envelope envelope,
1042
            FeatureType featureType,
1043
            String[] names) throws DataException {
1044
        FeatureQuery featureQuery = createFeatureQuery();
1045
        if (names == null) {
1046
            featureQuery.setFeatureType(featureType);
1047
        } else {
1048
            featureQuery.setAttributeNames(names);
1049
            featureQuery.setFeatureTypeId(featureType.getId());
1050
        }
1051

    
1052
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1053
        IProjection query_proj = getMapContext().getProjection();
1054
        if (this.getCoordTrans() != null) {
1055
            query_proj = this.getCoordTrans().getPOrig();
1056
        }
1057

    
1058
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
1059
                query_env.getGeometry(),
1060
                query_proj,
1061
                featureStore
1062
        );
1063
        featureQuery.setFilter(iee);
1064
        return getFeatureStore().getFeatureSet(featureQuery);
1065

    
1066
    }
1067
    
1068
    public FeatureSet queryByContainedInEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1069
        return queryByContainedInEnvelope(envelope, featureType, null);
1070
    }
1071
    
1072
    public FeatureSet queryByContainedInEnvelope(Envelope envelope,
1073
            FeatureType featureType,
1074
            String[] names) throws DataException {
1075
        FeatureQuery featureQuery = createFeatureQuery();
1076
        if (names == null) {
1077
            featureQuery.setFeatureType(featureType);
1078
        } else {
1079
            featureQuery.setAttributeNames(names);
1080
            featureQuery.setFeatureTypeId(featureType.getId());
1081
        }
1082

    
1083
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1084
        IProjection query_proj = getMapContext().getProjection();
1085
        if (this.getCoordTrans() != null) {
1086
            query_proj = this.getCoordTrans().getPOrig();
1087
        }
1088

    
1089
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
1090
                query_env.getGeometry(),
1091
                query_proj,
1092
                featureStore
1093
        );
1094
        featureQuery.setFilter(iee);
1095
        return getFeatureStore().getFeatureSet(featureQuery);
1096

    
1097
    }
1098
    
1099
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1100
            DataException {
1101

    
1102
        return getInfo(p, tolerance, cancel, true);
1103
    }
1104

    
1105
    public DynObjectSet getInfo(Point p,
1106
            double tolerance,
1107
            Cancellable cancel,
1108
            boolean fast) throws LoadLayerException, DataException {
1109
        Point2D infop = new Point2D.Double(p.x, p.y);
1110
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1111
        return queryByPoint(pReal,
1112
                tolerance,
1113
                getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1114
    }
1115

    
1116
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1117
            double tolerance) throws LoadLayerException, DataException {
1118
        return queryByPoint(p, tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
1119
    }
1120

    
1121
    @Override
1122
    public void legendCleared(LegendClearEvent event) {
1123
        this.updateDrawVersion();
1124
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(legend, event);
1125
        this.callLegendChanged(e);
1126
    }
1127

    
1128
    @Override
1129
    public boolean symbolChanged(SymbolLegendEvent e) {
1130
        this.updateDrawVersion();
1131
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
1132
        this.callLegendChanged(ev);
1133
        return true;
1134
    }
1135

    
1136
    public void update(Observable observable, Object notification) {
1137
        if (observable.equals(this.featureStore)) {
1138
            if (notification instanceof FeatureStoreNotification) {
1139
                FeatureStoreNotification event
1140
                        = (FeatureStoreNotification) notification;
1141
                if (event.getType() == FeatureStoreNotification.AFTER_DELETE
1142
                        || event.getType() == FeatureStoreNotification.AFTER_UNDO
1143
                        || event.getType() == FeatureStoreNotification.AFTER_REDO
1144
                        || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1145
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1146
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1147
//                        || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1148
                        || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1149
                    this.updateDrawVersion();
1150

    
1151
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
1152
                    getSpatialCache().setEnabled("editing", false);
1153

    
1154
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1155
                    this.updateDrawVersion();
1156

    
1157
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
1158
                    getSpatialCache().setEnabled("editing", true);
1159
                    
1160
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1161

    
1162
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE) {
1163
                    //If a transform has to be applied, try to reload the layer.
1164
                    try {
1165
                        reload();
1166
                    } catch (ReloadLayerException e) {
1167
                        logger.info("While reloading layer.", e);
1168
                        this.setAvailable(false);
1169
                    }
1170
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1171
                    this.setAvailable(false);
1172
                } else if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1173
                    this.setAvailable(true);
1174
                    getSpatialCache().setEnabled("editing", false);
1175
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1176
                    this.updateDrawVersion();
1177
                } else if (event.getType() == FeatureStoreNotification.SELECTION_CHANGE) {
1178
                    callSelectionChanged();
1179
                }
1180
            }
1181
        } else if (notification instanceof FeatureDrawnNotification
1182
                && spatialCache.isEnabled()) {
1183
            // This code is needed in editing mode
1184
            // for all layers involved in snapping
1185
            // (including the layer being edited)            
1186
            Geometry geometry
1187
                    = ((FeatureDrawnNotification) notification).getDrawnGeometry();
1188
            spatialCache.insert(geometry.getEnvelope(), geometry);
1189
        }
1190
    }
1191

    
1192
    public void setLayerToSnap(boolean enable) {
1193
        MapContext mapContext = this.getMapContext();
1194
        Set<FLyrVect> layers = (Set<FLyrVect>) mapContext.getLayersToSnap();
1195
        if( enable ) {
1196
            layers.add(this);
1197
        } else {
1198
            layers.remove(this);
1199
        }
1200
        mapContext.setLayersToSnap(layers);
1201
        this.getSpatialCache().setEnabled(enable);
1202
    }
1203
    
1204
    public boolean isLayerToSnap() {
1205
        MapContext mapContext = this.getMapContext();
1206
        if ( mapContext == null) {
1207
            return false;
1208
        }
1209
        return mapContext.getLayersToSnap().contains(this);
1210
    }
1211

    
1212
    /*
1213
     * (non-Javadoc)
1214
     *
1215
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1216
     */
1217
    public Set getMetadataChildren() {
1218
        Set ret = new TreeSet();
1219
        ret.add(this.featureStore);
1220
        return ret;
1221
    }
1222

    
1223
    /*
1224
     * (non-Javadoc)
1225
     *
1226
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1227
     */
1228
    public Object getMetadataID() throws MetadataException {
1229
        return "Layer(" + this.getName() + "):"
1230
                + this.featureStore.getMetadataID();
1231
    }
1232

    
1233
    public GeometryType getTypeVectorLayer() throws DataException,
1234
            LocatorException,
1235
            GeometryTypeNotSupportedException,
1236
            GeometryTypeNotValidException {
1237
        // Este metodo esta duplicado ?? getShapeType()
1238
        FeatureStore fs = this.getFeatureStore();
1239
        FeatureType fType = fs.getDefaultFeatureType();
1240
        FeatureAttributeDescriptor attr
1241
                = fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1242
        GeometryType geomType = attr.getGeomType();
1243
        return geomType;
1244
    }
1245

    
1246
    public static class SelfRegister
1247
            implements Callable {
1248

    
1249
        @Override
1250
        public Object call() {
1251
          registerPersistence();
1252
          registerDefaultVectorLayer();
1253
          DynObjectManager dynObjectManager = ToolsLocator.getDynObjectManager();
1254
          dynObjectManager.registerTag(TAG_LAYERVECT_MAXSCALE, "Sets the maximum scale visible. Higher scales won't be drawn, -1 if not defined");
1255
          dynObjectManager.registerTag(TAG_LAYERVECT_MINSCALE, "Sets the minimum scale visible. Lower scales won't be drawn, -1 if not defined");
1256
          return true;
1257
        }
1258
        
1259
        private Object registerDefaultVectorLayer() {
1260
            MapContextManager manager = MapContextLocator.getMapContextManager();
1261
            manager.registerLayer(FeatureStore.class, FLyrVect.class);
1262
            return true;          
1263
        }
1264
        
1265
        private Object registerPersistence() {
1266
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1267

    
1268
            DynStruct definition
1269
                    = manager.addDefinition(FLyrVect.class,
1270
                            "FLyrVect",
1271
                            "FLyrVect Persistence definition",
1272
                            null,
1273
                            null);
1274
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1275
                    "FLyrDefault");
1276

    
1277
            definition.addDynFieldObject("legend")
1278
                    .setClassOfValue(IVectorLegend.class)
1279
                    .setMandatory(false);
1280
            definition.addDynFieldObject("featureStore")
1281
                    .setClassOfValue(FeatureStore.class)
1282
                    .setMandatory(false);
1283
            definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1284
            definition.addDynFieldInt("typeShape").setMandatory(true);
1285
            definition.addDynFieldObject("labelingStrategy")
1286
                    .setClassOfValue(ILabelingStrategy.class)
1287
                    .setMandatory(false);
1288
            definition.addDynFieldObject("featureStoreParameters")
1289
                    .setClassOfValue(OpenFeatureStoreParameters.class)
1290
                    .setMandatory(false);
1291

    
1292
            return true;
1293
        }
1294
    }
1295

    
1296
    @Override
1297
    protected void doDispose() throws BaseException {
1298
        dispose(featureStore);
1299
        spatialCache.removeAll();
1300
    }
1301

    
1302
    /**
1303
     * Returns envelope in layer's data source CRS from envelope provided in
1304
     * viewport CRS
1305
     *
1306
     * @param lyr
1307
     * @param env
1308
     * @return
1309
     */
1310
    public static Envelope fromViewPortCRSToSourceCRS(FLayer lyr, Envelope env) {
1311

    
1312
        if (lyr == null || env == null) {
1313
            return null;
1314
        }
1315

    
1316
        ICoordTrans ct = lyr.getCoordTrans();
1317
        if (ct == null) {
1318
            return env;
1319
        } else {
1320
            return env.convert(ct.getInverted());
1321
        }
1322
    }
1323

    
1324
    public Geometry transformToSourceCRS(Geometry geom, boolean clone) {
1325
        return fromViewPortCRSToSourceCRS(this, geom, clone);
1326
    }
1327

    
1328
    /**
1329
     * Returns geometry in layer's data source CRS from geometry provided in
1330
     * viewport CRS
1331
     *
1332
     * @param lyr
1333
     * @param geo
1334
     * @param clone
1335
     * @return
1336
     * @deprecated use the transformToSourceCRS method of layer.
1337
     */
1338
    public static Geometry fromViewPortCRSToSourceCRS(
1339
            FLayer lyr,
1340
            Geometry geo,
1341
            boolean clone) {
1342

    
1343
        if (lyr == null || geo == null) {
1344
            return null;
1345
        }
1346
        ICoordTrans ct = lyr.getCoordTrans();
1347
        Geometry resp = geo;
1348
        if (clone) {
1349
            resp = resp.cloneGeometry();
1350
        }
1351
        if (ct != null) {
1352
            resp.reProject(ct.getInverted());
1353
        }
1354
        return resp;
1355
    }
1356

    
1357
    public Iterator iterator() {
1358
        return this.getFeatureStore().iterator();
1359
    }
1360

    
1361
    protected class EnvelopeCantBeInitializedException
1362
            extends BaseException {
1363

    
1364
        /**
1365
         *
1366
         */
1367
        private static final long serialVersionUID = 4572797479347381552L;
1368
        private final static String MESSAGE_FORMAT = "The envelope can't be initialized, maybe the layer has a wrong projection. Change the projection in layer properties of the add layer dialog to try fix it.";
1369
        private final static String MESSAGE_KEY = "_EnvelopeCantBeInitializedException";
1370

    
1371
        public EnvelopeCantBeInitializedException() {
1372
            super(MESSAGE_FORMAT, null, MESSAGE_KEY, serialVersionUID);
1373
        }
1374
    }
1375

    
1376
    @Override
1377
    public String getInfoString() {
1378
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
1379

    
1380
        if (!this.isAvailable()) {
1381
            builder.title().labelkey("Warning");
1382
            builder.text().value("The layer is not available.");
1383
        }
1384

    
1385
        Envelope env = null;
1386
        FeatureAttributeDescriptor attrgeom = null;
1387

    
1388
        try {
1389
            env = this.getFullEnvelope();
1390
        } catch (Exception ex) {
1391
        }
1392
        FeatureStore store = this.getFeatureStore();
1393
        try {
1394
            FeatureType ft = store.getDefaultFeatureType();
1395
            attrgeom = ft.getDefaultGeometryAttribute();
1396
        } catch (Exception ex) {
1397
        }
1398

    
1399
        builder.title().labelkey("Data_source");
1400
        builder.property().labelkey("Source_type").value(this.getProviderName());
1401
        builder.property().labelkey("origen").value(store==null? "not available":store.getFullName());
1402
        if (this.getDataStoreParameters() instanceof FilesystemStoreParameters) {
1403
            File f = ((FilesystemStoreParameters) (this.getDataStoreParameters())).getFile();
1404
            if (f != null && f.exists()) {
1405
                builder.property().labelkey("_Size").value("%d bytes", f.length());
1406
            }
1407
        }
1408
        if (attrgeom != null) {
1409
            builder.property().labelkey("_Geometry_column").value(attrgeom.getName());
1410
            builder.property().labelkey("_Geometry_type").value(attrgeom.getGeomType().getFullName());
1411
        }
1412

    
1413
        builder.title().labelkey("_Coordenadas_geograficas");
1414
        if (this.isAvailable()) {
1415
            builder.envelope().value(env);
1416
        }
1417

    
1418
        builder.title().labelkey("_Projection");
1419
        if (this.isAvailable()) {
1420
            builder.property().value(this.getProjection());
1421
            builder.text().asWKT(this.getProjection());
1422
        }
1423
        return builder.toString();
1424
    }
1425

    
1426
    @Override
1427
    public boolean isTemporary() {
1428
        if (this.featureStore != null) {
1429
            if (this.featureStore.isTemporary()) {
1430
                return true;
1431
            }
1432
        }
1433
        return super.isTemporary();
1434
    }
1435
    
1436
    private String getProviderName() {
1437
        if( this.featureStore!=null ) {
1438
            return this.featureStore.getProviderName();
1439
        }
1440
        if( this.dataStoreParameters!=null ) {
1441
            return this.dataStoreParameters.getProviderName();
1442
        }
1443
        return null;
1444
    }
1445
    
1446
    public DataStoreParameters getDataStoreParameters() {
1447
        if( this.featureStore!=null ) {
1448
            return this.featureStore.getParameters();
1449
        }
1450
        if( this.dataStoreParameters!=null ) {
1451
            return this.dataStoreParameters;
1452
        }
1453
        return null;
1454
    }
1455
    
1456
    public IProjection getProjection() {
1457
        if( this.featureStore==null) {
1458
            if(this.dataStoreParameters==null) {
1459
                return null;
1460
            }
1461
            if(!this.isVisible()){
1462
                return null;
1463
            }
1464
            try {
1465
                DataManager dataManager = DALLocator.getDataManager();
1466
                DataStore dataStore = dataManager.openStore(
1467
                        this.dataStoreParameters.getProviderName(),
1468
                        this.dataStoreParameters
1469
                );
1470
                this.bindToDataStore(dataStore);
1471
                IProjection projection = (IProjection) dataStore.getDynValue(FeatureStore.METADATA_CRS);
1472
                if (projection != null) {
1473
                    this.setProjection(projection);
1474
                }
1475
                if (projection != null && this.getMapContext() != null) {
1476
                    IProjection mapContextProj = this.getMapContext().getProjection();
1477
                    if (!projection.getAbrev().equals(mapContextProj.getAbrev())) {
1478
                        ICoordTrans ct = projection.getCT(mapContextProj);
1479
                        this.setCoordTrans(ct);
1480
                    } else {
1481
                        this.setCoordTrans(null);
1482
                    }
1483
                }
1484
            } catch (Exception ex) {
1485
                throw new RuntimeException("Can't set visibility to layer", ex);
1486
            }
1487
        }
1488
        return super.getProjection();
1489
    }
1490
    
1491
    private void callSelectionChanged() {
1492
        this.updateDrawVersion(false);
1493
        SelectionEvent e = new SelectionEvent();
1494
        for (LayerListener listener : this.layerListeners) {
1495
            if( listener instanceof SelectionListener ) {
1496
                SelectionListener l = (SelectionListener) listener;
1497
                try {
1498
                    l.selectionChanged(e);
1499
                } catch (Exception ex) {
1500
                    logger.warn("Error calling listener '" + listener.toString() + "'.", ex);
1501
                }
1502
            }
1503
        }
1504
    }    
1505

    
1506
    @Override
1507
    public void invalidate() {
1508
        this.updateDrawVersion();
1509
    }
1510
    
1511
    @Override
1512
    public Object getProperty(Object key) {
1513
        Object v = properties.getProperty(key);
1514
        if( v == null ) {
1515
            FeatureStore store = this.getFeatureStore();
1516
            if( store!= null ) {
1517
                FeatureType ft = store.getDefaultFeatureTypeQuietly();
1518
                if(ft != null) {
1519
                    v = ft.getTags().get("Layer."+key);
1520
                }
1521
            }
1522
        }
1523
        return v;
1524
    }
1525

    
1526
}