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

History | View | Annotate | Download (46.5 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

    
35
import org.cresques.cts.ICoordTrans;
36
import org.cresques.cts.IProjection;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.compat.print.PrintAttributes;
40
import org.gvsig.fmap.dal.DALLocator;
41
import org.gvsig.fmap.dal.DataStore;
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.exception.InitializeException;
44
import org.gvsig.fmap.dal.exception.ReadException;
45
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
46
import org.gvsig.fmap.dal.feature.FeatureQuery;
47
import org.gvsig.fmap.dal.feature.FeatureSet;
48
import org.gvsig.fmap.dal.feature.FeatureStore;
49
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
50
import org.gvsig.fmap.dal.feature.FeatureType;
51
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
52
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
55
import org.gvsig.fmap.geom.Geometry.TYPES;
56
import org.gvsig.fmap.geom.GeometryLocator;
57
import org.gvsig.fmap.geom.GeometryManager;
58
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
59
import org.gvsig.fmap.geom.primitive.Circle;
60
import org.gvsig.fmap.geom.primitive.Envelope;
61
import org.gvsig.fmap.geom.type.GeometryType;
62
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
63
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
64
import org.gvsig.fmap.mapcontext.MapContextLocator;
65
import org.gvsig.fmap.mapcontext.MapContextManager;
66
import org.gvsig.fmap.mapcontext.ViewPort;
67
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
68
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
69
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
70
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
71
import org.gvsig.fmap.mapcontext.layers.FLayer;
72
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
73
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
74
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
75
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
76
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
77
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
78
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
79
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
80
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
81
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
82
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
83
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
84
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
85
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
86
import org.gvsig.metadata.exceptions.MetadataException;
87
import org.gvsig.tools.ToolsLocator;
88
import org.gvsig.tools.dynobject.DynObjectSet;
89
import org.gvsig.tools.dynobject.DynStruct;
90
import org.gvsig.tools.evaluator.Evaluator;
91
import org.gvsig.tools.exception.BaseException;
92
import org.gvsig.tools.locator.LocatorException;
93
import org.gvsig.tools.observer.Observable;
94
import org.gvsig.tools.observer.Observer;
95
import org.gvsig.tools.persistence.PersistenceManager;
96
import org.gvsig.tools.persistence.PersistentState;
97
import org.gvsig.tools.persistence.exception.PersistenceException;
98
import org.gvsig.tools.task.Cancellable;
99
import org.gvsig.tools.util.Callable;
100

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

    
110
    final static private org.slf4j.Logger logger
111
            = LoggerFactory.getLogger(FLyrVect.class);
112
    private final GeometryManager geomManager
113
            = GeometryLocator.getGeometryManager();
114

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

    
123
    /**
124
     * An implementation of gvSIG spatial index
125
     */
126
    // protected ISpatialIndex spatialIndex = null;
127
    private IVectorLegend loadLegend = null;
128

    
129
    private boolean isLabeled;
130
    protected ILabelingStrategy strategy;
131
//        private ReprojectDefaultGeometry reprojectTransform;
132
    private FeatureQuery baseQuery = null;
133

    
134
    public FLyrVect() {
135
        super();
136
    }
137

    
138
    @Override
139
    public String getTocImageIcon() {
140
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
141
    }
142

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

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

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

    
176
        featureStore = (FeatureStore) dataStore;
177

    
178
        MapContextManager mapContextManager
179
                = MapContextLocator.getMapContextManager();
180

    
181
        //Set the legend
182
        IVectorLegend legend
183
                = (IVectorLegend) mapContextManager.getLegend(dataStore);
184

    
185
        if (legend == null) {
186
            throw new LegendLayerException(this.getName());
187
        }
188

    
189
        this.setLegend(legend);
190

    
191
        //Set the labeling strategy
192
        ILabelingStrategy labeler
193
                = (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
194

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

    
202
        this.delegate(dataStore);
203

    
204
        dataStore.addObserver(this);
205

    
206
        ToolsLocator.getDisposableManager().bind(dataStore);
207
    }
208

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

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

    
248
    }
