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

History | View | Annotate | Download (40.9 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6 42289 jjdelcerro
 * 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 40435 jjdelcerro
 *
11 42289 jjdelcerro
 * 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 40435 jjdelcerro
 *
16 42289 jjdelcerro
 * 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 40435 jjdelcerro
 *
20 42289 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40435 jjdelcerro
 */
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 42293 jjdelcerro
import java.util.Iterator;
31 40435 jjdelcerro
import java.util.Set;
32
import java.util.TreeSet;
33
34
import org.cresques.cts.ICoordTrans;
35
import org.cresques.cts.IProjection;
36
import org.slf4j.LoggerFactory;
37
38
import org.gvsig.compat.print.PrintAttributes;
39
import org.gvsig.fmap.dal.DataStore;
40
import org.gvsig.fmap.dal.exception.DataException;
41
import org.gvsig.fmap.dal.exception.ReadException;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
43
import org.gvsig.fmap.dal.feature.FeatureQuery;
44
import org.gvsig.fmap.dal.feature.FeatureSet;
45
import org.gvsig.fmap.dal.feature.FeatureStore;
46
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
47
import org.gvsig.fmap.dal.feature.FeatureType;
48
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
49
import org.gvsig.fmap.geom.Geometry;
50
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
51
import org.gvsig.fmap.geom.Geometry.TYPES;
52
import org.gvsig.fmap.geom.GeometryLocator;
53
import org.gvsig.fmap.geom.GeometryManager;
54
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
55
import org.gvsig.fmap.geom.primitive.Circle;
56
import org.gvsig.fmap.geom.primitive.Envelope;
57
import org.gvsig.fmap.geom.type.GeometryType;
58
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
59
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
60
import org.gvsig.fmap.mapcontext.MapContextLocator;
61
import org.gvsig.fmap.mapcontext.MapContextManager;
62
import org.gvsig.fmap.mapcontext.ViewPort;
63
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
64
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
65
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
66
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
67
import org.gvsig.fmap.mapcontext.layers.FLayer;
68
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
69
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
70
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
71
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
72
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
73
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
74
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
75
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
76
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
77
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
78 42802 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendEvent;
79 40435 jjdelcerro
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
80
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
81
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
82
import org.gvsig.metadata.exceptions.MetadataException;
83
import org.gvsig.tools.ToolsLocator;
84
import org.gvsig.tools.dynobject.DynObjectSet;
85
import org.gvsig.tools.dynobject.DynStruct;
86 42820 dmartinezizquierdo
import org.gvsig.tools.evaluator.Evaluator;
87 40435 jjdelcerro
import org.gvsig.tools.exception.BaseException;
88
import org.gvsig.tools.locator.LocatorException;
89
import org.gvsig.tools.observer.Observable;
90
import org.gvsig.tools.observer.Observer;
91
import org.gvsig.tools.persistence.PersistenceManager;
92
import org.gvsig.tools.persistence.PersistentState;
93
import org.gvsig.tools.persistence.exception.PersistenceException;
94
import org.gvsig.tools.task.Cancellable;
95 41840 jjdelcerro
import org.gvsig.tools.util.Callable;
96 40435 jjdelcerro
97
/**
98
 * Capa b?sica Vectorial.
99 42289 jjdelcerro
 *
100 40435 jjdelcerro
 */
101
public class FLyrVect extends FLyrDefault implements VectorLayer,
102 42289 jjdelcerro
        LegendContentsChangedListener, Observer {
103 40435 jjdelcerro
104 42289 jjdelcerro
    final static private org.slf4j.Logger logger
105
            = LoggerFactory.getLogger(FLyrVect.class);
106
    private final GeometryManager geomManager
107
            = GeometryLocator.getGeometryManager();
108 40435 jjdelcerro
109 42289 jjdelcerro
    /**
110
     * Leyenda de la capa vectorial
111
     */
112 40435 jjdelcerro
    private IVectorLegend legend;
113
    private int typeShape = -1;
114
    private FeatureStore featureStore = null;
115
    private SpatialCache spatialCache = new SpatialCache();
116
117
    /**
118
     * An implementation of gvSIG spatial index
119
     */
120
    // protected ISpatialIndex spatialIndex = null;
121
    private IVectorLegend loadLegend = null;
122
123
    private boolean isLabeled;
124
    protected ILabelingStrategy strategy;
125
//        private ReprojectDefaultGeometry reprojectTransform;
126 42775 jjdelcerro
    private FeatureQuery baseQuery = null;
127 40435 jjdelcerro
128
    public FLyrVect() {
129
        super();
130
    }
131 42289 jjdelcerro
132
    public String getTocImageIcon() {
133
        if (this.isAvailable()) {
134 40435 jjdelcerro
            return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
135 42289 jjdelcerro
        } else {
136
            /*
137
             * data store can be be null,
138
             * for example, a layer not loaded from persistence
139
             */
140 40435 jjdelcerro
            return "layer-icon-unavailable";
141 42289 jjdelcerro
        }
142 40435 jjdelcerro
143 42289 jjdelcerro
    }
144
145 40435 jjdelcerro
    /**
146
     * Devuelve el VectorialAdapater de la capa.
147 42289 jjdelcerro
     *
148 40435 jjdelcerro
     * @return VectorialAdapter.
149
     */
150
    public DataStore getDataStore() {
151 42811 jjdelcerro
//        if (!this.isAvailable()) {
152
//            return null;
153
//        }
154 40435 jjdelcerro
        return featureStore;
155
    }
156 42289 jjdelcerro
157 40435 jjdelcerro
    /**
158 42289 jjdelcerro
     * Asigna el data-store a la capa. Esta operacion no se deneria poder hacer
159
     * desde fuera de la clase.
160
     *
161 40435 jjdelcerro
     * @param dataStore
162
     * @throws LoadLayerException
163
     * @deprecated use {@link #bindToDataStore(DataStore)}
164
     */
165
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
166 42289 jjdelcerro
        bindToDataStore(dataStore);
167 40435 jjdelcerro
    }
168 42289 jjdelcerro
169 40435 jjdelcerro
    /**
170
     * Enlaza la capa con el DataStore indicado.
171 42289 jjdelcerro
     *
172 40435 jjdelcerro
     * @param dataStore
173
     * @throws LoadLayerException
174
     */
175
    protected void bindToDataStore(DataStore dataStore) throws LoadLayerException {
176
        if (this.featureStore != null && this.featureStore != dataStore) {
177
            this.featureStore.deleteObserver(this);
178
        }
179
180
        featureStore = (FeatureStore) dataStore;
181
182 42289 jjdelcerro
        MapContextManager mapContextManager
183
                = MapContextLocator.getMapContextManager();
184
185 40435 jjdelcerro
        //Set the legend
186 42289 jjdelcerro
        IVectorLegend legend
187
                = (IVectorLegend) mapContextManager.getLegend(dataStore);
188 40435 jjdelcerro
189
        if (legend == null) {
190
            throw new LegendLayerException(this.getName());
191
        }
192
193
        this.setLegend(legend);
194
195
        //Set the labeling strategy
196 42289 jjdelcerro
        ILabelingStrategy labeler
197
                = (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
198 40435 jjdelcerro
199
        if (labeler != null) {
200
            labeler.setLayer(this);
201
            this.setLabelingStrategy(labeler);
202
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
203 42289 jjdelcerro
            // etiquetes?????
204 40435 jjdelcerro
        }
205
206
        this.delegate(dataStore);
207
208
        dataStore.addObserver(this);
209
210
        ToolsLocator.getDisposableManager().bind(dataStore);
211
    }
212
213
    public Envelope getFullEnvelope() throws ReadException {
214
        Envelope rAux;
215
        try {
216
            rAux = getFeatureStore().getEnvelope();
217
        } catch (BaseException e) {
218
            throw new ReadException(getName(), e);
219
        }
220
221
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
222
        // y alto 0.
223
        if (rAux == null || rAux.isEmpty() || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
224 42289 jjdelcerro
                && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
225 40435 jjdelcerro
            try {
226 42289 jjdelcerro
                rAux
227
                        = geomManager.createEnvelope(0, 0, 90, 90, SUBTYPES.GEOM2D);
228 40435 jjdelcerro
            } catch (CreateEnvelopeException e) {
229
                logger.error("Error creating the envelope", e);
230
                e.printStackTrace();
231
            }
232
        }
233
        // Si existe reproyecci?n, reproyectar el extent
234
        ICoordTrans ct = getCoordTrans();
235
        if (ct != null) {
236 42289 jjdelcerro
            rAux = rAux.convert(ct);
237 40435 jjdelcerro
        }
238
        return rAux;
239
240
    }
241 42820 dmartinezizquierdo
242 42775 jjdelcerro
    public void setBaseQuery(FeatureQuery baseQuery) {
243
        this.baseQuery = baseQuery;
244
    }
245 40435 jjdelcerro
246 42775 jjdelcerro
    @Override
247
    public FeatureQuery getBaseQuery() {
248
        return this.baseQuery;
249
    }
250
251 42820 dmartinezizquierdo
    public void addBaseFilter(Evaluator filter) {
252
        if( this.baseQuery == null ) {
253
            this.baseQuery = this.getFeatureStore().createFeatureQuery();
254
        }
255
        this.baseQuery.addFilter(filter);
256
    }
257
258 40435 jjdelcerro
    /**
259
     * Draws using IFeatureIterator. This method will replace the old draw(...)
260
     * one.
261 42289 jjdelcerro
     *
262 40435 jjdelcerro
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
263
     * @param image
264
     * @param g
265
     * @param viewPort
266
     * @param cancel
267
     * @param scale
268
     * @throws ReadDriverException
269
     */
270
    public void draw(BufferedImage image,
271 42289 jjdelcerro
            Graphics2D g,
272
            ViewPort viewPort,
273
            Cancellable cancel,
274
            double scale) throws ReadException {
275 40435 jjdelcerro
276
        if (legend == null) {
277
            return;
278
        }
279
280
        if (!this.isWithinScale(scale)) {
281
            return;
282
        }
283
        if (cancel.isCanceled()) {
284
            return;
285
        }
286
287
        if (spatialCache.isEnabled()) {
288
            spatialCache.clearAll();
289
            legend.addDrawingObserver(this);
290
        }
291
292 42809 jbadia
        FeatureQuery featureQuery = createFeatureQuery();
293 42775 jjdelcerro
294 40435 jjdelcerro
        try {
295 42289 jjdelcerro
            FeatureAttributeDescriptor featureAttributeDescriptor
296
                    = getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
297 40435 jjdelcerro
298 42289 jjdelcerro
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)) {
299
                IntersectsTimeEvaluator intersectsTimeEvaluator
300
                        = new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
301 40435 jjdelcerro
                featureQuery.addFilter(intersectsTimeEvaluator);
302
            }
303
        } catch (DataException e1) {
304
            logger.error("Impossible to get the temporal filter", e1);
305
        }
306
307
        try {
308 42289 jjdelcerro
309 40435 jjdelcerro
            long tini = System.currentTimeMillis();
310 42289 jjdelcerro
311 40435 jjdelcerro
            legend.draw(image,
312 42289 jjdelcerro
                    g,
313
                    viewPort,
314
                    cancel,
315
                    scale,
316
                    null,
317
                    getCoordTrans(),
318
                    getFeatureStore(),
319
                    featureQuery);
320 40435 jjdelcerro
321 42289 jjdelcerro
            logger.debug("Layer " + this.getName() + " drawn in "
322
                    + (System.currentTimeMillis() - tini) + " milliseconds.");
323
324 40435 jjdelcerro
        } catch (LegendException e) {
325 42811 jjdelcerro
            this.setAvailable(false);
326
            this.setError(e);
327 40435 jjdelcerro
            throw new ReadException(getName(), e);
328
        } finally {
329
            if (spatialCache.isEnabled()) {
330
                legend.deleteDrawingObserver(this);
331
            }
332
        }
333
    }
