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

History | View | Annotate | Download (46.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or 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.AffineTransform;
28
import java.awt.geom.Point2D;
29
import java.awt.image.BufferedImage;
30
import java.io.File;
31
import java.util.Iterator;
32
import java.util.Set;
33
import java.util.TreeSet;
34
import java.util.logging.Level;
35
import java.util.logging.Logger;
36

    
37
import org.cresques.cts.ICoordTrans;
38
import org.cresques.cts.IProjection;
39
import org.slf4j.LoggerFactory;
40

    
41
import org.gvsig.compat.print.PrintAttributes;
42
import org.gvsig.fmap.dal.DALLocator;
43
import org.gvsig.fmap.dal.DataStore;
44
import org.gvsig.fmap.dal.exception.DataException;
45
import org.gvsig.fmap.dal.exception.InitializeException;
46
import org.gvsig.fmap.dal.exception.ReadException;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.FeatureQuery;
49
import org.gvsig.fmap.dal.feature.FeatureSet;
50
import org.gvsig.fmap.dal.feature.FeatureStore;
51
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
52
import org.gvsig.fmap.dal.feature.FeatureType;
53
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
54
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
55
import org.gvsig.fmap.geom.Geometry;
56
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
57
import org.gvsig.fmap.geom.Geometry.TYPES;
58
import org.gvsig.fmap.geom.GeometryLocator;
59
import org.gvsig.fmap.geom.GeometryManager;
60
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
61
import org.gvsig.fmap.geom.primitive.Circle;
62
import org.gvsig.fmap.geom.primitive.Envelope;
63
import org.gvsig.fmap.geom.type.GeometryType;
64
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
65
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
66
import org.gvsig.fmap.mapcontext.MapContextLocator;
67
import org.gvsig.fmap.mapcontext.MapContextManager;
68
import org.gvsig.fmap.mapcontext.ViewPort;
69
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
70
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
71
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
72
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
73
import org.gvsig.fmap.mapcontext.layers.DefaultLayerInformationBuilder;
74
import org.gvsig.fmap.mapcontext.layers.FLayer;
75
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
76
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
77
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
78
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
79
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
80
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
81
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
82
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
83
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
84
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
85
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
86
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
87
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
88
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
89
import org.gvsig.metadata.exceptions.MetadataException;
90
import org.gvsig.tools.ToolsLocator;
91
import org.gvsig.tools.dynobject.DynObjectSet;
92
import org.gvsig.tools.dynobject.DynStruct;
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

    
104
/**
105
 * Capa b?sica Vectorial.
106
 *
107
 */
108
public class FLyrVect
109
        extends FLyrDefault
110
        implements VectorLayer,
111
        LegendContentsChangedListener, Observer {
112

    
113
    final static private org.slf4j.Logger logger
114
            = LoggerFactory.getLogger(FLyrVect.class);
115
    private final GeometryManager geomManager
116
            = GeometryLocator.getGeometryManager();
117

    
118
    /**
119
     * Leyenda de la capa vectorial
120
     */
121
    private IVectorLegend legend;
122
    private int typeShape = -1;
123
    private FeatureStore featureStore = null;
124
    private SpatialCache spatialCache = new SpatialCache();
125

    
126
    /**
127
     * An implementation of gvSIG spatial index
128
     */
129
    // protected ISpatialIndex spatialIndex = null;
130
    private IVectorLegend loadLegend = null;
131

    
132
    private boolean isLabeled;
133
    protected ILabelingStrategy strategy;
134
//        private ReprojectDefaultGeometry reprojectTransform;
135
    private FeatureQuery baseQuery = null;
136

    
137
    public FLyrVect() {
138
        super();
139
    }
140

    
141
    @Override
142
    public String getTocImageIcon() {
143
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
144
    }
145

    
146
    /**
147
     * Return the store associated to the layer.
148
     *
149
     * @return the store
150
     */
151
    @Override
152
    public DataStore getDataStore() {
153
        return featureStore;
154
    }
155

    
156
    /**
157
     * Asigna el data-store a la capa. Esta operacion no se deneria poder hacer
158
     * desde fuera de la clase.
159
     *
160
     * @param dataStore
161
     * @throws LoadLayerException
162
     * @deprecated use {@link #bindToDataStore(DataStore)}
163
     */
164
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
165
        bindToDataStore(dataStore);
166
    }
167

    
168
    /**
169
     * Enlaza la capa con el DataStore indicado.
170
     *
171
     * @param dataStore
172
     * @throws LoadLayerException
173
     */
174
    protected void bindToDataStore(DataStore dataStore) throws LoadLayerException {
175
        if (this.featureStore != null && this.featureStore != dataStore) {
176
            this.featureStore.deleteObserver(this);
177
        }
178

    
179
        featureStore = (FeatureStore) dataStore;
180

    
181
        MapContextManager mapContextManager
182
                = MapContextLocator.getMapContextManager();
183

    
184
        //Set the legend
185
        IVectorLegend legend
186
                = (IVectorLegend) mapContextManager.getLegend(dataStore);
187

    
188
        if (legend == null) {
189
            throw new LegendLayerException(this.getName());
190
        }
191

    
192
        this.setLegend(legend);
193

    
194
        //Set the labeling strategy
195
        ILabelingStrategy labeler
196
                = (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
197

    
198
        if (labeler != null) {
199
            labeler.setLayer(this);
200
            this.setLabelingStrategy(labeler);
201
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
202
            // etiquetes?????
203
        }
204

    
205
        this.delegate(dataStore);
206

    
207
        dataStore.addObserver(this);
208

    
209
        ToolsLocator.getDisposableManager().bind(dataStore);
210
    }
211

    
212
    public Envelope getFullEnvelope() throws ReadException {
213
        Envelope rAux;
214
        if (getFeatureStore() == null) {
215
            return null;
216
        }
217
        try {
218
            rAux = getFeatureStore().getEnvelope();
219
        } catch (BaseException e) {
220
            throw new ReadException(getName(), e);
221
        }
222

    
223
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
224
        // y alto 0.
225
        if (rAux == null || rAux.isEmpty() || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
226
                && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
227
            try {
228
                rAux
229
                        = geomManager.createEnvelope(0, 0, 90, 90, SUBTYPES.GEOM2D);
230
            } catch (CreateEnvelopeException e) {
231
                logger.error("Error creating the envelope", e);
232
                e.printStackTrace();
233
            }
234
        }
235
        // Si existe reproyecci?n, reproyectar el extent
236
        ICoordTrans ct = getCoordTrans();
237
        if (ct != null) {
238
            boolean originalEnvelopeIsEmpty = rAux.isEmpty();
239
            rAux = rAux.convert(ct);
240
            if (!originalEnvelopeIsEmpty && rAux.isEmpty()) {
241
                try {
242
                    this.setAvailable(false);
243
                    throw new EnvelopeCantBeInitializedException();
244
                } catch (EnvelopeCantBeInitializedException e) {
245
                    this.addError(e);
246
                }
247
            }
248
        }
249
        return rAux;
250

    
251
    }
252

    
253
    public void setBaseQuery(FeatureQuery baseQuery) {
254
        this.baseQuery = baseQuery;
255
    }
256

    
257
    @Override
258
    public FeatureQuery getBaseQuery() {
259
        return this.baseQuery;
260
    }
261

    
262
    public void addBaseFilter(Evaluator filter) {
263
        if (this.baseQuery == null) {
264
            this.baseQuery = this.getFeatureStore().createFeatureQuery();
265
        }
266
        this.baseQuery.addFilter(filter);
267
    }
268

    
269
    public void addBaseFilter(String filter) {
270
        try {
271
            this.addBaseFilter(DALLocator.getDataManager().createExpresion(filter));
272
        } catch (InitializeException ex) {
273
            throw new RuntimeException("Can't create filter with '" + filter + "'", ex);
274
        }
275
    }
276

    
277
    /**
278
     * Draws using IFeatureIterator. This method will replace the old draw(...)
279
     * one.
280
     *
281
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
282
     * @param image
283
     * @param g
284
     * @param viewPort
285
     * @param cancel
286
     * @param scale
287
     * @throws ReadDriverException
288
     */
289
    public void draw(BufferedImage image,
290
            Graphics2D g,
291
            ViewPort viewPort,
292
            Cancellable cancel,
293
            double scale) throws ReadException {
294

    
295
        if (legend == null) {
296
            return;
297
        }
298

    
299
        if (!this.isWithinScale(scale)) {
300
            return;
301
        }
302
        if (cancel.isCanceled()) {
303
            return;
304
        }
305

    
306
        if (spatialCache.isEnabled()) {
307
            spatialCache.clearAll();
308
            legend.addDrawingObserver(this);
309
        }
310

    
311
        FeatureQuery featureQuery = createFeatureQuery();
312

    
313
        try {
314
            FeatureAttributeDescriptor featureAttributeDescriptor
315
                    = getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
316

    
317
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)) {
318
                IntersectsTimeEvaluator intersectsTimeEvaluator
319
                        = new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
320
                featureQuery.addFilter(intersectsTimeEvaluator);
321
            }
322
        } catch (DataException e1) {
323
            logger.error("Impossible to get the temporal filter", e1);
324
        }
325

    
326
        try {
327

    
328
            long tini = System.currentTimeMillis();
329

    
330
            legend.draw(image,
331
                    g,
332
                    viewPort,
333
                    cancel,
334
                    scale,
335
                    null,
336
                    getCoordTrans(),
337
                    getFeatureStore(),
338
                    featureQuery);
339

    
340
            logger.debug("Layer " + this.getName() + " drawn in "
341
                    + (System.currentTimeMillis() - tini) + " milliseconds.");
342

    
343
        } catch (LegendException e) {
344
            this.setAvailable(false);
345
            this.setError(e);
346
            throw new ReadException(getName(), e);
347
        } finally {
348
            if (spatialCache.isEnabled()) {
349
                legend.deleteDrawingObserver(this);
350
            }
351
        }
352
    }
