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

History | View | Annotate | Download (49.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or 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.List;
33
import java.util.Set;
34
import java.util.TreeSet;
35

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

    
40
import org.gvsig.compat.print.PrintAttributes;
41
import org.gvsig.fmap.dal.DALLocator;
42
import org.gvsig.fmap.dal.DataStore;
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.exception.InitializeException;
45
import org.gvsig.fmap.dal.exception.ReadException;
46
import org.gvsig.fmap.dal.feature.Feature;
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.FLayer;
74
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
75
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
76
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
77
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
78
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
79
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
80
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
81
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
82
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
83
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
84
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
85
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
86
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
87
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
88
import org.gvsig.metadata.exceptions.MetadataException;
89
import org.gvsig.tools.ToolsLocator;
90
import org.gvsig.tools.dynform.spi.DynFormSPILocator;
91
import org.gvsig.tools.dynform.spi.DynFormSPIManager;
92
import org.gvsig.tools.dynobject.DynObjectManager;
93
import org.gvsig.tools.dynobject.DynObjectSet;
94
import org.gvsig.tools.dynobject.DynStruct;
95
import org.gvsig.tools.dynobject.Tags;
96
import org.gvsig.tools.evaluator.Evaluator;
97
import org.gvsig.tools.exception.BaseException;
98
import org.gvsig.tools.locator.LocatorException;
99
import org.gvsig.tools.observer.Observable;
100
import org.gvsig.tools.observer.Observer;
101
import org.gvsig.tools.persistence.PersistenceManager;
102
import org.gvsig.tools.persistence.PersistentState;
103
import org.gvsig.tools.persistence.exception.PersistenceException;
104
import org.gvsig.tools.task.Cancellable;
105
import org.gvsig.tools.util.Callable;
106

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

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

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

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

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

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

    
147
    @Override
148
    public String getTocImageIcon() {
149
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
150
    }
151

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

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

    
174
    /**
175
     * Enlaza la capa con el DataStore indicado.
176
     *
177
     * @param dataStore
178
     * @throws LoadLayerException
179
     */
180
    protected void bindToDataStore(DataStore dataStore) throws LoadLayerException {
181
        if (this.featureStore != null && this.featureStore != dataStore) {
182
            this.featureStore.deleteObserver(this);
183
        }
184

    
185
        featureStore = (FeatureStore) dataStore;
186

    
187
        MapContextManager mapContextManager
188
                = MapContextLocator.getMapContextManager();
189

    
190
        //Set the legend
191
        IVectorLegend legend
192
                = (IVectorLegend) mapContextManager.getLegend(dataStore);
193

    
194
        if (legend == null) {
195
            throw new LegendLayerException(this.getName());
196
        }
197

    
198
        this.setLegend(legend);
199

    
200
        //Set the labeling strategy
201
        ILabelingStrategy labeler
202
                = (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
203

    
204
        if (labeler != null) {
205
            labeler.setLayer(this);
206
            this.setLabelingStrategy(labeler);
207
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
208
            // etiquetes?????
209
        }
210

    
211
        this.delegate(dataStore);
212

    
213
        dataStore.addObserver(this);
214
        
215
        FeatureType featureType = featureStore.getDefaultFeatureTypeQuietly();
216
        if( featureType!=null ) {
217
            Tags tags = featureType.getTags();
218
            if( tags.has(TAG_LAYERVECT_MAXSCALE) ) {
219
                this.setMaxScale(tags.getInt(TAG_LAYERVECT_MAXSCALE, -1));
220
            }
221
            if( tags.has(TAG_LAYERVECT_MINSCALE) ) {
222
                this.setMinScale(tags.getInt(TAG_LAYERVECT_MINSCALE, -1));
223
            }
224
        }
225

    
226
        ToolsLocator.getDisposableManager().bind(dataStore);
227
    }
228

    
229
    public Envelope getFullEnvelope() throws ReadException {
230
        Envelope rAux;
231
        if (getFeatureStore() == null) {
232
            return null;
233
        }
234
        try {
235
            rAux = getFeatureStore().getEnvelope();
236
        } catch (BaseException e) {
237
            throw new ReadException(getName(), e);
238
        }
239

    
240
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
241
        // y alto 0.
242
        if (rAux == null || rAux.isEmpty() || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
243
                && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
244
            try {
245
                rAux
246
                        = geomManager.createEnvelope(0, 0, 90, 90, SUBTYPES.GEOM2D);
247
            } catch (CreateEnvelopeException e) {
248
                logger.error("Error creating the envelope", e);
249
                e.printStackTrace();
250
            }
251
        }
252
        // Si existe reproyecci?n, reproyectar el extent
253
        ICoordTrans ct = getCoordTrans();
254
        if (ct != null) {
255
            boolean originalEnvelopeIsEmpty = rAux.isEmpty();
256
            rAux = rAux.convert(ct);
257
            if (!originalEnvelopeIsEmpty && rAux.isEmpty()) {
258
                try {
259
                    this.setAvailable(false);
260
                    throw new EnvelopeCantBeInitializedException();
261
                } catch (EnvelopeCantBeInitializedException e) {
262
                    this.addError(e);
263
                }
264
            }
265
        }
266
        return rAux;
267

    
268
    }
269

    
270
    public void setBaseQuery(FeatureQuery baseQuery) {
271
        this.baseQuery = baseQuery;
272
    }
273

    
274
    @Override
275
    public FeatureQuery getBaseQuery() {
276
        return this.baseQuery;
277
    }
278

    
279
    public void addBaseFilter(Evaluator filter) {
280
        if (this.baseQuery == null) {
281
            this.baseQuery = this.getFeatureStore().createFeatureQuery();
282
        }
283
        this.baseQuery.addFilter(filter);
284
    }
285

    
286
    public void addBaseFilter(String filter) {
287
        try {
288
            this.addBaseFilter(DALLocator.getDataManager().createExpresion(filter));
289
        } catch (InitializeException ex) {
290
            throw new RuntimeException("Can't create filter with '" + filter + "'", ex);
291
        }
292
    }
293

    
294
    /**
295
     * Draws using IFeatureIterator. This method will replace the old draw(...)
296
     * one.
297
     *
298
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
299
     * @param image
300
     * @param g
301
     * @param viewPort
302
     * @param cancel
303
     * @param scale
304
     * @throws ReadDriverException
305
     */
306
    public void draw(BufferedImage image,
307
            Graphics2D g,
308
            ViewPort viewPort,
309
            Cancellable cancel,
310
            double scale) throws ReadException {
311

    
312
        if (legend == null) {
313
            return;
314
        }
315

    
316
        if (!this.isWithinScale(scale)) {
317
            return;
318
        }
319
        if (cancel.isCanceled()) {
320
            return;
321
        }
322

    
323
        if (spatialCache.isEnabled()) {
324
            spatialCache.clearAll();
325
            legend.addDrawingObserver(this);
326
        }
327

    
328
        FeatureQuery featureQuery = createFeatureQuery();
329

    
330
        try {
331
            FeatureAttributeDescriptor featureAttributeDescriptor
332
                    = getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
333

    
334
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)) {
335
                IntersectsTimeEvaluator intersectsTimeEvaluator
336
                        = new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
337
                featureQuery.addFilter(intersectsTimeEvaluator);
338
            }
339
        } catch (DataException e1) {
340
            logger.error("Impossible to get the temporal filter", e1);
341
        }
342

    
343
        try {
344

    
345
            long tini = System.currentTimeMillis();
346

    
347
            legend.draw(image,
348
                    g,
349
                    viewPort,
350
                    cancel,
351
                    scale,
352
                    null,
353
                    getCoordTrans(),
354
                    getFeatureStore(),
355
                    featureQuery);
356

    
357
            logger.debug("Layer " + this.getName() + " drawn in "
358
                    + (System.currentTimeMillis() - tini) + " milliseconds.");
359

    
360
        } catch (LegendException e) {
361
            this.setAvailable(false);
362
            this.setError(e);
363
            throw new ReadException(getName(), e);
364
        } finally {
365
            if (spatialCache.isEnabled()) {
366
                legend.deleteDrawingObserver(this);
367
            }
368
        }
369
    }