334
335
    public void print(Graphics2D g,
336 42289 jjdelcerro
            ViewPort viewPort,
337
            Cancellable cancel,
338
            double scale,
339
            PrintAttributes properties) throws ReadException {
340 40435 jjdelcerro
        if (!this.isWithinScale(scale)) {
341
            return;
342
        }
343
        if (cancel.isCanceled()) {
344
            return;
345
        }
346 42775 jjdelcerro
        FeatureQuery featureQuery = createFeatureQuery();
347 40435 jjdelcerro
348
        try {
349
            legend.print(g,
350 42289 jjdelcerro
                    viewPort,
351
                    cancel,
352
                    scale,
353
                    null,
354
                    getCoordTrans(),
355
                    getFeatureStore(),
356 42775 jjdelcerro
                    featureQuery,
357 42289 jjdelcerro
                    properties);
358 40435 jjdelcerro
359
        } catch (LegendException e) {
360
            this.setVisible(false);
361
            this.setActive(false);
362
            throw new ReadException(getName(), e);
363
        }
364
    }
365
366
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
367
        if (this.legend == legend) {
368
            return;
369
        }
370
        if (this.legend != null && this.legend.equals(legend)) {
371
            return;
372
        }
373
        IVectorLegend oldLegend = this.legend;
374
        this.legend = legend;