249

    
250
    public void setBaseQuery(FeatureQuery baseQuery) {
251
        this.baseQuery = baseQuery;
252
    }
253

    
254
    @Override
255
    public FeatureQuery getBaseQuery() {
256
        return this.baseQuery;
257
    }
258

    
259
    public void addBaseFilter(Evaluator filter) {
260
        if (this.baseQuery == null) {
261
            this.baseQuery = this.getFeatureStore().createFeatureQuery();
262
        }
263
        this.baseQuery.addFilter(filter);
264
    }
265

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

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

    
292
        if (legend == null) {
293
            return;
294
        }
295

    
296
        if (!this.isWithinScale(scale)) {
297
            return;
298
        }
299
        if (cancel.isCanceled()) {
300
            return;
301
        }
302

    
303
        if (spatialCache.isEnabled()) {
304
            spatialCache.clearAll();
305
            legend.addDrawingObserver(this);
306
        }
307

    
308
        FeatureQuery featureQuery = createFeatureQuery();
309

    
310
        try {
311
            FeatureAttributeDescriptor featureAttributeDescriptor
312
                    = getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
313

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

    
323
        try {
324

    
325
            long tini = System.currentTimeMillis();
326

    
327
            legend.draw(image,
328
                    g,
329
                    viewPort,
330
                    cancel,
331
                    scale,
332
                    null,
333
                    getCoordTrans(),
334
                    getFeatureStore(),
335
                    featureQuery);
336

    
337
            logger.debug("Layer " + this.getName() + " drawn in "
338
                    + (System.currentTimeMillis() - tini) + " milliseconds.");
339

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

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

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

    
375
        } catch (LegendException e) {
376
            this.setVisible(false);
377
            this.setActive(false);
378
            throw new ReadException(getName(), e);
379
        }
380
    }
381

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

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

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

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

    
455
    public void saveToState(PersistentState state) throws PersistenceException {
456

    
457
        FeatureStore featureStore = null;
458

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

    
464
        try {
465
            super.saveToState(state);
466

    
467
            if (getLegend() != null) {
468
                state.set("legend", getLegend());
469
            }
470

    
471
            featureStore = getFeatureStore();
472

    
473
            if (featureStore != null) {
474
                state.set("featureStore", featureStore);
475
            }
476

    
477
            state.set("isLabeled", isLabeled);
478

    
479
            if (strategy != null) {
480
                state.set("labelingStrategy", strategy);
481
            }
482

    
483
            if (getLinkProperties() != null) {
484
                state.set("linkProperties", getLinkProperties());
485
            }
486

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

    
496
    }
497

    
498
    @Override
499
    public void loadFromState(PersistentState state) throws PersistenceException {
500

    
501
        FeatureStore store = null;
502
        try {
503
            super.loadFromState(state);
504

    
505
            this.setIsLabeled(false);
506
            this.setLabelingStrategy(null);
507

    
508
            typeShape = state.getInt("typeShape", Geometry.TYPES.GEOMETRY);
509

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

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

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

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

    
553
    }
554

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

    
568
        return ret; //"layer" + ret.substring(ret.indexOf('@') + 1);
569
    }
570

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

    
584
    public void setEditing(boolean b) throws StartEditionLayerException {
585

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

    
592
        if (b == super.isEditing()) {
593
            return;
594
        }
595

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

    
609
    /**
610
     * @deprecated Use {@link #getSpatialCache()}
611
     */
612
    public void clearSpatialCache() {
613
        spatialCache.clearAll();
614
    }
615

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

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

    
630
    public SpatialCache getSpatialCache() {
631
        return spatialCache;
632
    }
633

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

    
644
    }
645

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

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

    
666
    protected void setLoadSelection(Object xml) {
667
        // this.loadSelection = xml;
668
    }
669

    
670
    protected void setLoadLegend(IVectorLegend legend) {
671
        this.loadLegend = legend;
672
    }
673

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

    
683
    }