353

    
354
    public void print(Graphics2D g,
355
            ViewPort viewPort,
356
            Cancellable cancel,
357
            double scale,
358
            PrintAttributes properties) throws ReadException {
359
        if (!this.isWithinScale(scale)) {
360
            return;
361
        }
362
        if (cancel.isCanceled()) {
363
            return;
364
        }
365
        FeatureQuery featureQuery = createFeatureQuery();
366

    
367
        try {
368
            legend.print(g,
369
                    viewPort,
370
                    cancel,
371
                    scale,
372
                    null,
373
                    getCoordTrans(),
374
                    getFeatureStore(),
375
                    featureQuery,
376
                    properties);
377

    
378
        } catch (LegendException e) {
379
            this.setVisible(false);
380
            this.setActive(false);
381
            throw new ReadException(getName(), e);
382
        }
383
    }
384

    
385
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
386
        if (this.legend == legend) {
387
            return;
388
        }
389
        if (this.legend != null && this.legend.equals(legend)) {
390
            return;
391
        }
392
        IVectorLegend oldLegend = this.legend;
393
        this.legend = legend;
394
        if (oldLegend != null) {
395
            oldLegend.removeLegendListener(this);
396
            oldLegend.deleteDrawingObserver(this);
397
        }
398
        if (legend != null) {
399
            this.legend.addDrawingObserver(this);
400
            this.legend.addLegendListener(this);
401
        }