375
        if (oldLegend != null) {
376
            oldLegend.removeLegendListener(this);
377
            oldLegend.deleteDrawingObserver(this);
378
        }
379
        if (legend != null) {
380
            this.legend.addDrawingObserver(this);
381
            this.legend.addLegendListener(this);
382
        }
383 42802 jjdelcerro
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
384 40435 jjdelcerro
        e.setLayer(this);
385
        updateDrawVersion();
386
        callLegendChanged(e);
387
    }
388
389
    /**
390
     * Devuelve la Leyenda de la capa.
391 42289 jjdelcerro
     *
392 40435 jjdelcerro
     * @return Leyenda.
393
     */
394
    public ILegend getLegend() {
395
        return legend;
396
    }
397
398
    public int getShapeType() throws ReadException {
399 42289 jjdelcerro
        if (typeShape == -1) {
400
            FeatureType featureType = null;
401
            try {
402
                if (getDataStore() != null) {
403
                    featureType
404
                            = (((FeatureStore) getDataStore()).getDefaultFeatureType());
405
                }
406
            } catch (DataException e) {
407
                throw new ReadException(getName(), e);
408
            }
409
            if (featureType != null) {
410
                int indexGeom = featureType.getDefaultGeometryAttributeIndex();
411
                typeShape
412
                        = featureType.getAttributeDescriptor(indexGeom).getGeometryType();
413
            }
414
        }
415
        return typeShape;
416 40435 jjdelcerro
    }
417
418
    /**
419
     * Returns the layer's geometry type
420 42289 jjdelcerro
     *
421 40435 jjdelcerro
     * @return the geometry type
422 42289 jjdelcerro
     *
423
     * @throws ReadException if there is an error getting the geometry type
424 40435 jjdelcerro
     */
425
    public GeometryType getGeometryType() throws ReadException {
426
        FeatureType featureType = null;
427
        try {
428
            if (getDataStore() != null) {
429 42289 jjdelcerro
                featureType
430
                        = (((FeatureStore) getDataStore()).getDefaultFeatureType());
431 40435 jjdelcerro
            }
432
        } catch (DataException e) {
433
            throw new ReadException(getName(), e);
434
        }
435
        return featureType == null ? null : featureType
436 42289 jjdelcerro
                .getDefaultGeometryAttribute().getGeomType();
437 40435 jjdelcerro
    }
438
439
    public void saveToState(PersistentState state) throws PersistenceException {
440
441 41807 jjdelcerro
        FeatureStore featureStore = null;
442
443 42289 jjdelcerro
        if (!this.isAvailable()) {
444 41807 jjdelcerro
            logger.info("The '" + this.getName() + "' layer is not available, it will persist not.");
445 40435 jjdelcerro
            return;
446
        }
447 42289 jjdelcerro
448 41807 jjdelcerro
        try {
449
            super.saveToState(state);
450 40435 jjdelcerro
451 42289 jjdelcerro
            if (getLegend() != null) {
452 41807 jjdelcerro
                state.set("legend", getLegend());
453
            }
454 40435 jjdelcerro
455 41807 jjdelcerro
            featureStore = getFeatureStore();
456 40435 jjdelcerro
457 42289 jjdelcerro
            if (featureStore != null) {
458 41807 jjdelcerro
                state.set("featureStore", featureStore);
459
            }
460 40435 jjdelcerro
461 41807 jjdelcerro
            state.set("isLabeled", isLabeled);
462 40435 jjdelcerro
463 42289 jjdelcerro
            if (strategy != null) {
464 41807 jjdelcerro
                state.set("labelingStrategy", strategy);
465
            }
466 40435 jjdelcerro
467 42289 jjdelcerro
            if (getLinkProperties() != null) {
468 41807 jjdelcerro
                state.set("linkProperties", getLinkProperties());
469
            }
470 40435 jjdelcerro
471 41807 jjdelcerro
            state.set("typeShape", typeShape);
472
        } catch (PersistenceException ex) {
473
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
474
            throw ex;
475
        } catch (RuntimeException ex) {
476
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
477
            throw ex;
478 40435 jjdelcerro
        }
479
480
    }