370

    
371
    public void print(Graphics2D g,
372
            ViewPort viewPort,
373
            Cancellable cancel,
374
            double scale,
375
            PrintAttributes properties) throws ReadException {
376
        if (!this.isWithinScale(scale)) {
377
            return;
378
        }
379
        if (cancel.isCanceled()) {
380
            return;
381
        }
382
        FeatureQuery featureQuery = createFeatureQuery();
383

    
384
        try {
385
            legend.print(g,
386
                    viewPort,
387
                    cancel,
388
                    scale,
389
                    null,
390
                    getCoordTrans(),
391
                    getFeatureStore(),
392
                    featureQuery,
393
                    properties);
394

    
395
        } catch (LegendException e) {
396
            this.setVisible(false);
397
            this.setActive(false);
398
            throw new ReadException(getName(), e);
399
        }
400
    }
401

    
402
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
403
        if (this.legend == legend) {
404
            return;
405
        }
406
        if (this.legend != null && this.legend.equals(legend)) {
407
            return;
408
        }
409
        IVectorLegend oldLegend = this.legend;
410
        this.legend = legend;
411
        if (oldLegend != null) {
412
            oldLegend.removeLegendListener(this);
413
            oldLegend.deleteDrawingObserver(this);
414
        }
415
        if (legend != null) {
416
            this.legend.addDrawingObserver(this);
417
            this.legend.addLegendListener(this);
418
        }
419
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
420
        e.setLayer(this);
421
        updateDrawVersion();
422
        callLegendChanged(e);
423
    }
424

    
425
    /**
426
     * Devuelve la Leyenda de la capa.
427
     *
428
     * @return Leyenda.
429
     */
430
    public ILegend getLegend() {
431
        return legend;
432
    }