402
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
403
        e.setLayer(this);
404
        updateDrawVersion();
405
        callLegendChanged(e);
406
    }
407

    
408
    /**
409
     * Devuelve la Leyenda de la capa.
410
     *
411
     * @return Leyenda.
412
     */
413
    public ILegend getLegend() {
414
        return legend;
415
    }
416

    
417
    public int getShapeType() throws ReadException {
418
        if (typeShape == -1) {
419
            FeatureType featureType = null;
420
            try {
421
                if (getDataStore() != null) {
422
                    featureType
423
                            = (((FeatureStore) getDataStore()).getDefaultFeatureType());
424
                }
425
            } catch (DataException e) {
426
                throw new ReadException(getName(), e);
427
            }
428
            if (featureType != null) {
429
                int indexGeom = featureType.getDefaultGeometryAttributeIndex();
430
                typeShape
431
                        = featureType.getAttributeDescriptor(indexGeom).getGeometryType();
432
            }
433
        }
434
        return typeShape;
435
    }
436

    
437
    /**
438
     * Returns the layer's geometry type
439
     *
440
     * @return the geometry type
441
     *
442
     * @throws ReadException if there is an error getting the geometry type
443
     */
444
    public GeometryType getGeometryType() throws ReadException {
445
        FeatureType featureType = null;
446
        try {
447
            if (getDataStore() != null) {
448
                featureType
449
                        = (((FeatureStore) getDataStore()).getDefaultFeatureType());
450
            }
451
        } catch (DataException e) {
452
            throw new ReadException(getName(), e);
453
        }
454
        return featureType == null ? null : featureType
455
                .getDefaultGeometryAttribute().getGeomType();
456
    }
457

    
458
    public void saveToState(PersistentState state) throws PersistenceException {
459

    
460
        FeatureStore featureStore = null;
461

    
462
        if (!this.isAvailable()) {
463
            logger.info("The '" + this.getName() + "' layer is not available, it will persist not.");
464
            return;
465
        }
466

    
467
        try {
468
            super.saveToState(state);
469

    
470
            if (getLegend() != null) {
471
                state.set("legend", getLegend());
472
            }
473

    
474
            featureStore = getFeatureStore();
475

    
476
            if (featureStore != null) {
477
                state.set("featureStore", featureStore);
478
            }
479

    
480
            state.set("isLabeled", isLabeled);
481

    
482
            if (strategy != null) {
483
                state.set("labelingStrategy", strategy);
484
            }
485

    
486
            if (getLinkProperties() != null) {
487
                state.set("linkProperties", getLinkProperties());
488
            }
489

    
490
            state.set("typeShape", typeShape);
491
        } catch (PersistenceException ex) {
492
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
493
            throw ex;
494
        } catch (RuntimeException ex) {
495
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
496
            throw ex;
497
        }
498

    
499
    }
500

    
501
    @Override
502
    public void loadFromState(PersistentState state) throws PersistenceException {
503

    
504
        FeatureStore store = null;
505
        try {
506
            super.loadFromState(state);
507

    
508
            this.setIsLabeled(false);
509
            this.setLabelingStrategy(null);
510

    
511
            typeShape = state.getInt("typeShape", Geometry.TYPES.GEOMETRY);
512

    
513
            store = (FeatureStore) state.get("featureStore");
514
            if (store == null) { // Averiguar como puede llegar aqui un null.
515
                this.setAvailable(false);
516
                this.addError(new RuntimeException("Can't retrieve store information."));
517
            } else {
518
                if (store.isBroken()) {
519
                    this.setAvailable(false);
520
                    this.addError(store.getBreakingsCause());
521
                }
522
            }
523
            try {
524
                this.bindToDataStore(store);
525
            } catch (Exception ex) {
526
                this.setAvailable(false);
527
                this.addError(ex);
528
            }
529

    
530
            try {
531
                IVectorLegend vectorLegend = (IVectorLegend) state.get("legend");
532
                this.setLegend(vectorLegend);
533
            } catch (Exception ex) {
534
                this.setAvailable(false);
535
                this.addError(ex);
536
            }
537

    
538
            try {
539
                if (state.getBoolean("isLabeled", false)) {
540
                    this.setIsLabeled(true);
541
                    ILabelingStrategy labelingStrategy = (ILabelingStrategy) state.get("labelingStrategy");
542
                    this.setLabelingStrategy(labelingStrategy);
543
                }
544
            } catch (Exception ex) {
545
                this.setAvailable(false);
546
                this.addError(ex);
547
            }
548

    
549
        } catch (Throwable e) {
550
            String storeName = (store == null) ? "unknow" : store.getFullName();
551
            logger.warn("can't load layer '" + this.getName() + "' (store=" + storeName + ") from persisted state.", e);
552
            this.setAvailable(false);
553
            this.addError(e);
554
        }
555

    
556
    }