481
482
    public void loadFromState(PersistentState state) throws PersistenceException {
483
484
        DataStore store = null;
485 41807 jjdelcerro
        IVectorLegend vectorLegend = null;
486
        ILabelingStrategy labelingStrategy = null;
487
        Boolean isLabeled = Boolean.FALSE;
488 41146 jldominguez
489 40435 jjdelcerro
        try {
490 42289 jjdelcerro
            super.loadFromState(state);
491
            store = (DataStore) state.get("featureStore");
492 40435 jjdelcerro
493 41807 jjdelcerro
            try {
494
                this.bindToDataStore(store);
495
            } catch (LoadLayerException e) {
496 42289 jjdelcerro
                throw new PersistenceException("Can't bind layer '" + this.getName() + "' to store '" + store.getFullName() + "'.", e);
497 41807 jjdelcerro
            }
498 40435 jjdelcerro
499 41807 jjdelcerro
            vectorLegend = (IVectorLegend) state.get("legend");
500
501
            try {
502
                this.setLegend(vectorLegend);
503
            } catch (LegendLayerException e) {
504
                throw new PersistenceException("Can't set vector legend to the layer.", e);
505 40435 jjdelcerro
            }
506
507 41807 jjdelcerro
            try {
508
                isLabeled = (Boolean) state.get("isLabeled");
509 42289 jjdelcerro
                if (isLabeled.booleanValue()) {
510 41807 jjdelcerro
                    labelingStrategy = (ILabelingStrategy) state.get("labelingStrategy");
511
                }
512
            } catch (Exception ex) {
513
                throw new PersistenceException("Can't load labeling strategi from persistent state.",
514
                        ex);
515
            }
516 40435 jjdelcerro
517 42289 jjdelcerro
            if (isLabeled.booleanValue()) {
518 41807 jjdelcerro
                this.setIsLabeled(true);
519
                this.setLabelingStrategy(labelingStrategy);
520
            } else {
521
                this.setIsLabeled(false);
522
                this.setLabelingStrategy(null);
523
            }
524 40435 jjdelcerro
525 41807 jjdelcerro
            typeShape = state.getInt("typeShape");
526
527
        } catch (Throwable e) {
528 42289 jjdelcerro
            String storeName = (store == null) ? "unknow" : store.getFullName();
529
            logger.warn("can't load layer '" + this.getName() + "' (store=" + storeName + ") from persisted state.", e);
530 41807 jjdelcerro
            this.setAvailable(false);
531
            return;
532
        }
533
534 40435 jjdelcerro
    }
535
536
    /**
537
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
538
     * identifiquen la capa.
539 42289 jjdelcerro
     *
540 40435 jjdelcerro
     * @return DOCUMENT ME!
541
     */
542
    public String toString() {
543
        /*
544
         * Se usa internamente para que la parte de datos identifique de forma
545
         * un?voca las tablas
546
         */
547
        String ret = super.toString();
548
549 42651 jjdelcerro
        return ret ; //"layer" + ret.substring(ret.indexOf('@') + 1);
550 40435 jjdelcerro
    }
551
552
    public boolean isEditing() {
553
        FeatureStore fs = getFeatureStore();
554
        if (fs == null) {
555
            /*
556
             * This happens when layer is not available, for example,
557
             * it was not possible to load from persistence
558
             */
559
            return false;
560
        } else {
561
            return fs.isEditing();
562
        }
563
    }
564 42289 jjdelcerro
565 40435 jjdelcerro
    public void setEditing(boolean b) throws StartEditionLayerException {
566 42289 jjdelcerro
567 40435 jjdelcerro
        try {
568
            throw new RuntimeException();
569
        } catch (Throwable th) {
570
            logger.info("This method is deprecated. ", th);
571
        }
572 42289 jjdelcerro
573 40435 jjdelcerro
        if (b == super.isEditing()) {
574
            return;
575
        }
576 42289 jjdelcerro
577 40435 jjdelcerro
        super.setEditing(b);
578
        FeatureStore fs = getFeatureStore();
579
        if (b) {
580
            try {
581
                fs.edit();
582
            } catch (DataException e) {
583
                throw new StartEditionLayerException(getName(), e);
584
            }
585
        }
586
        setSpatialCacheEnabled(b);
587
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
588
    }
589
590
    /**
591
     * @deprecated Use {@link #getSpatialCache()}
592
     */
593
    public void clearSpatialCache() {
594
        spatialCache.clearAll();
595
    }
596
597
    /**
598
     * @deprecated Use {@link #getSpatialCache()}
599
     */
600
    public boolean isSpatialCacheEnabled() {
601
        return spatialCache.isEnabled();
602
    }
603
604
    /**
605
     * @deprecated Use {@link #getSpatialCache()}
606
     */
607
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
608
        spatialCache.setEnabled(spatialCacheEnabled);
609
    }
610
611
    public SpatialCache getSpatialCache() {
612
        return spatialCache;
613
    }