433

    
434
    public int getShapeType() throws ReadException {
435
        if (typeShape == -1) {
436
            FeatureType featureType = null;
437
            try {
438
                if (getDataStore() != null) {
439
                    featureType
440
                            = (((FeatureStore) getDataStore()).getDefaultFeatureType());
441
                }
442
            } catch (DataException e) {
443
                throw new ReadException(getName(), e);
444
            }
445
            if (featureType != null) {
446
                int indexGeom = featureType.getDefaultGeometryAttributeIndex();
447
                typeShape
448
                        = featureType.getAttributeDescriptor(indexGeom).getGeometryType();
449
            }
450
        }
451
        return typeShape;
452
    }
453

    
454
    /**
455
     * Returns the layer's geometry type
456
     *
457
     * @return the geometry type
458
     *
459
     * @throws ReadException if there is an error getting the geometry type
460
     */
461
    public GeometryType getGeometryType() throws ReadException {
462
        FeatureType featureType = null;
463
        try {
464
            if (getDataStore() != null) {
465
                featureType
466
                        = (((FeatureStore) getDataStore()).getDefaultFeatureType());
467
            }
468
        } catch (DataException e) {
469
            throw new ReadException(getName(), e);
470
        }
471
        return featureType == null ? null : featureType
472
                .getDefaultGeometryAttribute().getGeomType();
473
    }
474

    
475
    public void saveToState(PersistentState state) throws PersistenceException {
476

    
477
        FeatureStore featureStore = null;
478

    
479
        if (!this.isAvailable()) {
480
            logger.info("The '" + this.getName() + "' layer is not available, it will persist not.");
481
            return;
482
        }
483

    
484
        try {
485
            super.saveToState(state);
486

    
487
            if (getLegend() != null) {
488
                state.set("legend", getLegend());
489
            }
490

    
491
            featureStore = getFeatureStore();
492

    
493
            if (featureStore != null) {
494
                state.set("featureStore", featureStore);
495
            }
496

    
497
            state.set("isLabeled", isLabeled);
498

    
499
            if (strategy != null) {
500
                state.set("labelingStrategy", strategy);
501
            }
502

    
503
            if (getLinkProperties() != null) {
504
                state.set("linkProperties", getLinkProperties());
505
            }
506

    
507
            state.set("typeShape", typeShape);
508
        } catch (PersistenceException ex) {
509
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
510
            throw ex;
511
        } catch (RuntimeException ex) {
512
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
513
            throw ex;
514
        }
515

    
516
    }
517

    
518
    @Override
519
    public void loadFromState(PersistentState state) throws PersistenceException {
520

    
521
        FeatureStore store = null;
522
        try {
523
            super.loadFromState(state);
524

    
525
            this.setIsLabeled(false);
526
            this.setLabelingStrategy(null);
527

    
528
            typeShape = state.getInt("typeShape", Geometry.TYPES.GEOMETRY);
529

    
530
            store = (FeatureStore) state.get("featureStore");
531
            if (store == null) { // Averiguar como puede llegar aqui un null.
532
                this.setAvailable(false);
533
                this.addError(new RuntimeException("Can't retrieve store information."));
534
            } else {
535
                if (store.isBroken()) {
536
                    this.setAvailable(false);
537
                    this.addError(store.getBreakingsCause());
538
                }
539
            }
540
            try {
541
                this.bindToDataStore(store);
542
            } catch (Exception ex) {
543
                this.setAvailable(false);
544
                this.addError(ex);
545
            }
546

    
547
            try {
548
                IVectorLegend vectorLegend = (IVectorLegend) state.get("legend");
549
                this.setLegend(vectorLegend);
550
            } catch (Exception ex) {
551
                this.setAvailable(false);
552
                this.addError(ex);
553
            }
554

    
555
            try {
556
                if (state.getBoolean("isLabeled", false)) {
557
                    this.setIsLabeled(true);
558
                    ILabelingStrategy labelingStrategy = (ILabelingStrategy) state.get("labelingStrategy");
559
                    this.setLabelingStrategy(labelingStrategy);
560
                }
561
            } catch (Exception ex) {
562
                this.setAvailable(false);
563
                this.addError(ex);
564
            }
565

    
566
        } catch (Throwable e) {
567
            String storeName = (store == null) ? "unknow" : store.getFullName();
568
            logger.warn("can't load layer '" + this.getName() + "' (store=" + storeName + ") from persisted state.", e);
569
            this.setAvailable(false);
570
            this.addError(e);
571
        }
572

    
573
    }
574

    
575
    /**
576
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
577
     * identifiquen la capa.
578
     *
579
     * @return DOCUMENT ME!
580
     */
581
    public String toString() {
582
        /*
583
         * Se usa internamente para que la parte de datos identifique de forma
584
         * un?voca las tablas
585
         */
586
        String ret = super.toString();
587

    
588
        return ret; //"layer" + ret.substring(ret.indexOf('@') + 1);
589
    }
590

    
591
    public boolean isEditing() {
592
        FeatureStore fs = getFeatureStore();
593
        if (fs == null) {
594
            /*
595
             * This happens when layer is not available, for example,
596
             * it was not possible to load from persistence
597
             */
598
            return false;
599
        } else {
600
            return fs.isEditing();
601
        }
602
    }