557

    
558
    /**
559
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
560
     * identifiquen la capa.
561
     *
562
     * @return DOCUMENT ME!
563
     */
564
    public String toString() {
565
        /*
566
         * Se usa internamente para que la parte de datos identifique de forma
567
         * un?voca las tablas
568
         */
569
        String ret = super.toString();
570

    
571
        return ret; //"layer" + ret.substring(ret.indexOf('@') + 1);
572
    }
573

    
574
    public boolean isEditing() {
575
        FeatureStore fs = getFeatureStore();
576
        if (fs == null) {
577
            /*
578
             * This happens when layer is not available, for example,
579
             * it was not possible to load from persistence
580
             */
581
            return false;
582
        } else {
583
            return fs.isEditing();
584
        }
585
    }
586

    
587
    public void setEditing(boolean b) throws StartEditionLayerException {
588

    
589
        try {
590
            throw new RuntimeException();
591
        } catch (Throwable th) {
592
            logger.info("This method is deprecated. ", th);
593
        }
594

    
595
        if (b == super.isEditing()) {
596
            return;
597
        }
598

    
599
        super.setEditing(b);
600
        FeatureStore fs = getFeatureStore();
601
        if (b) {
602
            try {
603
                fs.edit();
604
            } catch (DataException e) {
605
                throw new StartEditionLayerException(getName(), e);
606
            }
607
        }
608
        setSpatialCacheEnabled(b);
609
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
610
    }
611

    
612
    /**
613
     * @deprecated Use {@link #getSpatialCache()}
614
     */
615
    public void clearSpatialCache() {
616
        spatialCache.clearAll();
617
    }
618

    
619
    /**
620
     * @deprecated Use {@link #getSpatialCache()}
621
     */
622
    public boolean isSpatialCacheEnabled() {
623
        return spatialCache.isEnabled();
624
    }
625

    
626
    /**
627
     * @deprecated Use {@link #getSpatialCache()}
628
     */
629
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
630
        spatialCache.setEnabled(spatialCacheEnabled);
631
    }
632

    
633
    public SpatialCache getSpatialCache() {
634
        return spatialCache;
635
    }
636

    
637
    /**
638
     * Siempre es un numero mayor de 1000
639
     *
640
     * @param maxFeatures
641
     */
642
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
643
        if (maxFeatures > spatialCache.getMaxFeatures()) {
644
            spatialCache.setMaxFeatures(maxFeatures);
645
        }
646

    
647
    }
648

    
649
    /**
650
     * This method returns a boolean that is used by the FPopMenu to make
651
     * visible the properties menu or not. It is visible by default, and if a
652
     * later don't have to show this menu only has to override this method.
653
     *
654
     * @return If the properties menu is visible (or not)
655
     */
656
    public boolean isPropertiesMenuVisible() {
657
        return true;
658
    }
659

    
660
    public void reload() throws ReloadLayerException {
661
        super.reload();
662
        try {
663
            getFeatureStore().refresh();
664
        } catch (Exception e) {
665
            throw new ReloadLayerException(getName(), e);
666
        }
667
    }
668

    
669
    protected void setLoadSelection(Object xml) {
670
        // this.loadSelection = xml;
671
    }
672

    
673
    protected void setLoadLegend(IVectorLegend legend) {
674
        this.loadLegend = legend;
675
    }
676

    
677
    protected void putLoadSelection() {
678
        // if (this.loadSelection == null) return;
679
        // try {
680
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
681
        // } catch (ReadDriverException e) {
682
        // throw new XMLException(e);
683
        // }
684
        // this.loadSelection = null;
685

    
686
    }
687

    
688
    protected void putLoadLegend() throws LegendLayerException {
689
        if (this.loadLegend == null) {
690
            return;
691
        }
692
        this.setLegend(this.loadLegend);
693
        this.loadLegend = null;
694
    }
695

    
696
    protected void cleanLoadOptions() {
697
        this.loadLegend = null;
698
    }
699

    
700
    public boolean isWritable() {
701
        return getFeatureStore().allowWrite();
702
    }
703

    
704
    public FLayer cloneLayer() throws Exception {
705
        FLyrVect clonedLayer = new FLyrVect();
706
        clonedLayer.bindToDataStore(getDataStore());
707
        // if (isJoined()) {
708
        // clonedLayer.setIsJoined(true);
709
        // }
710
        clonedLayer.setVisible(isVisible());
711
        // clonedLayer.setISpatialIndex(getISpatialIndex());
712
        clonedLayer.setName(getName());
713
        clonedLayer.setCoordTrans(getCoordTrans());
714

    
715
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
716

    
717
        clonedLayer.setIsLabeled(isLabeled());
718
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
719
        if (labelingStrategy != null) {
720
            clonedLayer.setLabelingStrategy(labelingStrategy);
721
        }
722

    
723
        return clonedLayer;
724
    }