614
615
    /**
616
     * Siempre es un numero mayor de 1000
617 42289 jjdelcerro
     *
618 40435 jjdelcerro
     * @param maxFeatures
619
     */
620
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
621
        if (maxFeatures > spatialCache.getMaxFeatures()) {
622
            spatialCache.setMaxFeatures(maxFeatures);
623
        }
624
625
    }
626
627
    /**
628 42289 jjdelcerro
     * This method returns a boolean that is used by the FPopMenu to make
629
     * visible the properties menu or not. It is visible by default, and if a
630
     * later don't have to show this menu only has to override this method.
631
     *
632
     * @return If the properties menu is visible (or not)
633 40435 jjdelcerro
     */
634
    public boolean isPropertiesMenuVisible() {
635
        return true;
636
    }
637
638
    public void reload() throws ReloadLayerException {
639
        super.reload();
640
        try {
641
            getFeatureStore().refresh();
642
        } catch (Exception e) {
643
            throw new ReloadLayerException(getName(), e);
644
        }
645
    }
646
647
    protected void setLoadSelection(Object xml) {
648
        // this.loadSelection = xml;
649
    }
650
651
    protected void setLoadLegend(IVectorLegend legend) {
652
        this.loadLegend = legend;
653
    }
654
655
    protected void putLoadSelection() {
656
        // if (this.loadSelection == null) return;
657
        // try {
658
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
659
        // } catch (ReadDriverException e) {
660
        // throw new XMLException(e);
661
        // }
662
        // this.loadSelection = null;
663
664
    }
665
666
    protected void putLoadLegend() throws LegendLayerException {
667
        if (this.loadLegend == null) {
668
            return;
669
        }
670
        this.setLegend(this.loadLegend);
671
        this.loadLegend = null;
672
    }
673
674
    protected void cleanLoadOptions() {
675
        this.loadLegend = null;
676
    }
677
678
    public boolean isWritable() {
679
        return getFeatureStore().allowWrite();
680
    }
681
682
    public FLayer cloneLayer() throws Exception {
683
        FLyrVect clonedLayer = new FLyrVect();
684
        clonedLayer.bindToDataStore(getDataStore());
685
        // if (isJoined()) {
686
        // clonedLayer.setIsJoined(true);
687
        // }
688
        clonedLayer.setVisible(isVisible());
689
        // clonedLayer.setISpatialIndex(getISpatialIndex());
690
        clonedLayer.setName(getName());
691
        clonedLayer.setCoordTrans(getCoordTrans());
692
693
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
694
695
        clonedLayer.setIsLabeled(isLabeled());
696
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
697
        if (labelingStrategy != null) {
698
            clonedLayer.setLabelingStrategy(labelingStrategy);
699
        }
700
701
        return clonedLayer;
702
    }
703
704
    protected boolean isOnePoint(AffineTransform graphicsTransform,
705 42289 jjdelcerro
            ViewPort viewPort,
706
            double dpi,
707
            CartographicSupport csSym,
708
            Geometry geom,
709
            int[] xyCoords) {
710 40435 jjdelcerro
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
711 42289 jjdelcerro
                && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
712 40435 jjdelcerro
    }
713
714
    private boolean isOnePoint(AffineTransform graphicsTransform,
715 42289 jjdelcerro
            ViewPort viewPort,
716
            Geometry geom,
717
            int[] xyCoords) {
718 40435 jjdelcerro
        boolean onePoint = false;
719
        int type = geom.getType();
720
        if (type == Geometry.TYPES.NULL) {
721
            return false;
722
        }
723
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
724
725
            Envelope geomBounds = geom.getEnvelope();
726
727
            // ICoordTrans ct = getCoordTrans();
728
            // Se supone que la geometria ya esta reproyectada
729
            // if (ct!=null) {
730
            // // geomBounds = ct.getInverted().convert(geomBounds);
731
            // geomBounds = geomBounds.convert(ct);
732
            // }
733
            double dist1Pixel = viewPort.getDist1pixel();
734
735 42289 jjdelcerro
            onePoint
736
                    = (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
737 40435 jjdelcerro
738
            if (onePoint) {
739
                // avoid out of range exceptions
740
                org.gvsig.fmap.geom.primitive.Point p;
741
                try {
742 42289 jjdelcerro
                    p
743
                            = geomManager.createPoint(geomBounds.getMinimum(0),
744
                                    geomBounds.getMinimum(1),
745
                                    SUBTYPES.GEOM2D);
746 40435 jjdelcerro
                    p.transform(viewPort.getAffineTransform());
747
                    p.transform(graphicsTransform);
748
                    xyCoords[0] = (int) p.getX();
749
                    xyCoords[1] = (int) p.getY();
750
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
751
                    logger.error("Error creating a point", e);
752
                }
753
754
            }
755
756
        }
757
        return onePoint;
758
    }
759
760
    public boolean isLabeled() {
761
        return isLabeled;
762
    }
763
764
    public void setIsLabeled(boolean isLabeled) {
765
        this.isLabeled = isLabeled;
766
    }
767
768
    public ILabelingStrategy getLabelingStrategy() {
769
        return strategy;
770
    }
771
772
    public void setLabelingStrategy(ILabelingStrategy strategy) {
773
        this.strategy = strategy;
774
        if (strategy == null) {
775
            return;
776
        }
777
        strategy.setLayer(this);
778
        updateDrawVersion();
779
    }
780
781
    public void drawLabels(BufferedImage image,
782 42289 jjdelcerro
            Graphics2D g,
783
            ViewPort viewPort,
784
            Cancellable cancel,
785
            double scale,
786
            double dpi) throws ReadException {
787 40435 jjdelcerro
        if (strategy != null && isWithinScale(scale)) {
788 41676 jjdelcerro
            strategy.draw(image, g, scale, viewPort, cancel, dpi);
789 40435 jjdelcerro
        }
790
    }