603

    
604
    public void setEditing(boolean b) throws StartEditionLayerException {
605

    
606
        try {
607
            throw new RuntimeException();
608
        } catch (Throwable th) {
609
            logger.info("This method is deprecated. ", th);
610
        }
611

    
612
        if (b == super.isEditing()) {
613
            return;
614
        }
615

    
616
        super.setEditing(b);
617
        FeatureStore fs = getFeatureStore();
618
        if (b) {
619
            try {
620
                fs.edit();
621
            } catch (DataException e) {
622
                throw new StartEditionLayerException(getName(), e);
623
            }
624
        }
625
        setSpatialCacheEnabled(b);
626
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
627
    }
628

    
629
    /**
630
     * @deprecated Use {@link #getSpatialCache()}
631
     */
632
    public void clearSpatialCache() {
633
        spatialCache.clearAll();
634
    }
635

    
636
    /**
637
     * @deprecated Use {@link #getSpatialCache()}
638
     */
639
    public boolean isSpatialCacheEnabled() {
640
        return spatialCache.isEnabled();
641
    }
642

    
643
    /**
644
     * @deprecated Use {@link #getSpatialCache()}
645
     */
646
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
647
        spatialCache.setEnabled(spatialCacheEnabled);
648
    }
649

    
650
    public SpatialCache getSpatialCache() {
651
        return spatialCache;
652
    }
653

    
654
    /**
655
     * Siempre es un numero mayor de 1000
656
     *
657
     * @param maxFeatures
658
     */
659
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
660
        if (maxFeatures > spatialCache.getMaxFeatures()) {
661
            spatialCache.setMaxFeatures(maxFeatures);
662
        }
663

    
664
    }
665

    
666
    /**
667
     * This method returns a boolean that is used by the FPopMenu to make
668
     * visible the properties menu or not. It is visible by default, and if a
669
     * later don't have to show this menu only has to override this method.
670
     *
671
     * @return If the properties menu is visible (or not)
672
     */
673
    public boolean isPropertiesMenuVisible() {
674
        return true;
675
    }
676

    
677
    public void reload() throws ReloadLayerException {
678
        super.reload();
679
        try {
680
            getFeatureStore().refresh();
681
        } catch (Exception e) {
682
            throw new ReloadLayerException(getName(), e);
683
        }
684
    }
685

    
686
    protected void setLoadSelection(Object xml) {
687
        // this.loadSelection = xml;
688
    }
689

    
690
    protected void setLoadLegend(IVectorLegend legend) {
691
        this.loadLegend = legend;
692
    }
693

    
694
    protected void putLoadSelection() {
695
        // if (this.loadSelection == null) return;
696
        // try {
697
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
698
        // } catch (ReadDriverException e) {
699
        // throw new XMLException(e);
700
        // }
701
        // this.loadSelection = null;
702

    
703
    }
704

    
705
    protected void putLoadLegend() throws LegendLayerException {
706
        if (this.loadLegend == null) {
707
            return;
708
        }
709
        this.setLegend(this.loadLegend);
710
        this.loadLegend = null;
711
    }
712

    
713
    protected void cleanLoadOptions() {
714
        this.loadLegend = null;
715
    }
716

    
717
    public boolean isWritable() {
718
        return getFeatureStore().allowWrite();
719
    }
720

    
721
    public FLayer cloneLayer() throws Exception {
722
        FLyrVect clonedLayer = new FLyrVect();
723
        clonedLayer.bindToDataStore(getDataStore());
724
        // if (isJoined()) {
725
        // clonedLayer.setIsJoined(true);
726
        // }
727
        clonedLayer.setVisible(isVisible());
728
        // clonedLayer.setISpatialIndex(getISpatialIndex());
729
        clonedLayer.setName(getName());
730
        clonedLayer.setCoordTrans(getCoordTrans());
731

    
732
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
733

    
734
        clonedLayer.setIsLabeled(isLabeled());
735
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
736
        if (labelingStrategy != null) {
737
            clonedLayer.setLabelingStrategy(labelingStrategy);
738
        }
739

    
740
        return clonedLayer;
741
    }
742

    
743
    protected boolean isOnePoint(AffineTransform graphicsTransform,
744
            ViewPort viewPort,
745
            double dpi,
746
            CartographicSupport csSym,
747
            Geometry geom,
748
            int[] xyCoords) {
749
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
750
                && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
751
    }
752

    
753
    private boolean isOnePoint(AffineTransform graphicsTransform,
754
            ViewPort viewPort,
755
            Geometry geom,
756
            int[] xyCoords) {
757
        boolean onePoint = false;
758
        int type = geom.getType();
759
        if (type == Geometry.TYPES.NULL) {
760
            return false;
761
        }
762
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
763

    
764
            Envelope geomBounds = geom.getEnvelope();
765

    
766
            // ICoordTrans ct = getCoordTrans();
767
            // Se supone que la geometria ya esta reproyectada
768
            // if (ct!=null) {
769
            // // geomBounds = ct.getInverted().convert(geomBounds);
770
            // geomBounds = geomBounds.convert(ct);
771
            // }
772
            double dist1Pixel = viewPort.getDist1pixel();
773

    
774
            onePoint
775
                    = (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
776

    
777
            if (onePoint) {
778
                // avoid out of range exceptions
779
                org.gvsig.fmap.geom.primitive.Point p;
780
                try {
781
                    p
782
                            = geomManager.createPoint(geomBounds.getMinimum(0),
783
                                    geomBounds.getMinimum(1),
784
                                    SUBTYPES.GEOM2D);
785
                    p.transform(viewPort.getAffineTransform());
786
                    p.transform(graphicsTransform);
787
                    xyCoords[0] = (int) p.getX();
788
                    xyCoords[1] = (int) p.getY();
789
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
790
                    logger.error("Error creating a point", e);
791
                }
792

    
793
            }
794

    
795
        }
796
        return onePoint;
797
    }