684

    
685
    protected void putLoadLegend() throws LegendLayerException {
686
        if (this.loadLegend == null) {
687
            return;
688
        }
689
        this.setLegend(this.loadLegend);
690
        this.loadLegend = null;
691
    }
692

    
693
    protected void cleanLoadOptions() {
694
        this.loadLegend = null;
695
    }
696

    
697
    public boolean isWritable() {
698
        return getFeatureStore().allowWrite();
699
    }
700

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

    
712
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
713

    
714
        clonedLayer.setIsLabeled(isLabeled());
715
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
716
        if (labelingStrategy != null) {
717
            clonedLayer.setLabelingStrategy(labelingStrategy);
718
        }
719

    
720
        return clonedLayer;
721
    }
722

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

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

    
744
            Envelope geomBounds = geom.getEnvelope();
745

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

    
754
            onePoint
755
                    = (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
756

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

    
773
            }
774

    
775
        }
776
        return onePoint;
777
    }
778

    
779
    public boolean isLabeled() {
780
        return isLabeled;
781
    }
782

    
783
    public void setIsLabeled(boolean isLabeled) {
784
        this.isLabeled = isLabeled;
785
    }
786

    
787
    public ILabelingStrategy getLabelingStrategy() {
788
        return strategy;
789
    }
790

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

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

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

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

    
830
    public void load() throws LoadLayerException {
831
        super.load();
832
    }
833

    
834
    public FeatureStore getFeatureStore() {
835
        return (FeatureStore) getDataStore();
836
    }
837

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1015
    }
1016
    
1017
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1018
            DataException {
1019

    
1020
        return getInfo(p, tolerance, cancel, true);
1021
    }
1022

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

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

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

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

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

    
1069
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
1070

    
1071
                    setSpatialCacheEnabled(false);
1072
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1073
                    this.updateDrawVersion();
1074

    
1075
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
1076

    
1077
                    setSpatialCacheEnabled(true);
1078
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1079

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

    
1108
    private boolean isLayerToSnap() {
1109

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

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

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

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

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

    
1169
    public static class SelfRegister
1170
            implements Callable {
1171

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

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

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

    
1209
            return true;
1210
        }
1211
    }
1212

    
1213
    @Override
1214
    protected void doDispose() throws BaseException {
1215
        dispose(featureStore);
1216
        spatialCache.clearAll();
1217
    }
1218

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

    
1229
        if (lyr == null || env == null) {
1230
            return null;
1231
        }
1232

    
1233
        ICoordTrans ct = lyr.getCoordTrans();
1234
        if (ct == null) {
1235
            return env;
1236
        } else {
1237
            return env.convert(ct.getInverted());
1238
        }
1239
    }
1240

    
1241
    public Geometry transformToSourceCRS(Geometry geom, boolean clone) {
1242
        return fromViewPortCRSToSourceCRS(this, geom, clone);
1243
    }
1244

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

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

    
1274
    public Iterator iterator() {
1275
        return this.getFeatureStore().iterator();
1276
    }
1277

    
1278
    protected class EnvelopeCantBeInitializedException
1279
            extends BaseException {
1280

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

    
1288
        public EnvelopeCantBeInitializedException() {
1289
            super(MESSAGE_FORMAT, null, MESSAGE_KEY, serialVersionUID);
1290
        }
1291
    }
1292

    
1293
    @Override
1294
    public String getInfoString() {
1295
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
1296

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

    
1302
        Envelope env = null;
1303
        FeatureAttributeDescriptor attrgeom = null;
1304

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

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

    
1330
        builder.title().labelkey("_Coordenadas_geograficas");
1331
        if (this.isAvailable()) {
1332
            builder.envelope().value(env);
1333
        }
1334

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

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

    
1353

    
1354
    
1355

    
1356
}