791
792
    public void printLabels(Graphics2D g,
793 42289 jjdelcerro
            ViewPort viewPort,
794
            Cancellable cancel,
795
            double scale,
796
            PrintAttributes properties) throws ReadException {
797 40435 jjdelcerro
        if (strategy != null) {
798 41676 jjdelcerro
            strategy.print(g, scale, viewPort, cancel, properties);
799 40435 jjdelcerro
        }
800
    }
801
802
    /**
803
     * Return true, because a Vectorial Layer supports HyperLink
804 42289 jjdelcerro
     *
805 40435 jjdelcerro
     * @deprecated the hiperlink functionaliti is out the layer now
806
     */
807
    public boolean allowLinks() {
808
        return false;
809
    }
810
811
    public void load() throws LoadLayerException {
812
        super.load();
813
    }
814
815
    public FeatureStore getFeatureStore() {
816
        return (FeatureStore) getDataStore();
817
    }
818
819 42775 jjdelcerro
    public FeatureQuery createFeatureQuery() {
820
        if( this.baseQuery==null ) {
821
            return this.getFeatureStore().createFeatureQuery();
822
        }
823
        try {
824
            return (FeatureQuery) baseQuery.clone();
825
        } catch (CloneNotSupportedException ex) {
826
            throw new RuntimeException(ex);
827
        }
828
    }
829 42820 dmartinezizquierdo
830 40435 jjdelcerro
    /**
831 42289 jjdelcerro
     * @deprecated use instead
832
     * {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
833 40435 jjdelcerro
     */
834
    public FeatureSet queryByPoint(Point2D mapPoint,
835 42289 jjdelcerro
            double tol,
836
            FeatureType featureType) throws DataException {
837 40435 jjdelcerro
        logger.warn("Deprecated use of queryByPoint.");
838
        GeometryManager manager = GeometryLocator.getGeometryManager();
839
        org.gvsig.fmap.geom.primitive.Point center;
840
        try {
841 42289 jjdelcerro
            center
842
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
843
                            SUBTYPES.GEOM2D);
844 40435 jjdelcerro
            center.setX(mapPoint.getX());
845
            center.setY(mapPoint.getY());
846 42289 jjdelcerro
            Circle circle
847
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
848 40435 jjdelcerro
            circle.setPoints(center, tol);
849
            return queryByGeometry(circle, featureType);
850
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
851
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
852
        }
853
    }
854
855
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
856 42289 jjdelcerro
            double tol,
857
            FeatureType featureType) throws DataException {
858 40435 jjdelcerro
        GeometryManager manager = GeometryLocator.getGeometryManager();
859
        try {
860 42289 jjdelcerro
            Circle circle
861
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
862 40435 jjdelcerro
            circle.setPoints(point, tol);
863
            return queryByGeometry(circle, featureType);
864
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
865
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
866
        }
867
    }
868
869 40941 jldominguez
    /**
870
     * Input geom must be in the CRS of the view.
871 42289 jjdelcerro
     *
872 40941 jldominguez
     * @param geom
873
     * @param featureType
874
     * @return
875
     * @throws DataException
876
     */
877 40435 jjdelcerro
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
878 42775 jjdelcerro
        FeatureQuery featureQuery = createFeatureQuery();
879 42289 jjdelcerro
        String geomName
880
                = featureStore.getDefaultFeatureType()
881 40435 jjdelcerro
                .getDefaultGeometryAttributeName();
882
        featureQuery.setFeatureType(featureType);
883 42289 jjdelcerro
884 41813 jjdelcerro
        Geometry query_geo = this.transformToSourceCRS(geom, true);
885 40435 jjdelcerro
        IProjection query_proj = getMapContext().getProjection();
886
        if (this.getCoordTrans() != null) {
887 42289 jjdelcerro
            query_proj = this.getCoordTrans().getPOrig();
888 40435 jjdelcerro
        }
889
890 42289 jjdelcerro
        IntersectsGeometryEvaluator iee
891
                = new IntersectsGeometryEvaluator(
892
                        query_geo,
893
                        query_proj,
894
                        featureStore.getDefaultFeatureType(),
895
                        geomName);
896 40435 jjdelcerro
        featureQuery.setFilter(iee);
897
        featureQuery.setAttributeNames(null);
898
        return getFeatureStore().getFeatureSet(featureQuery);
899
900
    }
901
902
    /**
903
     * It return the {@link FeatureSet} that intersects with the envelope.
904 42289 jjdelcerro
     *
905
     * @param envelope envelope that defines the area for the query.
906
     * @param featureType only the features with this feature type are used in
907
     * the query.
908
     * @return the set of features that intersect with the envelope.
909 40435 jjdelcerro
     * @throws DataException
910
     */
911
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
912
        return queryByEnvelope(envelope, featureType, null);
913
    }
914
915
    /**
916
     * It return the {@link FeatureSet} that intersects with the envelope.
917 42289 jjdelcerro
     *
918
     * @param envelope envelope that defines the area for the query in viewport
919
     * CRS
920
     * @param featureType only the features with this feature type are used in
921
     * the query.
922
     * @param names the feature attributes that have to be checked.
923
     * @return the set of features that intersect with the envelope.
924 40435 jjdelcerro
     * @throws DataException
925
     */