798

    
799
    public boolean isLabeled() {
800
        return isLabeled;
801
    }
802

    
803
    public void setIsLabeled(boolean isLabeled) {
804
        this.isLabeled = isLabeled;
805
    }
806

    
807
    public ILabelingStrategy getLabelingStrategy() {
808
        return strategy;
809
    }
810

    
811
    public void setLabelingStrategy(ILabelingStrategy strategy) {
812
        this.strategy = strategy;
813
        if (strategy == null) {
814
            return;
815
        }
816
        strategy.setLayer(this);
817
        updateDrawVersion();
818
    }
819

    
820
    public void drawLabels(BufferedImage image,
821
            Graphics2D g,
822
            ViewPort viewPort,
823
            Cancellable cancel,
824
            double scale,
825
            double dpi) throws ReadException {
826
        if (strategy != null && isWithinScale(scale)) {
827
            strategy.draw(image, g, scale, viewPort, cancel, dpi);
828
        }
829
    }
830

    
831
    public void printLabels(Graphics2D g,
832
            ViewPort viewPort,
833
            Cancellable cancel,
834
            double scale,
835
            PrintAttributes properties) throws ReadException {
836
        if (strategy != null) {
837
            strategy.print(g, scale, viewPort, cancel, properties);
838
        }
839
    }
840

    
841
    /**
842
     * Return true, because a Vectorial Layer supports HyperLink
843
     *
844
     * @deprecated the hiperlink functionaliti is out the layer now
845
     */
846
    public boolean allowLinks() {
847
        return false;
848
    }
849

    
850
    public void load() throws LoadLayerException {
851
        super.load();
852
    }
853

    
854
    public FeatureStore getFeatureStore() {
855
        return (FeatureStore) getDataStore();
856
    }
857

    
858
    public FeatureQuery createFeatureQuery() {
859
        if (this.baseQuery == null) {
860
            return this.getFeatureStore().createFeatureQuery();
861
        }
862
        try {
863
            return (FeatureQuery) baseQuery.clone();
864
        } catch (CloneNotSupportedException ex) {
865
            throw new RuntimeException(ex);
866
        }
867
    }
868

    
869
    /**
870
     * @deprecated use instead
871
     * {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
872
     */
873
    public FeatureSet queryByPoint(Point2D mapPoint,
874
            double tol,
875
            FeatureType featureType) throws DataException {
876
        logger.warn("Deprecated use of queryByPoint.");
877
        GeometryManager manager = GeometryLocator.getGeometryManager();
878
        org.gvsig.fmap.geom.primitive.Point center;
879
        try {
880
            center
881
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
882
                            SUBTYPES.GEOM2D);
883
            center.setX(mapPoint.getX());
884
            center.setY(mapPoint.getY());
885
            Circle circle
886
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
887
            circle.setPoints(center, tol);
888
            return queryByGeometry(circle, featureType);
889
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
890
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
891
        }
892
    }
893

    
894
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
895
            double tol,
896
            FeatureType featureType) throws DataException {
897
        GeometryManager manager = GeometryLocator.getGeometryManager();
898
        try {
899
            Circle circle
900
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
901
            circle.setPoints(point, tol);
902
            return queryByGeometry(circle, featureType);
903
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
904
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
905
        }
906
    }
907

    
908
    public FeatureQuery createQueryByPoint(double x, double y,
909
            double tol,
910
            FeatureType featureType) throws DataException {
911
        GeometryManager manager = GeometryLocator.getGeometryManager();
912
        org.gvsig.fmap.geom.primitive.Point center;
913
        try {
914
            center
915
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
916
                            SUBTYPES.GEOM2D);
917
            center.setX(x);
918
            center.setY(y);
919
            Circle circle
920
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
921
            circle.setPoints(center, tol);
922
            return createQueryByGeometry(circle, featureType);
923
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
924
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
925
        }
926
    }
927

    
928
    /**
929
     * Input geom must be in the CRS of the view.
930
     *
931
     * @param geom
932
     * @param featureType
933
     * @return
934
     * @throws DataException
935
     */
936
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
937
        FeatureQuery featureQuery = createFeatureQuery();
938
        featureQuery.setFeatureType(featureType);
939

    
940
        Geometry query_geo = this.transformToSourceCRS(geom, true);
941
        IProjection query_proj = getMapContext().getProjection();
942
        if (this.getCoordTrans() != null) {
943
            query_proj = this.getCoordTrans().getPOrig();
944
        }
945
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
946
                query_geo,