725

    
726
    protected boolean isOnePoint(AffineTransform graphicsTransform,
727
            ViewPort viewPort,
728
            double dpi,
729
            CartographicSupport csSym,
730
            Geometry geom,
731
            int[] xyCoords) {
732
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
733
                && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
734
    }
735

    
736
    private boolean isOnePoint(AffineTransform graphicsTransform,
737
            ViewPort viewPort,
738
            Geometry geom,
739
            int[] xyCoords) {
740
        boolean onePoint = false;
741
        int type = geom.getType();
742
        if (type == Geometry.TYPES.NULL) {
743
            return false;
744
        }
745
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
746

    
747
            Envelope geomBounds = geom.getEnvelope();
748

    
749
            // ICoordTrans ct = getCoordTrans();
750
            // Se supone que la geometria ya esta reproyectada
751
            // if (ct!=null) {
752
            // // geomBounds = ct.getInverted().convert(geomBounds);
753
            // geomBounds = geomBounds.convert(ct);
754
            // }
755
            double dist1Pixel = viewPort.getDist1pixel();
756

    
757
            onePoint
758
                    = (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
759

    
760
            if (onePoint) {
761
                // avoid out of range exceptions
762
                org.gvsig.fmap.geom.primitive.Point p;
763
                try {
764
                    p
765
                            = geomManager.createPoint(geomBounds.getMinimum(0),
766
                                    geomBounds.getMinimum(1),
767
                                    SUBTYPES.GEOM2D);
768
                    p.transform(viewPort.getAffineTransform());
769
                    p.transform(graphicsTransform);
770
                    xyCoords[0] = (int) p.getX();
771
                    xyCoords[1] = (int) p.getY();
772
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
773
                    logger.error("Error creating a point", e);
774
                }
775

    
776
            }
777

    
778
        }
779
        return onePoint;
780
    }
781

    
782
    public boolean isLabeled() {
783
        return isLabeled;
784
    }
785

    
786
    public void setIsLabeled(boolean isLabeled) {
787
        this.isLabeled = isLabeled;
788
    }
789

    
790
    public ILabelingStrategy getLabelingStrategy() {
791
        return strategy;
792
    }
793

    
794
    public void setLabelingStrategy(ILabelingStrategy strategy) {
795
        this.strategy = strategy;
796
        if (strategy == null) {
797
            return;
798
        }
799
        strategy.setLayer(this);
800
        updateDrawVersion();
801
    }
802

    
803
    public void drawLabels(BufferedImage image,
804
            Graphics2D g,
805
            ViewPort viewPort,
806
            Cancellable cancel,
807
            double scale,
808
            double dpi) throws ReadException {
809
        if (strategy != null && isWithinScale(scale)) {
810
            strategy.draw(image, g, scale, viewPort, cancel, dpi);
811
        }
812
    }
813

    
814
    public void printLabels(Graphics2D g,
815
            ViewPort viewPort,
816
            Cancellable cancel,
817
            double scale,
818
            PrintAttributes properties) throws ReadException {
819
        if (strategy != null) {
820
            strategy.print(g, scale, viewPort, cancel, properties);
821
        }
822
    }
823

    
824
    /**
825
     * Return true, because a Vectorial Layer supports HyperLink
826
     *
827
     * @deprecated the hiperlink functionaliti is out the layer now
828
     */
829
    public boolean allowLinks() {
830
        return false;
831
    }
832

    
833
    public void load() throws LoadLayerException {
834
        super.load();
835
    }
836

    
837
    public FeatureStore getFeatureStore() {
838
        return (FeatureStore) getDataStore();
839
    }
840

    
841
    public FeatureQuery createFeatureQuery() {
842
        if (this.baseQuery == null) {
843
            return this.getFeatureStore().createFeatureQuery();
844
        }
845
        try {
846
            return (FeatureQuery) baseQuery.clone();
847
        } catch (CloneNotSupportedException ex) {
848
            throw new RuntimeException(ex);
849
        }
850
    }
851

    
852
    /**
853
     * @deprecated use instead
854
     * {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
855
     */
856
    public FeatureSet queryByPoint(Point2D mapPoint,
857
            double tol,
858
            FeatureType featureType) throws DataException {
859
        logger.warn("Deprecated use of queryByPoint.");
860
        GeometryManager manager = GeometryLocator.getGeometryManager();
861
        org.gvsig.fmap.geom.primitive.Point center;
862
        try {
863
            center
864
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
865
                            SUBTYPES.GEOM2D);
866
            center.setX(mapPoint.getX());
867
            center.setY(mapPoint.getY());
868
            Circle circle
869
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
870
            circle.setPoints(center, tol);
871
            return queryByGeometry(circle, featureType);
872
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
873
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
874
        }
875
    }
876

    
877
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
878
            double tol,
879
            FeatureType featureType) throws DataException {
880
        GeometryManager manager = GeometryLocator.getGeometryManager();
881
        try {
882
            Circle circle
883
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
884
            circle.setPoints(point, tol);
885
            return queryByGeometry(circle, featureType);
886
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
887
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
888
        }
889
    }