926
    public FeatureSet queryByEnvelope(Envelope envelope,
927 42289 jjdelcerro
            FeatureType featureType,
928
            String[] names) throws DataException {
929 42775 jjdelcerro
        FeatureQuery featureQuery = createFeatureQuery();
930 40435 jjdelcerro
        if (names == null) {
931
            featureQuery.setFeatureType(featureType);
932
        } else {
933
            featureQuery.setAttributeNames(names);
934
            featureQuery.setFeatureTypeId(featureType.getId());
935
        }
936 41676 jjdelcerro
        String geomName = featureStore.getDefaultFeatureType()
937 40435 jjdelcerro
                .getDefaultGeometryAttributeName();
938 42289 jjdelcerro
939 40435 jjdelcerro
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
940
        IProjection query_proj = getMapContext().getProjection();
941
        if (this.getCoordTrans() != null) {
942 42289 jjdelcerro
            query_proj = this.getCoordTrans().getPOrig();
943 40435 jjdelcerro
        }
944 42289 jjdelcerro
945
        IntersectsGeometryEvaluator iee
946
                = new IntersectsGeometryEvaluator(
947
                        query_env.getGeometry(), query_proj,
948
                        featureStore.getDefaultFeatureType(),
949
                        geomName);
950 40435 jjdelcerro
        featureQuery.setFilter(iee);
951
        return getFeatureStore().getFeatureSet(featureQuery);
952
953
    }
954
955
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
956 42289 jjdelcerro
            DataException {
957 40435 jjdelcerro
958
        return getInfo(p, tolerance, cancel, true);
959
    }
960
961
    public DynObjectSet getInfo(Point p,
962 42289 jjdelcerro
            double tolerance,
963
            Cancellable cancel,
964
            boolean fast) throws LoadLayerException, DataException {
965 40435 jjdelcerro
        Point2D infop = new Point2D.Double(p.x, p.y);
966
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
967
        return queryByPoint(pReal,
968 42289 jjdelcerro
                tolerance,
969
                getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
970 40435 jjdelcerro
    }
971
972
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
973 42289 jjdelcerro
            double tolerance) throws LoadLayerException, DataException {
974
        return queryByPoint(p, tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
975 40435 jjdelcerro
    }
976 42289 jjdelcerro
977 42802 jjdelcerro
    @Override
978 40435 jjdelcerro
    public void legendCleared(LegendClearEvent event) {
979
        this.updateDrawVersion();
980 42802 jjdelcerro
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(legend,event);
981 40435 jjdelcerro
        this.callLegendChanged(e);
982
    }
983
984 42802 jjdelcerro
    @Override
985 40435 jjdelcerro
    public boolean symbolChanged(SymbolLegendEvent e) {
986
        this.updateDrawVersion();
987 42802 jjdelcerro
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
988 40435 jjdelcerro
        this.callLegendChanged(ev);
989
        return true;
990
    }
991
992
    public void update(Observable observable, Object notification) {
993
        if (observable.equals(this.featureStore)) {
994
            if (notification instanceof FeatureStoreNotification) {
995 42289 jjdelcerro
                FeatureStoreNotification event
996
                        = (FeatureStoreNotification) notification;
997 40435 jjdelcerro
                if (event.getType() == FeatureStoreNotification.AFTER_DELETE
998 42289 jjdelcerro
                        || event.getType() == FeatureStoreNotification.AFTER_UNDO
999
                        || event.getType() == FeatureStoreNotification.AFTER_REDO
1000
                        || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1001
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1002
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1003
                        || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1004
                        || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1005 40435 jjdelcerro
                    this.updateDrawVersion();
1006 42289 jjdelcerro
1007 40435 jjdelcerro
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
1008 42289 jjdelcerro
1009 40435 jjdelcerro
                    setSpatialCacheEnabled(false);
1010
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1011
                    this.updateDrawVersion();
1012 42289 jjdelcerro
1013 40435 jjdelcerro
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
1014 42289 jjdelcerro
1015 40435 jjdelcerro
                    setSpatialCacheEnabled(true);
1016
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1017
1018 42289 jjdelcerro
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE) {
1019 40435 jjdelcerro
                    //If a transform has to be applied, try to reload the layer.
1020
                    try {
1021
                        reload();
1022
                    } catch (ReloadLayerException e) {
1023 41132 jldominguez
                        logger.info("While reloading layer.", e);
1024 40435 jjdelcerro
                        this.setAvailable(false);
1025
                    }
1026
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1027
                    this.setAvailable(false);
1028 42289 jjdelcerro
                } else if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1029 40435 jjdelcerro
                    this.setAvailable(true);
1030
                    setSpatialCacheEnabled(false);
1031
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1032
                    this.updateDrawVersion();
1033
                }
1034
            }
1035 42289 jjdelcerro
        } else if (notification instanceof FeatureDrawnNotification
1036
                && (isEditing() || isLayerToSnap())) {
1037 40614 jldominguez
            // This code is needed in editing mode
1038 42289 jjdelcerro
            // for all layers involved in snapping
1039
            // (including the layer being edited)
1040
            Geometry geometry
1041
                    = ((FeatureDrawnNotification) notification).getDrawnGeometry();
1042 40435 jjdelcerro
            spatialCache.insert(geometry.getEnvelope(), geometry);
1043
        }
1044
    }
1045
1046 40614 jldominguez
    private boolean isLayerToSnap() {
1047 41223 jldominguez
1048
        if (this.getMapContext() == null) {
1049
            /*
1050
             * This happens with the graphics layer because it has no parent
1051
             */
1052
            return false;
1053
        } else {
1054
            return this.getMapContext().getLayersToSnap().contains(this);
1055
        }
1056 40614 jldominguez
1057 42289 jjdelcerro
        /*
1058
         Iterator itersnap = this.getMapContext().getLayersToSnap().iterator();
1059
         Object item = null;
1060
         while (itersnap.hasNext()) {
1061
         item = itersnap.next();
1062
         if (item == this) {
1063
         return true;
1064
         }
1065
         }
1066
         return false;
1067
         */
1068
    }