947
                query_proj,
948
                featureStore
949
        );
950
        featureQuery.setFilter(iee);
951
        featureQuery.setAttributeNames(null);
952
        return getFeatureStore().getFeatureSet(featureQuery);
953

    
954
    }
955
    
956
    public FeatureQuery createQueryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
957
        FeatureQuery featureQuery = createFeatureQuery();
958
        featureQuery.setFeatureType(featureType);
959

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

    
974
    }
975
    
976
    public FeatureSet queryByContainedInGeometry(Geometry geom, FeatureType featureType) throws DataException {
977
        FeatureQuery featureQuery = createFeatureQuery();
978
        featureQuery.setFeatureType(featureType);
979

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

    
994
    }
995
    /**
996
     * It return the {@link FeatureSet} that intersects with the envelope.
997
     *
998
     * @param envelope envelope that defines the area for the query.
999
     * @param featureType only the features with this feature type are used in
1000
     * the query.
1001
     * @return the set of features that intersect with the envelope.
1002
     * @throws DataException
1003
     */
1004
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1005
        return queryByEnvelope(envelope, featureType, null);
1006
    }
1007

    
1008
    /**
1009
     * It return the {@link FeatureSet} that intersects with the envelope.
1010
     *
1011
     * @param envelope envelope that defines the area for the query in viewport
1012
     * CRS
1013
     * @param featureType only the features with this feature type are used in
1014
     * the query.
1015
     * @param names the feature attributes that have to be checked.
1016
     * @return the set of features that intersect with the envelope.
1017
     * @throws DataException
1018
     */
1019
    public FeatureSet queryByEnvelope(Envelope envelope,
1020
            FeatureType featureType,
1021
            String[] names) throws DataException {
1022
        FeatureQuery featureQuery = createFeatureQuery();
1023
        if (names == null) {
1024
            featureQuery.setFeatureType(featureType);
1025
        } else {
1026
            featureQuery.setAttributeNames(names);
1027
            featureQuery.setFeatureTypeId(featureType.getId());
1028
        }
1029

    
1030
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1031
        IProjection query_proj = getMapContext().getProjection();
1032
        if (this.getCoordTrans() != null) {
1033
            query_proj = this.getCoordTrans().getPOrig();
1034
        }
1035

    
1036
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
1037
                query_env.getGeometry(),
1038
                query_proj,
1039
                featureStore
1040
        );
1041
        featureQuery.setFilter(iee);
1042
        return getFeatureStore().getFeatureSet(featureQuery);
1043

    
1044
    }
1045
    
1046
    public FeatureSet queryByContainedInEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1047
        return queryByContainedInEnvelope(envelope, featureType, null);
1048
    }
1049
    
1050
    public FeatureSet queryByContainedInEnvelope(Envelope envelope,
1051
            FeatureType featureType,
1052
            String[] names) throws DataException {
1053
        FeatureQuery featureQuery = createFeatureQuery();
1054
        if (names == null) {
1055
            featureQuery.setFeatureType(featureType);
1056
        } else {
1057
            featureQuery.setAttributeNames(names);
1058
            featureQuery.setFeatureTypeId(featureType.getId());
1059
        }
1060

    
1061
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1062
        IProjection query_proj = getMapContext().getProjection();
1063
        if (this.getCoordTrans() != null) {
1064
            query_proj = this.getCoordTrans().getPOrig();
1065
        }
1066

    
1067
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
1068
                query_env.getGeometry(),
1069
                query_proj,
1070
                featureStore
1071
        );
1072
        featureQuery.setFilter(iee);
1073
        return getFeatureStore().getFeatureSet(featureQuery);
1074

    
1075
    }
1076
    
1077
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1078
            DataException {
1079

    
1080
        return getInfo(p, tolerance, cancel, true);
1081
    }