890

    
891
    /**
892
     * Input geom must be in the CRS of the view.
893
     *
894
     * @param geom
895
     * @param featureType
896
     * @return
897
     * @throws DataException
898
     */
899
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
900
        FeatureQuery featureQuery = createFeatureQuery();
901
        featureQuery.setFeatureType(featureType);
902

    
903
        Geometry query_geo = this.transformToSourceCRS(geom, true);
904
        IProjection query_proj = getMapContext().getProjection();
905
        if (this.getCoordTrans() != null) {
906
            query_proj = this.getCoordTrans().getPOrig();
907
        }
908
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
909
                query_geo,
910
                query_proj,
911
                featureStore
912
        );
913
        featureQuery.setFilter(iee);
914
        featureQuery.setAttributeNames(null);
915
        return getFeatureStore().getFeatureSet(featureQuery);
916

    
917
    }
918
    
919
    public FeatureSet queryByContainedInGeometry(Geometry geom, FeatureType featureType) throws DataException {
920
        FeatureQuery featureQuery = createFeatureQuery();
921
        featureQuery.setFeatureType(featureType);
922

    
923
        Geometry query_geo = this.transformToSourceCRS(geom, true);
924
        IProjection query_proj = getMapContext().getProjection();
925
        if (this.getCoordTrans() != null) {
926
            query_proj = this.getCoordTrans().getPOrig();
927
        }
928
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
929
                query_geo,
930
                query_proj,
931
                featureStore
932
        );
933
        featureQuery.setFilter(iee);
934
        featureQuery.setAttributeNames(null);
935
        return getFeatureStore().getFeatureSet(featureQuery);
936

    
937
    }
938
    /**
939
     * It return the {@link FeatureSet} that intersects with the envelope.
940
     *
941
     * @param envelope envelope that defines the area for the query.
942
     * @param featureType only the features with this feature type are used in
943
     * the query.
944
     * @return the set of features that intersect with the envelope.
945
     * @throws DataException
946
     */
947
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
948
        return queryByEnvelope(envelope, featureType, null);
949
    }
950

    
951
    /**
952
     * It return the {@link FeatureSet} that intersects with the envelope.
953
     *
954
     * @param envelope envelope that defines the area for the query in viewport
955
     * CRS
956
     * @param featureType only the features with this feature type are used in
957
     * the query.
958
     * @param names the feature attributes that have to be checked.
959
     * @return the set of features that intersect with the envelope.
960
     * @throws DataException
961
     */
962
    public FeatureSet queryByEnvelope(Envelope envelope,
963
            FeatureType featureType,
964
            String[] names) throws DataException {
965
        FeatureQuery featureQuery = createFeatureQuery();
966
        if (names == null) {
967
            featureQuery.setFeatureType(featureType);
968
        } else {
969
            featureQuery.setAttributeNames(names);
970
            featureQuery.setFeatureTypeId(featureType.getId());
971
        }
972

    
973
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
974
        IProjection query_proj = getMapContext().getProjection();
975
        if (this.getCoordTrans() != null) {
976
            query_proj = this.getCoordTrans().getPOrig();
977
        }
978

    
979
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
980
                query_env.getGeometry(),
981
                query_proj,
982
                featureStore
983
        );
984
        featureQuery.setFilter(iee);
985
        return getFeatureStore().getFeatureSet(featureQuery);
986

    
987
    }
988
    
989
    public FeatureSet queryByContainedInEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
990
        return queryByContainedInEnvelope(envelope, featureType, null);
991
    }
992
    
993
    public FeatureSet queryByContainedInEnvelope(Envelope envelope,
994
            FeatureType featureType,
995
            String[] names) throws DataException {
996
        FeatureQuery featureQuery = createFeatureQuery();
997
        if (names == null) {
998
            featureQuery.setFeatureType(featureType);
999
        } else {
1000
            featureQuery.setAttributeNames(names);
1001
            featureQuery.setFeatureTypeId(featureType.getId());
1002
        }
1003

    
1004
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1005
        IProjection query_proj = getMapContext().getProjection();
1006
        if (this.getCoordTrans() != null) {
1007
            query_proj = this.getCoordTrans().getPOrig();
1008
        }
1009

    
1010
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
1011
                query_env.getGeometry(),
1012
                query_proj,
1013
                featureStore
1014
        );
1015
        featureQuery.setFilter(iee);
1016
        return getFeatureStore().getFeatureSet(featureQuery);
1017

    
1018
    }
1019
    
1020
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1021
            DataException {
1022

    
1023
        return getInfo(p, tolerance, cancel, true);
1024
    }