1069
1070
    /*
1071 40435 jjdelcerro
     * (non-Javadoc)
1072 42820 dmartinezizquierdo
     *
1073 40435 jjdelcerro
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1074
     */
1075
    public Set getMetadataChildren() {
1076
        Set ret = new TreeSet();
1077
        ret.add(this.featureStore);
1078
        return ret;
1079
    }
1080
1081
    /*
1082
     * (non-Javadoc)
1083 42820 dmartinezizquierdo
     *
1084 40435 jjdelcerro
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1085
     */
1086
    public Object getMetadataID() throws MetadataException {
1087
        return "Layer(" + this.getName() + "):"
1088 42289 jjdelcerro
                + this.featureStore.getMetadataID();
1089 40435 jjdelcerro
    }
1090
1091
    public GeometryType getTypeVectorLayer() throws DataException,
1092 42289 jjdelcerro
            LocatorException,
1093
            GeometryTypeNotSupportedException,
1094
            GeometryTypeNotValidException {
1095 40435 jjdelcerro
        // FIXME Esto deberia de pedirse a FType!!!!
1096
        FeatureStore fs = this.getFeatureStore();
1097
        FeatureType fType = fs.getDefaultFeatureType();
1098 42289 jjdelcerro
        FeatureAttributeDescriptor attr
1099
                = fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1100
        GeometryType geomType
1101
                = GeometryLocator.getGeometryManager()
1102 40435 jjdelcerro
                .getGeometryType(attr.getGeometryType(),
1103 42289 jjdelcerro
                        attr.getGeometrySubType());
1104 40435 jjdelcerro
        return geomType;
1105
    }
1106
1107 41840 jjdelcerro
    public static class RegisterPersistence implements Callable {
1108 40435 jjdelcerro
1109 41840 jjdelcerro
        public Object call() {
1110
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1111 40435 jjdelcerro
1112 41840 jjdelcerro
            DynStruct definition
1113
                    = manager.addDefinition(FLyrVect.class,
1114
                            "FLyrVect",
1115
                            "FLyrVect Persistence definition",
1116
                            null,
1117
                            null);
1118
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1119
                    "FLyrDefault");
1120
1121
            definition.addDynFieldObject("legend")
1122
                    .setClassOfValue(IVectorLegend.class)
1123
                    .setMandatory(true);
1124
            definition.addDynFieldObject("featureStore")
1125
                    .setClassOfValue(FeatureStore.class)
1126
                    .setMandatory(true);
1127
            definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1128
            definition.addDynFieldInt("typeShape").setMandatory(true);
1129
            definition.addDynFieldObject("labelingStrategy")
1130
                    .setClassOfValue(ILabelingStrategy.class)
1131
                    .setMandatory(false);
1132
1133
            return Boolean.TRUE;
1134
        }
1135 40435 jjdelcerro
    }
1136
1137
    protected void doDispose() throws BaseException {
1138
        dispose(featureStore);
1139
        spatialCache.clearAll();
1140
    }
1141 42289 jjdelcerro
1142 40435 jjdelcerro
    /**
1143 42289 jjdelcerro
     * Returns envelope in layer's data source CRS from envelope provided in
1144
     * viewport CRS
1145
     *
1146 40435 jjdelcerro
     * @param lyr
1147
     * @param env
1148
     * @return
1149
     */
1150
    public static Envelope fromViewPortCRSToSourceCRS(FLayer lyr, Envelope env) {
1151
1152
        if (lyr == null || env == null) {
1153
            return null;
1154
        }
1155
1156
        ICoordTrans ct = lyr.getCoordTrans();
1157
        if (ct == null) {
1158
            return env;
1159
        } else {
1160
            return env.convert(ct.getInverted());
1161
        }
1162
    }
1163
1164 41813 jjdelcerro
    public Geometry transformToSourceCRS(Geometry geom, boolean clone) {
1165 42289 jjdelcerro
        return fromViewPortCRSToSourceCRS(this, geom, clone);
1166 41813 jjdelcerro
    }
1167 42289 jjdelcerro
1168 40435 jjdelcerro
    /**
1169 42289 jjdelcerro
     * Returns geometry in layer's data source CRS from geometry provided in
1170
     * viewport CRS
1171
     *
1172 40435 jjdelcerro
     * @param lyr
1173
     * @param geo
1174
     * @param clone
1175
     * @return
1176 41813 jjdelcerro
     * @deprecated use the transformToSourceCRS method of layer.
1177 40435 jjdelcerro
     */
1178
    public static Geometry fromViewPortCRSToSourceCRS(
1179 42289 jjdelcerro
            FLayer lyr,
1180
            Geometry geo,
1181
            boolean clone) {
1182
1183 40435 jjdelcerro
        if (lyr == null || geo == null) {
1184
            return null;
1185
        }
1186
        ICoordTrans ct = lyr.getCoordTrans();
1187
        Geometry resp = geo;
1188
        if (clone) {
1189
            resp = resp.cloneGeometry();
1190
        }
1191
        if (ct != null) {
1192
            resp.reProject(ct.getInverted());
1193
        }
1194
        return resp;
1195
    }
1196
1197 42293 jjdelcerro
    public Iterator iterator() {
1198
        return this.getFeatureStore().iterator();
1199
    }
1200 40435 jjdelcerro
}