1082

    
1083
    public DynObjectSet getInfo(Point p,
1084
            double tolerance,
1085
            Cancellable cancel,
1086
            boolean fast) throws LoadLayerException, DataException {
1087
        Point2D infop = new Point2D.Double(p.x, p.y);
1088
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1089
        return queryByPoint(pReal,
1090
                tolerance,
1091
                getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1092
    }
1093

    
1094
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1095
            double tolerance) throws LoadLayerException, DataException {
1096
        return queryByPoint(p, tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
1097
    }
1098

    
1099
    @Override
1100
    public void legendCleared(LegendClearEvent event) {
1101
        this.updateDrawVersion();
1102
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(legend, event);
1103
        this.callLegendChanged(e);
1104
    }
1105

    
1106
    @Override
1107
    public boolean symbolChanged(SymbolLegendEvent e) {
1108
        this.updateDrawVersion();
1109
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
1110
        this.callLegendChanged(ev);
1111
        return true;
1112
    }
1113

    
1114
    public void update(Observable observable, Object notification) {
1115
        if (observable.equals(this.featureStore)) {
1116
            if (notification instanceof FeatureStoreNotification) {
1117
                FeatureStoreNotification event
1118
                        = (FeatureStoreNotification) notification;
1119
                if (event.getType() == FeatureStoreNotification.AFTER_DELETE
1120
                        || event.getType() == FeatureStoreNotification.AFTER_UNDO
1121
                        || event.getType() == FeatureStoreNotification.AFTER_REDO
1122
                        || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1123
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1124
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1125
                        || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1126
                        || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1127
                    this.updateDrawVersion();
1128

    
1129
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
1130

    
1131
                    setSpatialCacheEnabled(false);
1132
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1133
                    this.updateDrawVersion();
1134

    
1135
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
1136

    
1137
                    setSpatialCacheEnabled(true);
1138
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1139

    
1140
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE) {
1141
                    //If a transform has to be applied, try to reload the layer.
1142
                    try {
1143
                        reload();
1144
                    } catch (ReloadLayerException e) {
1145
                        logger.info("While reloading layer.", e);
1146
                        this.setAvailable(false);
1147
                    }
1148
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1149
                    this.setAvailable(false);
1150
                } else if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1151
                    this.setAvailable(true);
1152
                    setSpatialCacheEnabled(false);
1153
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1154
                    this.updateDrawVersion();
1155
                }
1156
            }
1157
        } else if (notification instanceof FeatureDrawnNotification
1158
                && spatialCache.isEnabled()) {
1159
            // This code is needed in editing mode
1160
            // for all layers involved in snapping
1161
            // (including the layer being edited)            
1162
            Geometry geometry
1163
                    = ((FeatureDrawnNotification) notification).getDrawnGeometry();
1164
            spatialCache.insert(geometry.getEnvelope(), geometry);
1165
        }
1166
    }
1167

    
1168
    private boolean isLayerToSnap() {
1169

    
1170
        if (this.getMapContext() == null) {
1171
            /*
1172
             * This happens with the graphics layer because it has no parent
1173
             */
1174
            return false;
1175
        } else {
1176
            return this.getMapContext().getLayersToSnap().contains(this);
1177
        }
1178

    
1179
        /*
1180
         Iterator itersnap = this.getMapContext().getLayersToSnap().iterator();
1181
         Object item = null;
1182
         while (itersnap.hasNext()) {
1183
         item = itersnap.next();
1184
         if (item == this) {
1185
         return true;
1186
         }
1187
         }
1188
         return false;
1189
         */
1190
    }
1191

    
1192
    /*
1193
     * (non-Javadoc)
1194
     *
1195
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1196
     */
1197
    public Set getMetadataChildren() {
1198
        Set ret = new TreeSet();
1199
        ret.add(this.featureStore);
1200
        return ret;
1201
    }
1202

    
1203
    /*
1204
     * (non-Javadoc)
1205
     *
1206
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1207
     */
1208
    public Object getMetadataID() throws MetadataException {
1209
        return "Layer(" + this.getName() + "):"
1210
                + this.featureStore.getMetadataID();
1211
    }
1212

    
1213
    public GeometryType getTypeVectorLayer() throws DataException,
1214
            LocatorException,
1215
            GeometryTypeNotSupportedException,
1216
            GeometryTypeNotValidException {
1217
        // FIXME Esto deberia de pedirse a FType!!!!
1218
        FeatureStore fs = this.getFeatureStore();
1219
        FeatureType fType = fs.getDefaultFeatureType();
1220
        FeatureAttributeDescriptor attr
1221
                = fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1222
        GeometryType geomType
1223
                = GeometryLocator.getGeometryManager()
1224
                        .getGeometryType(attr.getGeometryType(),
1225
                                attr.getGeometrySubType());
1226
        return geomType;
1227
    }
1228

    
1229
    public static class SelfRegister
1230
            implements Callable {
1231

    
1232
        @Override
1233
        public Object call() {
1234
          registerPersistence();
1235
          registerDefaultVectorLayer();
1236
          DynObjectManager dynObjectManager = ToolsLocator.getDynObjectManager();
1237
          dynObjectManager.registerTag(TAG_LAYERVECT_MAXSCALE, "Sets the maximum scale visible. Higher scales won't be drawn, -1 if not defined");
1238
          dynObjectManager.registerTag(TAG_LAYERVECT_MINSCALE, "Sets the minimum scale visible. Lower scales won't be drawn, -1 if not defined");
1239
          return true;
1240
        }
1241
        
1242
        private Object registerDefaultVectorLayer() {
1243
            MapContextManager manager = MapContextLocator.getMapContextManager();
1244
            manager.registerLayer(FeatureStore.class, FLyrVect.class);
1245
            return true;          
1246
        }
1247
        
1248
        private Object registerPersistence() {
1249
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1250

    
1251
            DynStruct definition
1252
                    = manager.addDefinition(FLyrVect.class,
1253
                            "FLyrVect",
1254
                            "FLyrVect Persistence definition",
1255
                            null,
1256
                            null);
1257
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1258
                    "FLyrDefault");
1259

    
1260
            definition.addDynFieldObject("legend")
1261
                    .setClassOfValue(IVectorLegend.class)
1262
                    .setMandatory(true);
1263
            definition.addDynFieldObject("featureStore")
1264
                    .setClassOfValue(FeatureStore.class)
1265
                    .setMandatory(true);
1266
            definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1267
            definition.addDynFieldInt("typeShape").setMandatory(true);
1268
            definition.addDynFieldObject("labelingStrategy")
1269
                    .setClassOfValue(ILabelingStrategy.class)
1270
                    .setMandatory(false);
1271

    
1272
            return true;
1273
        }