1025

    
1026
    public DynObjectSet getInfo(Point p,
1027
            double tolerance,
1028
            Cancellable cancel,
1029
            boolean fast) throws LoadLayerException, DataException {
1030
        Point2D infop = new Point2D.Double(p.x, p.y);
1031
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1032
        return queryByPoint(pReal,
1033
                tolerance,
1034
                getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1035
    }
1036

    
1037
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1038
            double tolerance) throws LoadLayerException, DataException {
1039
        return queryByPoint(p, tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
1040
    }
1041

    
1042
    @Override
1043
    public void legendCleared(LegendClearEvent event) {
1044
        this.updateDrawVersion();
1045
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(legend, event);
1046
        this.callLegendChanged(e);
1047
    }
1048

    
1049
    @Override
1050
    public boolean symbolChanged(SymbolLegendEvent e) {
1051
        this.updateDrawVersion();
1052
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
1053
        this.callLegendChanged(ev);
1054
        return true;
1055
    }
1056

    
1057
    public void update(Observable observable, Object notification) {
1058
        if (observable.equals(this.featureStore)) {
1059
            if (notification instanceof FeatureStoreNotification) {
1060
                FeatureStoreNotification event
1061
                        = (FeatureStoreNotification) notification;
1062
                if (event.getType() == FeatureStoreNotification.AFTER_DELETE
1063
                        || event.getType() == FeatureStoreNotification.AFTER_UNDO
1064
                        || event.getType() == FeatureStoreNotification.AFTER_REDO
1065
                        || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1066
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1067
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1068
                        || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1069
                        || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1070
                    this.updateDrawVersion();
1071

    
1072
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
1073

    
1074
                    setSpatialCacheEnabled(false);
1075
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1076
                    this.updateDrawVersion();
1077

    
1078
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
1079

    
1080
                    setSpatialCacheEnabled(true);
1081
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1082

    
1083
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE) {
1084
                    //If a transform has to be applied, try to reload the layer.
1085
                    try {
1086
                        reload();
1087
                    } catch (ReloadLayerException e) {
1088
                        logger.info("While reloading layer.", e);
1089
                        this.setAvailable(false);
1090
                    }
1091
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1092
                    this.setAvailable(false);
1093
                } else if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1094
                    this.setAvailable(true);
1095
                    setSpatialCacheEnabled(false);
1096
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1097
                    this.updateDrawVersion();
1098
                }
1099
            }
1100
        } else if (notification instanceof FeatureDrawnNotification
1101
                && spatialCache.isEnabled()) {
1102
            // This code is needed in editing mode
1103
            // for all layers involved in snapping
1104
            // (including the layer being edited)
1105
            Geometry geometry
1106
                    = ((FeatureDrawnNotification) notification).getDrawnGeometry();
1107
            spatialCache.insert(geometry.getEnvelope(), geometry);
1108
        }
1109
    }
1110

    
1111
    private boolean isLayerToSnap() {
1112

    
1113
        if (this.getMapContext() == null) {
1114
            /*
1115
             * This happens with the graphics layer because it has no parent
1116
             */
1117
            return false;
1118
        } else {
1119
            return this.getMapContext().getLayersToSnap().contains(this);
1120
        }
1121

    
1122
        /*
1123
         Iterator itersnap = this.getMapContext().getLayersToSnap().iterator();
1124
         Object item = null;
1125
         while (itersnap.hasNext()) {
1126
         item = itersnap.next();
1127
         if (item == this) {
1128
         return true;
1129
         }
1130
         }
1131
         return false;
1132
         */
1133
    }
1134

    
1135
    /*
1136
     * (non-Javadoc)
1137
     *
1138
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1139
     */
1140
    public Set getMetadataChildren() {
1141
        Set ret = new TreeSet();
1142
        ret.add(this.featureStore);
1143
        return ret;
1144
    }
1145

    
1146
    /*
1147
     * (non-Javadoc)
1148
     *
1149
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1150
     */
1151
    public Object getMetadataID() throws MetadataException {
1152
        return "Layer(" + this.getName() + "):"
1153
                + this.featureStore.getMetadataID();
1154
    }
1155

    
1156
    public GeometryType getTypeVectorLayer() throws DataException,
1157
            LocatorException,
1158
            GeometryTypeNotSupportedException,
1159
            GeometryTypeNotValidException {
1160
        // FIXME Esto deberia de pedirse a FType!!!!
1161
        FeatureStore fs = this.getFeatureStore();
1162
        FeatureType fType = fs.getDefaultFeatureType();
1163
        FeatureAttributeDescriptor attr
1164
                = fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1165
        GeometryType geomType
1166
                = GeometryLocator.getGeometryManager()
1167
                        .getGeometryType(attr.getGeometryType(),
1168
                                attr.getGeometrySubType());
1169
        return geomType;
1170
    }
1171

    
1172
    public static class SelfRegister
1173
            implements Callable {
1174

    
1175
        @Override
1176
        public Object call() {
1177
          registerPersistence();
1178
          registerDefaultVectorLayer();
1179
          return true;
1180
        }
1181
        
1182
        private Object registerDefaultVectorLayer() {
1183
            MapContextManager manager = MapContextLocator.getMapContextManager();
1184
            manager.registerLayer(FeatureStore.class, FLyrVect.class);
1185
            return true;          
1186
        }
1187
        
1188
        private Object registerPersistence() {
1189
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1190

    
1191
            DynStruct definition
1192
                    = manager.addDefinition(FLyrVect.class,
1193
                            "FLyrVect",
1194
                            "FLyrVect Persistence definition",
1195
                            null,
1196
                            null);
1197
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1198
                    "FLyrDefault");
1199

    
1200
            definition.addDynFieldObject("legend")
1201
                    .setClassOfValue(IVectorLegend.class)
1202
                    .setMandatory(true);
1203
            definition.addDynFieldObject("featureStore")
1204
                    .setClassOfValue(FeatureStore.class)
1205
                    .setMandatory(true);
1206
            definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1207
            definition.addDynFieldInt("typeShape").setMandatory(true);
1208
            definition.addDynFieldObject("labelingStrategy")
1209
                    .setClassOfValue(ILabelingStrategy.class)
1210
                    .setMandatory(false);
1211

    
1212
            return true;
1213
        }
1214
    }
1215

    
1216
    @Override
1217
    protected void doDispose() throws BaseException {
1218
        dispose(featureStore);
1219
        spatialCache.clearAll();
1220
    }
1221

    
1222
    /**
1223
     * Returns envelope in layer's data source CRS from envelope provided in
1224
     * viewport CRS
1225
     *
1226
     * @param lyr
1227
     * @param env
1228
     * @return
1229
     */
1230
    public static Envelope fromViewPortCRSToSourceCRS(FLayer lyr, Envelope env) {
1231

    
1232
        if (lyr == null || env == null) {
1233
            return null;
1234
        }
1235

    
1236
        ICoordTrans ct = lyr.getCoordTrans();
1237
        if (ct == null) {
1238
            return env;
1239
        } else {
1240
            return env.convert(ct.getInverted());
1241
        }
1242
    }
1243

    
1244
    public Geometry transformToSourceCRS(Geometry geom, boolean clone) {
1245
        return fromViewPortCRSToSourceCRS(this, geom, clone);
1246
    }
1247

    
1248
    /**
1249
     * Returns geometry in layer's data source CRS from geometry provided in
1250
     * viewport CRS
1251
     *
1252
     * @param lyr
1253
     * @param geo
1254
     * @param clone
1255
     * @return
1256
     * @deprecated use the transformToSourceCRS method of layer.
1257
     */
1258
    public static Geometry fromViewPortCRSToSourceCRS(
1259
            FLayer lyr,
1260
            Geometry geo,
1261
            boolean clone) {
1262

    
1263
        if (lyr == null || geo == null) {
1264
            return null;
1265
        }
1266
        ICoordTrans ct = lyr.getCoordTrans();
1267
        Geometry resp = geo;
1268
        if (clone) {
1269
            resp = resp.cloneGeometry();
1270
        }
1271
        if (ct != null) {
1272
            resp.reProject(ct.getInverted());
1273
        }
1274
        return resp;
1275
    }
1276

    
1277
    public Iterator iterator() {
1278
        return this.getFeatureStore().iterator();
1279
    }
1280

    
1281
    protected class EnvelopeCantBeInitializedException
1282
            extends BaseException {
1283

    
1284
        /**
1285
         *
1286
         */
1287
        private static final long serialVersionUID = 4572797479347381552L;
1288
        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.";
1289
        private final static String MESSAGE_KEY = "_EnvelopeCantBeInitializedException";
1290

    
1291
        public EnvelopeCantBeInitializedException() {
1292
            super(MESSAGE_FORMAT, null, MESSAGE_KEY, serialVersionUID);
1293
        }
1294
    }
1295

    
1296
    @Override
1297
    public String getInfoString() {
1298
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
1299

    
1300
        if (!this.isAvailable()) {
1301
            builder.title().labelkey("Warning");
1302
            builder.text().value("The layer is not available.");
1303
        }
1304

    
1305
        Envelope env = null;
1306
        FeatureAttributeDescriptor attrgeom = null;
1307

    
1308
        try {
1309
            env = this.getFullEnvelope();
1310
        } catch (Exception ex) {
1311
        }
1312
        FeatureStore store = this.getFeatureStore();
1313
        try {
1314
            FeatureType ft = store.getDefaultFeatureType();
1315
            attrgeom = ft.getDefaultGeometryAttribute();
1316
        } catch (Exception ex) {
1317
        }
1318

    
1319
        builder.title().labelkey("Data_source");
1320
        builder.property().labelkey("Source_type").value(store.getProviderName());
1321
        builder.property().labelkey("origen").value(store.getFullName());
1322
        if (store.getParameters() instanceof FilesystemStoreParameters) {
1323
            File f = ((FilesystemStoreParameters) (store.getParameters())).getFile();
1324
            if (f != null && f.exists()) {
1325
                builder.property().labelkey("_Size").value("%d bytes", f.length());
1326
            }
1327
        }
1328
        if (attrgeom != null) {
1329
            builder.property().labelkey("_Geometry_column").value(attrgeom.getName());
1330
            builder.property().labelkey("_Geometry_type").value(attrgeom.getGeomType().getFullName());
1331
        }
1332

    
1333
        builder.title().labelkey("_Coordenadas_geograficas");
1334
        if (this.isAvailable()) {
1335
            builder.envelope().value(env);
1336
        }
1337

    
1338
        builder.title().labelkey("_Projection");
1339
        if (this.isAvailable()) {
1340
            builder.property().value(this.getProjection());
1341
            builder.text().asWKT(this.getProjection());
1342
        }
1343
        return builder.toString();
1344
    }
1345

    
1346
    @Override
1347
    public boolean isTemporary() {
1348
        if (this.featureStore != null) {
1349
            if (this.featureStore.isTemporary()) {
1350
                return true;
1351
            }
1352
        }
1353
        return super.isTemporary();
1354
    }
1355

    
1356

    
1357
    
1358

    
1359
}