1274
    }
1275

    
1276
    @Override
1277
    protected void doDispose() throws BaseException {
1278
        dispose(featureStore);
1279
        spatialCache.clearAll();
1280
    }
1281

    
1282
    /**
1283
     * Returns envelope in layer's data source CRS from envelope provided in
1284
     * viewport CRS
1285
     *
1286
     * @param lyr
1287
     * @param env
1288
     * @return
1289
     */
1290
    public static Envelope fromViewPortCRSToSourceCRS(FLayer lyr, Envelope env) {
1291

    
1292
        if (lyr == null || env == null) {
1293
            return null;
1294
        }
1295

    
1296
        ICoordTrans ct = lyr.getCoordTrans();
1297
        if (ct == null) {
1298
            return env;
1299
        } else {
1300
            return env.convert(ct.getInverted());
1301
        }
1302
    }
1303

    
1304
    public Geometry transformToSourceCRS(Geometry geom, boolean clone) {
1305
        return fromViewPortCRSToSourceCRS(this, geom, clone);
1306
    }
1307

    
1308
    /**
1309
     * Returns geometry in layer's data source CRS from geometry provided in
1310
     * viewport CRS
1311
     *
1312
     * @param lyr
1313
     * @param geo
1314
     * @param clone
1315
     * @return
1316
     * @deprecated use the transformToSourceCRS method of layer.
1317
     */
1318
    public static Geometry fromViewPortCRSToSourceCRS(
1319
            FLayer lyr,
1320
            Geometry geo,
1321
            boolean clone) {
1322

    
1323
        if (lyr == null || geo == null) {
1324
            return null;
1325
        }
1326
        ICoordTrans ct = lyr.getCoordTrans();
1327
        Geometry resp = geo;
1328
        if (clone) {
1329
            resp = resp.cloneGeometry();
1330
        }
1331
        if (ct != null) {
1332
            resp.reProject(ct.getInverted());
1333
        }
1334
        return resp;
1335
    }
1336

    
1337
    public Iterator iterator() {
1338
        return this.getFeatureStore().iterator();
1339
    }
1340

    
1341
    protected class EnvelopeCantBeInitializedException
1342
            extends BaseException {
1343

    
1344
        /**
1345
         *
1346
         */
1347
        private static final long serialVersionUID = 4572797479347381552L;
1348
        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.";
1349
        private final static String MESSAGE_KEY = "_EnvelopeCantBeInitializedException";
1350

    
1351
        public EnvelopeCantBeInitializedException() {
1352
            super(MESSAGE_FORMAT, null, MESSAGE_KEY, serialVersionUID);
1353
        }
1354
    }
1355

    
1356
    @Override
1357
    public String getInfoString() {
1358
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
1359

    
1360
        if (!this.isAvailable()) {
1361
            builder.title().labelkey("Warning");
1362
            builder.text().value("The layer is not available.");
1363
        }
1364

    
1365
        Envelope env = null;
1366
        FeatureAttributeDescriptor attrgeom = null;
1367

    
1368
        try {
1369
            env = this.getFullEnvelope();
1370
        } catch (Exception ex) {
1371
        }
1372
        FeatureStore store = this.getFeatureStore();
1373
        try {
1374
            FeatureType ft = store.getDefaultFeatureType();
1375
            attrgeom = ft.getDefaultGeometryAttribute();
1376
        } catch (Exception ex) {
1377
        }
1378

    
1379
        builder.title().labelkey("Data_source");
1380
        builder.property().labelkey("Source_type").value(store.getProviderName());
1381
        builder.property().labelkey("origen").value(store.getFullName());
1382
        if (store.getParameters() instanceof FilesystemStoreParameters) {
1383
            File f = ((FilesystemStoreParameters) (store.getParameters())).getFile();
1384
            if (f != null && f.exists()) {
1385
                builder.property().labelkey("_Size").value("%d bytes", f.length());
1386
            }
1387
        }
1388
        if (attrgeom != null) {
1389
            builder.property().labelkey("_Geometry_column").value(attrgeom.getName());
1390
            builder.property().labelkey("_Geometry_type").value(attrgeom.getGeomType().getFullName());
1391
        }
1392

    
1393
        builder.title().labelkey("_Coordenadas_geograficas");
1394
        if (this.isAvailable()) {
1395
            builder.envelope().value(env);
1396
        }
1397

    
1398
        builder.title().labelkey("_Projection");
1399
        if (this.isAvailable()) {
1400
            builder.property().value(this.getProjection());
1401
            builder.text().asWKT(this.getProjection());
1402
        }
1403
        return builder.toString();
1404
    }
1405

    
1406
    @Override
1407
    public boolean isTemporary() {
1408
        if (this.featureStore != null) {
1409
            if (this.featureStore.isTemporary()) {
1410
                return true;
1411
            }
1412
        }
1413
        return super.isTemporary();
1414
    }
1415
}