Statistics
| Revision:

svn-gvsig-desktop / branches / dal_time_support / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / layers / vectorial / FLyrVect.java @ 35625

History | View | Annotate | Download (51.2 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.fmap.mapcontext.layers.vectorial;
42

    
43
import java.awt.Graphics2D;
44
import java.awt.Point;
45
import java.awt.geom.AffineTransform;
46
import java.awt.geom.Point2D;
47
import java.awt.image.BufferedImage;
48
import java.util.Set;
49
import java.util.TreeSet;
50

    
51
import org.cresques.cts.ICoordTrans;
52
import org.slf4j.LoggerFactory;
53

    
54
import org.gvsig.compat.print.PrintAttributes;
55
import org.gvsig.fmap.dal.DALLocator;
56
import org.gvsig.fmap.dal.DataManager;
57
import org.gvsig.fmap.dal.DataStore;
58
import org.gvsig.fmap.dal.DataStoreParameters;
59
import org.gvsig.fmap.dal.exception.DataException;
60
import org.gvsig.fmap.dal.exception.ReadException;
61
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
62
import org.gvsig.fmap.dal.feature.FeatureQuery;
63
import org.gvsig.fmap.dal.feature.FeatureSet;
64
import org.gvsig.fmap.dal.feature.FeatureStore;
65
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
66
import org.gvsig.fmap.dal.feature.FeatureType;
67
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
70
import org.gvsig.fmap.geom.Geometry.TYPES;
71
import org.gvsig.fmap.geom.GeometryLocator;
72
import org.gvsig.fmap.geom.GeometryManager;
73
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
74
import org.gvsig.fmap.geom.primitive.Circle;
75
import org.gvsig.fmap.geom.primitive.Envelope;
76
import org.gvsig.fmap.geom.type.GeometryType;
77
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
78
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
79
import org.gvsig.fmap.mapcontext.MapContextLocator;
80
import org.gvsig.fmap.mapcontext.ViewPort;
81
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
82
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
83
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
84
import org.gvsig.fmap.mapcontext.exceptions.ReprojectLayerException;
85
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
86
import org.gvsig.fmap.mapcontext.exceptions.StopEditionLayerException;
87
import org.gvsig.fmap.mapcontext.layers.FLayer;
88
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
89
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
90
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
91
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
92
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
93
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
94
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
95
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
96
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
97
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
98
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
99
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
100
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
101
import org.gvsig.metadata.exceptions.MetadataException;
102
import org.gvsig.tools.ToolsLocator;
103
import org.gvsig.tools.dynobject.DynObjectSet;
104
import org.gvsig.tools.dynobject.DynStruct;
105
import org.gvsig.tools.dynobject.exception.DynMethodException;
106
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
107
import org.gvsig.tools.exception.BaseException;
108
import org.gvsig.tools.locator.LocatorException;
109
import org.gvsig.tools.observer.Observable;
110
import org.gvsig.tools.observer.Observer;
111
import org.gvsig.tools.persistence.PersistenceManager;
112
import org.gvsig.tools.persistence.PersistentState;
113
import org.gvsig.tools.persistence.exception.PersistenceException;
114
import org.gvsig.tools.task.Cancellable;
115

    
116
/**
117
 * Capa b?sica Vectorial.
118
 * 
119
 * @author Fernando Gonz?lez Cort?s
120
 */
121

    
122
public class FLyrVect extends FLyrDefault implements VectorLayer,
123
LegendContentsChangedListener, Observer {
124

    
125
    final static private org.slf4j.Logger logger =
126
        LoggerFactory.getLogger(FLyrVect.class);
127
    private final GeometryManager geomManager =
128
        GeometryLocator.getGeometryManager();
129

    
130
    /** Leyenda de la capa vectorial */
131
    private IVectorLegend legend;
132
    private int typeShape = -1;
133
    private FeatureStore featureStore = null;
134
    private SpatialCache spatialCache = new SpatialCache();
135

    
136
    /**
137
     * An implementation of gvSIG spatial index
138
     */
139
    // protected ISpatialIndex spatialIndex = null;
140
    private IVectorLegend loadLegend = null;
141

    
142
    private boolean isLabeled;
143
    protected ILabelingStrategy strategy;
144

    
145
    public FLyrVect() {
146
        super();
147
    }
148

    
149
    /**
150
     * Devuelve el VectorialAdapater de la capa.
151
     * 
152
     * @return VectorialAdapter.
153
     */
154
    public DataStore getDataStore() {
155
        if (!this.isAvailable()) {
156
            return null;
157
        }
158
        return featureStore;
159
    }
160

    
161
    /**
162
     * If we use a persistent spatial index associated with this layer, and the
163
     * index is not intrisic to the layer (for example spatial databases) this
164
     * method looks for existent spatial index, and loads it.
165
     * 
166
     */
167
    // private void loadSpatialIndex() {
168
    // //FIXME: Al abrir el indice en fichero...
169
    // //?C?mo lo liberamos? un metodo Layer.shutdown()
170
    //
171
    //
172
    // ReadableVectorial source = getSource();
173
    // //REVISAR QUE PASA CON LOS DRIVERS DXF, DGN, etc.
174
    // //PUES SON VECTORIALFILEADAPTER
175
    // if (!(source instanceof VectorialFileAdapter)) {
176
    // // we are not interested in db adapters
177
    // return;
178
    // }
179
    // VectorialDriver driver = source.getDriver();
180
    // if (!(driver instanceof BoundedShapes)) {
181
    // // we dont spatially index layers that are not bounded
182
    // return;
183
    // }
184
    // File file = ((VectorialFileAdapter) source).getFile();
185
    // String fileName = file.getAbsolutePath();
186
    // File sptFile = new File(fileName + ".qix");
187
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
188
    // // before to exit, look for it in temp path
189
    // String tempPath = System.getProperty("java.io.tmpdir");
190
    // fileName = tempPath + File.separator + sptFile.getName();
191
    // sptFile = new File(fileName);
192
    // // it doesnt exists, must to create
193
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
194
    // return;
195
    // }// if
196
    // }// if
197
    //
198
    // try {
199
    // source.start();
200
    // spatialIndex = new
201
    // QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
202
    // "NM", source.getFullExtent(), source.getShapeCount(), false);
203
    // source.setSpatialIndex(spatialIndex);
204
    // } catch (SpatialIndexException e) {
205
    // spatialIndex = null;
206
    // e.printStackTrace();
207
    // return;
208
    // } catch (ReadDriverException e) {
209
    // spatialIndex = null;
210
    // e.printStackTrace();
211
    // return;
212
    // }
213
    //
214
    // }
215

    
216
    /**
217
     * Checks if it has associated an external spatial index
218
     * (an spatial index file).
219
     * 
220
     * It looks for it in main file path, or in temp system path.
221
     * If main file is rivers.shp, it looks for a file called
222
     * rivers.shp.qix.
223
     * 
224
     * @return
225
     */
226
    // public boolean isExternallySpatiallyIndexed() {
227
    // /*
228
    // * FIXME (AZABALA): Independizar del tipo de fichero de ?ndice
229
    // * con el que se trabaje (ahora mismo considera la extension .qix,
230
    // * pero esto depender? del tipo de ?ndice)
231
    // * */
232
    // ReadableVectorial source = getSource();
233
    // if (!(source instanceof VectorialFileAdapter)) {
234
    // // we are not interested in db adapters.
235
    // // think in non spatial dbs, like HSQLDB
236
    // return false;
237
    // }
238
    // File file = ((VectorialFileAdapter) source).getFile();
239
    // String fileName = file.getAbsolutePath();
240
    // File sptFile = new File(fileName + ".qix");
241
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
242
    // // before to exit, look for it in temp path
243
    // // it doesnt exists, must to create
244
    // String tempPath = System.getProperty("java.io.tmpdir");
245
    // fileName = tempPath + File.separator + sptFile.getName();
246
    // sptFile = new File(fileName);
247
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
248
    // return false;
249
    // }// if
250
    // }// if
251
    // return true;
252
    // }
253
    /**
254
     * Inserta el VectorialAdapter a la capa.
255
     * 
256
     * @param va
257
     *            VectorialAdapter.
258
     * 
259
     * @deprecated esto deber?a se ser protected
260
     */
261
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
262
        if (this.featureStore != null && this.featureStore != dataStore) {
263
            this.featureStore.deleteObserver(this);
264
        }
265

    
266
        featureStore = (FeatureStore) dataStore;
267

    
268
        IVectorLegend legend =
269
            (IVectorLegend) MapContextLocator.getMapContextManager().getLegend(dataStore);
270

    
271
        if (legend == null) {
272
            throw new LegendLayerException(this.getName());
273
        }
274

    
275
        this.setLegend(legend);
276

    
277
        ILabelingStrategy labeler = null;
278
        try {
279
            labeler =
280
                (ILabelingStrategy) dataStore.invokeDynMethod("getLabeling",
281
                    null);
282
        } catch (DynMethodNotSupportedException e1) {
283
            labeler = null;
284
        } catch (DynMethodException e1) {
285
            logger.error("Can't load the specific lebeling strategy provided for the layer {}.",
286
                this.getName(),
287
                e1);
288
        }
289

    
290
        if (labeler != null) {
291
            labeler.setLayer(this);
292
            this.setLabelingStrategy(labeler);
293
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
294
            // etiquetes?????
295
        }
296

    
297
        this.delegate(dataStore);
298

    
299
        dataStore.addObserver(this);
300

    
301
        ToolsLocator.getDisposableManager().bind(dataStore);
302
    }
303

    
304
    public Envelope getFullEnvelope() throws ReadException {
305
        Envelope rAux;
306
        try {
307
            rAux = getFeatureStore().getEnvelope();
308
        } catch (BaseException e) {
309
            throw new ReadException(getName(), e);
310
        }
311

    
312
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
313
        // y alto 0.
314
        if (rAux == null || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
315
            && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
316
            try {
317
                rAux =
318
                    geomManager.createEnvelope(0, 0, 100, 100, SUBTYPES.GEOM2D);
319
            } catch (CreateEnvelopeException e) {
320
                logger.error("Error creating the envelope", e);
321
                e.printStackTrace();
322
            }
323
        }
324
        // Si existe reproyecci?n, reproyectar el extent
325
        ICoordTrans ct = getCoordTrans();
326
        try {
327
            if (ct != null) {
328
                Point2D pt1 =
329
                    new Point2D.Double(rAux.getMinimum(0), rAux.getMinimum(1));
330
                Point2D pt2 =
331
                    new Point2D.Double(rAux.getMaximum(0), rAux.getMaximum(1));
332
                pt1 = ct.convert(pt1, null);
333
                pt2 = ct.convert(pt2, null);
334
                try {
335
                    rAux =
336
                        geomManager.createEnvelope(pt1.getX(),
337
                            pt1.getY(),
338
                            pt2.getX(),
339
                            pt2.getY(),
340
                            SUBTYPES.GEOM2D);
341
                } catch (CreateEnvelopeException e) {
342
                    logger.error("Error creating the envelope", e);
343
                    e.printStackTrace();
344
                }// new Rectangle2D.Double();
345
            }
346
        } catch (IllegalStateException e) {
347
            this.setAvailable(false);
348
            this.addError(new ReprojectLayerException(getName(), e));
349
        }
350
        return rAux;
351

    
352
    }
353

    
354
    /**
355
     * Draws using IFeatureIterator. This method will replace the old draw(...)
356
     * one.
357
     * 
358
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
359
     * @param image
360
     * @param g
361
     * @param viewPort
362
     * @param cancel
363
     * @param scale
364
     * @throws ReadDriverException
365
     */
366
    public void draw(BufferedImage image,
367
        Graphics2D g,
368
        ViewPort viewPort,
369
        Cancellable cancel,
370
        double scale) throws ReadException {
371

    
372
        if (legend == null) {
373
            return;
374
        }
375

    
376
        if (!this.isWithinScale(scale)) {
377
            return;
378
        }
379
        if (cancel.isCanceled()) {
380
            return;
381
        }
382

    
383
        if (spatialCache.isEnabled()) {
384
            spatialCache.clearAll();
385
            legend.addDrawingObserver(this);
386
        }
387

    
388
        FeatureQuery featureQuery = null;
389
        try {
390
            FeatureAttributeDescriptor featureAttributeDescriptor =
391
                getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
392

    
393
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)){
394
                featureQuery = getFeatureStore().createFeatureQuery();
395
                IntersectsTimeEvaluator intersectsTimeEvaluator =
396
                    new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
397
                featureQuery.addFilter(intersectsTimeEvaluator);
398
            }
399
        } catch (DataException e1) {
400
            logger.error("Impossible to get the temporal filter", e1);
401
        }
402

    
403
        try {
404
            legend.draw(image,
405
                g,
406
                viewPort,
407
                cancel,
408
                scale,
409
                null,
410
                getCoordTrans(),
411
                getFeatureStore(),
412
                featureQuery);
413

    
414
        } catch (LegendException e) {
415
            this.setVisible(false);
416
            this.setActive(false);
417
            throw new ReadException(getName(), e);
418
        } finally {
419
            if (spatialCache.isEnabled()) {
420
                legend.deleteDrawingObserver(this);
421
            }
422
        }
423
    }
424

    
425
    public void print(Graphics2D g,
426
        ViewPort viewPort,
427
        Cancellable cancel,
428
        double scale,
429
        PrintAttributes properties) throws ReadException {
430
        if (!this.isWithinScale(scale)) {
431
            return;
432
        }
433
        if (cancel.isCanceled()) {
434
            return;
435
        }
436

    
437
        try {
438
            legend.print(g,
439
                viewPort,
440
                cancel,
441
                scale,
442
                null,
443
                getCoordTrans(),
444
                getFeatureStore(),
445
                null,
446
                properties);
447

    
448
        } catch (LegendException e) {
449
            this.setVisible(false);
450
            this.setActive(false);
451
            throw new ReadException(getName(), e);
452
        }
453
    }
454

    
455
    /**
456
     * <p>
457
     * Creates an spatial index associated to this layer. The spatial index will
458
     * used the native projection of the layer, so if the layer is reprojected,
459
     * it will be ignored.
460
     * </p>
461
     * 
462
     * @param cancelMonitor
463
     *            instance of CancellableMonitorable that allows
464
     *            to monitor progress of spatial index creation, and cancel the
465
     *            process
466
     */
467
    // public void createSpatialIndex(CancellableMonitorable cancelMonitor){
468
    // // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
469
    // // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
470
    // // para que acepten recorrer sin geometria, solo con rectangulos.
471
    //
472
    // //If this vectorial layer is based in a spatial database, the spatial
473
    // //index is already implicit. We only will index file drivers
474
    // ReadableVectorial va = getSource();
475
    // //We must think in non spatial databases, like HSQLDB
476
    // if(!(va instanceof VectorialFileAdapter)){
477
    // return;
478
    // }
479
    // if (!(va.getDriver() instanceof BoundedShapes)) {
480
    // return;
481
    // }
482
    // File file = ((VectorialFileAdapter) va).getFile();
483
    // String fileName = file.getAbsolutePath();
484
    // ISpatialIndex localCopy = null;
485
    // try {
486
    // va.start();
487
    // localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
488
    // va.getShapeCount(), true);
489
    //
490
    // } catch (SpatialIndexException e1) {
491
    // // Probably we dont have writing permissions
492
    // String directoryName = System.getProperty("java.io.tmpdir");
493
    // File newFile = new File(directoryName +
494
    // File.separator +
495
    // file.getName());
496
    // String newFileName = newFile.getName();
497
    // try {
498
    // localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
499
    // va.getShapeCount(), true);
500
    // } catch (SpatialIndexException e) {
501
    // // if we cant build a file based spatial index, we'll build
502
    // // a pure memory spatial index
503
    // localCopy = new QuadtreeJts();
504
    // } catch (ReadException e) {
505
    // localCopy = new QuadtreeJts();
506
    // }
507
    //
508
    // } catch(Exception e){
509
    // e.printStackTrace();
510
    // }//try
511
    // BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
512
    // try {
513
    // for (int i=0; i < va.getShapeCount(); i++)
514
    // {
515
    // if(cancelMonitor != null){
516
    // if(cancelMonitor.isCanceled())
517
    // return;
518
    // cancelMonitor.reportStep();
519
    // }
520
    // Rectangle2D r = shapeBounds.getShapeBounds(i);
521
    // if(r != null)
522
    // localCopy.insert(r, i);
523
    // } // for
524
    // va.stop();
525
    // if(localCopy instanceof IPersistentSpatialIndex)
526
    // ((IPersistentSpatialIndex) localCopy).flush();
527
    // spatialIndex = localCopy;
528
    // //vectorial adapter needs a reference to the spatial index, to solve
529
    // //request for feature iteration based in spatial queries
530
    // source.setSpatialIndex(spatialIndex);
531
    // } catch (ReadException e) {
532
    // // TODO Auto-generated catch block
533
    // e.printStackTrace();
534
    // }
535
    // }
536

    
537
    // public void createSpatialIndex() {
538
    // createSpatialIndex(null);
539
    // }
540

    
541
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
542
        if (this.legend == legend) {
543
            return;
544
        }
545
        if (this.legend != null && this.legend.equals(legend)) {
546
            return;
547
        }
548
        IVectorLegend oldLegend = this.legend;
549
        this.legend = legend;
550
        if (oldLegend != null) {
551
            oldLegend.removeLegendListener(this);
552
            oldLegend.deleteDrawingObserver(this);
553
        }
554
        if (legend != null) {
555
            this.legend.addDrawingObserver(this);
556
            this.legend.addLegendListener(this);
557
        }
558
        LegendChangedEvent e =
559
            LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
560
        e.setLayer(this);
561
        callLegendChanged(e);
562
    }
563

    
564
    /**
565
     * Devuelve la Leyenda de la capa.
566
     * 
567
     * @return Leyenda.
568
     */
569
    public ILegend getLegend() {
570
        return legend;
571
    }
572

    
573
    /**
574
     * Devuelve el tipo de shape que contiene la capa.
575
     * 
576
     * @return tipo de shape.
577
     * 
578
     * @throws ReadException
579
     */
580
    public int getShapeType() throws ReadException {
581
        if (typeShape == -1) {
582
            FeatureType featureType;
583
            try {
584
                featureType =
585
                    (((FeatureStore) getDataStore()).getDefaultFeatureType());
586
            } catch (DataException e) {
587
                throw new ReadException(getName(), e);
588
            }
589
            int indexGeom = featureType.getDefaultGeometryAttributeIndex();
590
            typeShape =
591
                featureType.getAttributeDescriptor(indexGeom).getGeometryType();
592
        }
593
        return typeShape;
594
    }
595

    
596
    public void saveToState(PersistentState state) throws PersistenceException {
597

    
598
        if (!this.isAvailable()) {
599
            return;
600
        }
601

    
602
        super.saveToState(state);
603

    
604
        if (getLegend() != null) {
605
            state.set("legend", getLegend());
606
        }
607

    
608
        FeatureStore fst = null;
609
        fst = getFeatureStore();
610

    
611
        if (fst != null) {
612
            state.set("featureStore", fst);
613
        }
614

    
615
        state.set("isLabeled", isLabeled);
616

    
617
        if (strategy != null) {
618
            state.set("labelingStrategy", strategy);
619
        }
620

    
621
        if (getLinkProperties() != null) {
622
            state.set("linkProperties", getLinkProperties());
623
        }
624

    
625
        // state.set("bHasJoin", bHasJoin);
626
        state.set("typeShape", typeShape);
627
    }
628

    
629
    // public XMLEntity getXMLEntity() throws XMLException {
630
    //
631
    // if (!this.isAvailable() && this.orgXMLEntity != null) {
632
    // return this.orgXMLEntity;
633
    // }
634
    // XMLEntity xml = super.getXMLEntity();
635
    // if (getLegend()!=null){
636
    // XMLEntity xmlLegend=getLegend().getXMLEntity();
637
    // xmlLegend.putProperty("tagName","legend");
638
    // xml.addChild(xmlLegend);
639
    // }
640
    // try {
641
    // PersistenceManager manager = ToolsLocator.getPersistenceManager();
642
    // PersistentState stateFeatureStore=manager.getState(getFeatureStore());
643
    // stateFeatureStore.set("tagName","featureStore");
644
    // xml.addChild(((XMLEntityState)stateFeatureStore).getXMLEntity());
645
    // } catch (ReadException e) {
646
    // throw new XMLLayerException(getName(),e);
647
    // } catch (PersistenceException e) {
648
    // throw new XMLLayerException(getName(),e);
649
    // }
650
    // // properties from ILabelable
651
    // xml.putProperty("isLabeled", isLabeled);
652
    // if (strategy != null) {
653
    // XMLEntity strategyXML = strategy.getXMLEntity();
654
    // strategyXML.putProperty("tagName", "labelingStrategy");
655
    // xml.addChild(strategy.getXMLEntity());
656
    // }
657
    // xml.addChild(getLinkProperties().getXMLEntity());
658
    // return xml;
659
    // }
660

    
661
    public void loadFromState(PersistentState state) throws PersistenceException {
662

    
663
        super.loadFromState(state);
664

    
665
        DataStore store = (DataStore) state.get("featureStore");
666
        try {
667
            this.setDataStore(store);
668
        } catch (LoadLayerException e) {
669
            throw new PersistenceException("While loading FLyrVect from state.",
670
                e);
671
        }
672

    
673
        IVectorLegend lgnd = (IVectorLegend) state.get("legend");
674
        try {
675
            this.setLegend(lgnd);
676
        } catch (LegendLayerException e) {
677
            throw new PersistenceException("While loading FLyrVect from state.",
678
                e);
679
        }
680

    
681
        Boolean isLbl = new Boolean(false);
682
        ILabelingStrategy lblst = null;
683

    
684
        try {
685
            isLbl = (Boolean) state.get("isLabeled");
686
            if (isLbl.booleanValue()) {
687
                lblst = (ILabelingStrategy) state.get("labelingStrategy");
688
            }
689
        } catch (Exception ex) {
690
            throw new PersistenceException("While loading FLyrVect from state.",
691
                ex);
692
        }
693

    
694
        /*
695
         * String _labelFieldName = null;
696
         * String _labelfield = null;
697
         */
698

    
699
        if (isLbl.booleanValue()) {
700
            this.setIsLabeled(true);
701
            this.setLabelingStrategy(lblst);
702
        } else {
703
            this.setIsLabeled(false);
704
            this.setLabelingStrategy(null);
705
        }
706

    
707
        // try {
708
        // linkProperties = (FLyrVectLinkProperties)
709
        // state.get("linkProperties");
710
        // } catch (PersistenceException pex) {
711
        // // not mandatory
712
        // linkProperties = null;
713
        // }
714

    
715
        // bHasJoin = state.getBoolean("bHasJoin");
716
        typeShape = state.getInt("typeShape");
717

    
718
        // try { _labelFieldName = state.getString("labelFieldName"); } catch
719
        // (PersistenceException ex) {
720
        // _labelFieldName = null;
721
        // }
722
        // try { _labelfield = state.getString("labelfield"); } catch
723
        // (PersistenceException ex) {
724
        // _labelfield = null;
725
        // }
726

    
727
        // ILabelingStrategy not implemented
728
        // if (_labelFieldName != null) {
729
        //
730
        // AttrInTableLabelingStrategy labeling = new
731
        // AttrInTableLabelingStrategy();
732
        // try {
733
        // labeling.setLayer(this);
734
        // } catch (ReadException e) {
735
        // logger.error("While setting layer to AttrInTableLabelingStrategy: " +
736
        // e.getMessage());
737
        // }
738
        // labeling.setUsesFixedSize(true);
739
        // labeling.setFixedSize(10);
740
        // labeling.setTextField(_labelFieldName);
741
        // labeling.setHeightField(state.getString("labelHeightFieldName"));
742
        // labeling.setRotationField(state.getString("labelRotationFieldName"));
743
        // setLabelingStrategy(labeling);
744
        // setIsLabeled(true);
745
        //
746
        // } else {
747
        // if (_labelfield != null) {
748
        //
749
        // AttrInTableLabelingStrategy labeling = new
750
        // AttrInTableLabelingStrategy();
751
        // try {
752
        // labeling.setLayer(this);
753
        // } catch (ReadException e) {
754
        // logger.error("While setting layer to AttrInTableLabelingStrategy: " +
755
        // e.getMessage());
756
        // }
757
        // labeling.setUsesFixedSize(true);
758
        // labeling.setFixedSize(10);
759
        // labeling.setTextField(_labelfield);
760
        // labeling.setHeightField(state.getString("labelFieldHeight"));
761
        // labeling.setRotationField(state.getString("labelFieldRotation"));
762
        // setLabelingStrategy(labeling);
763
        // setIsLabeled(true);
764
        // }
765
        // }
766

    
767
    }
768

    
769
    // public void setXMLEntity(XMLEntity xml) throws XMLException {
770
    // try {
771
    // super.setXMLEntity(xml);
772
    // XMLEntity legendXML = xml.firstChild("tagName","legend");
773
    // IVectorLegend leg = LegendFactory.createFromXML(legendXML);
774
    //
775
    // // PersistentState persistentState=new XMLEntityState(new
776
    // XMLEntityManager());
777
    // XMLEntity xmlStore=xml.firstChild("tagName","featureStore");
778
    // XMLEntityManager xmlManger = new XMLEntityManager();
779
    // PersistentState state = xmlManger.createState(xmlStore);
780
    // DataStore store = (DataStore)
781
    // ToolsLocator.getPersistenceManager().create(state);
782
    // // persistentState.createState(xmlStore);
783
    //
784
    // // DataManager dm=DALLocator.getDataManager();
785
    //
786
    // this.setDataStore(store);
787
    // /* end patch */
788
    // try {
789
    // setLegend(leg);
790
    // } catch (LegendLayerException e) {
791
    // throw new XMLLegendException(e);
792
    // }
793
    // // set properties for ILabelable
794
    //
795
    // if (xml.contains("isLabeled")
796
    // && xml.getBooleanProperty(("isLabeled"))) {
797
    // XMLEntity labelingXML = xml.firstChild("tagName", "labelingStrategy");
798
    // if (labelingXML != null){
799
    //
800
    // isLabeled = true;
801
    // try {
802
    // this.strategy = LabelingFactory.createStrategyFromXML(labelingXML, this);
803
    // } catch (NotExistInXMLEntity neXMLEX) {
804
    // // no strategy was set, just continue;
805
    // logger.warn("Reached what should be unreachable code");
806
    // }
807
    // } else {
808
    // isLabeled = false;
809
    // }
810
    // } else if (legendXML.contains("labelFieldName")||
811
    // legendXML.contains("labelfield")) {
812
    // /* (jaume) begin patch;
813
    // * for backward compatibility purposes. Since gvSIG v1.1 labeling is
814
    // * no longer managed by the Legend but by the ILabelingStrategy. The
815
    // * following allows restoring older projects' labelings.
816
    // */
817
    // String labelTextField = null;
818
    // if (legendXML.contains("labelFieldName")){
819
    // labelTextField = legendXML.getStringProperty("labelFieldName");
820
    // if (labelTextField != null) {
821
    // AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
822
    // labeling.setLayer(this);
823
    // labeling.setUsesFixedSize(true);
824
    // labeling.setFixedSize(10);
825
    // labeling.setTextField(labelTextField);
826
    // labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
827
    // labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
828
    // this.setLabelingStrategy(labeling);
829
    // this.setIsLabeled(true);
830
    // }
831
    // }else{
832
    // labelTextField = legendXML.getStringProperty("labelfield");
833
    // if (labelTextField != null) {
834
    // AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
835
    // labeling.setLayer(this);
836
    // labeling.setUsesFixedSize(true);
837
    // labeling.setFixedSize(10);
838
    // labeling.setTextField(labelTextField);
839
    // labeling.setHeightField(legendXML.getStringProperty("labelFieldHeight"));
840
    // labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
841
    // this.setLabelingStrategy(labeling);
842
    // this.setIsLabeled(true);
843
    // }
844
    // }
845
    // }else{
846
    // isLabeled = false;
847
    // }
848
    // XMLEntity xmlLinkProperties=xml.firstChild("typeChild","linkProperties");
849
    // if (xmlLinkProperties != null){
850
    // getLinkProperties().setXMLEntity(xmlLinkProperties);
851
    // }
852
    // } catch (Exception e) {
853
    // e.printStackTrace();
854
    // this.setAvailable(false);
855
    // this.orgXMLEntity = xml;
856
    //
857
    // }
858
    // //
859
    //
860
    // }
861

    
862
    /**
863
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
864
     * identifiquen la capa.
865
     * 
866
     * @return DOCUMENT ME!
867
     */
868
    public String toString() {
869
        /*
870
         * Se usa internamente para que la parte de datos identifique de forma
871
         * un?voca las tablas
872
         */
873
        String ret = super.toString();
874

    
875
        return "layer" + ret.substring(ret.indexOf('@') + 1);
876
    }
877

    
878
    // public boolean isJoined() {
879
    // return bHasJoin;
880
    // }
881

    
882
    /**
883
     * Returns if a layer is spatially indexed
884
     * 
885
     * @return if this layer has the ability to proces spatial queries without
886
     *         secuential scans.
887
     * @throws StopEditionLayerException 
888
     */
889
    // public boolean isSpatiallyIndexed() {
890
    // ReadableVectorial source = getSource();
891
    // if (source instanceof ISpatialDB)
892
    // return true;
893
    //
894
    // //FIXME azabala
895
    // /*
896
    // * Esto es muy dudoso, y puede cambiar.
897
    // * Estoy diciendo que las que no son fichero o no son
898
    // * BoundedShapes estan indexadas. Esto es mentira, pero
899
    // * as? quien pregunte no querr? generar el indice.
900
    // * Esta por ver si interesa generar el indice para capas
901
    // * HSQLDB, WFS, etc.
902
    // */
903
    // if(!(source instanceof VectorialFileAdapter)){
904
    // return true;
905
    // }
906
    // if (!(source.getDriver() instanceof BoundedShapes)) {
907
    // return true;
908
    // }
909
    //
910
    // if (getISpatialIndex() != null)
911
    // return true;
912
    // return false;
913
    // }
914
    //
915
    // public void setIsJoined(boolean hasJoin) {
916
    // bHasJoin = hasJoin;
917
    // }
918

    
919
    // /**
920
    // * @return Returns the spatialIndex.
921
    // */
922
    // public ISpatialIndex getISpatialIndex() {
923
    // return spatialIndex;
924
    // }
925
    // /**
926
    // * Sets the spatial index. This could be useful if, for some
927
    // * reasons, you want to work with a distinct spatial index
928
    // * (for example, a spatial index which could makes nearest
929
    // * neighbour querys)
930
    // * @param spatialIndex
931
    // */
932
    // public void setISpatialIndex(ISpatialIndex spatialIndex){
933
    // this.spatialIndex = spatialIndex;
934
    // }
935

    
936
    public void setEditing(boolean b) throws StartEditionLayerException {
937
        super.setEditing(b);
938
        FeatureStore fs = getFeatureStore();
939
        if (b) {
940
            try {
941
                fs.edit();
942
            } catch (ReadException e) {
943
                throw new StartEditionLayerException(getName(), e);
944
            } catch (DataException e) {
945
                throw new StartEditionLayerException(getName(), e);
946
            }
947
        }
948
        setSpatialCacheEnabled(b);
949
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
950
    }
951

    
952
    /**
953
     * @deprecated Use {@link #getSpatialCache()}
954
     */
955
    public void clearSpatialCache() {
956
        spatialCache.clearAll();
957
    }
958

    
959
    /**
960
     * @deprecated Use {@link #getSpatialCache()}
961
     */
962
    public boolean isSpatialCacheEnabled() {
963
        return spatialCache.isEnabled();
964
    }
965

    
966
    /**
967
     * @deprecated Use {@link #getSpatialCache()}
968
     */
969
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
970
        spatialCache.setEnabled(spatialCacheEnabled);
971
    }
972

    
973
    public SpatialCache getSpatialCache() {
974
        return spatialCache;
975
    }
976

    
977
    /**
978
     * Siempre es un numero mayor de 1000
979
     * 
980
     * @param maxFeatures
981
     */
982
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
983
        if (maxFeatures > spatialCache.getMaxFeatures()) {
984
            spatialCache.setMaxFeatures(maxFeatures);
985
        }
986

    
987
    }
988

    
989
    /**
990
     * This method returns a boolean that is used by the FPopMenu
991
     * to make visible the properties menu or not. It is visible by
992
     * default, and if a later don't have to show this menu only
993
     * has to override this method.
994
     * 
995
     * @return
996
     *         If the properties menu is visible (or not)
997
     */
998
    public boolean isPropertiesMenuVisible() {
999
        return true;
1000
    }
1001

    
1002
    public void reload() throws ReloadLayerException {
1003
        super.reload();
1004
        try {
1005
            DataManager dataManager = DALLocator.getDataManager();
1006
            DataStoreParameters storeParameters;
1007

    
1008
            storeParameters = getFeatureStore().getParameters();
1009

    
1010
            DataStore dataStore = dataManager.createStore(storeParameters);
1011
            setDataStore(dataStore);
1012
            getFeatureStore().refresh();
1013
        } catch (Exception e) {
1014
            throw new ReloadLayerException(getName(), e);
1015
        }
1016
        // try {
1017
        // this.source.getDriver().reload();
1018
        // if (this.getLegend() == null) {
1019
        // if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1020
        // WithDefaultLegend aux = (WithDefaultLegend)
1021
        // this.getRecordset().getDriver();
1022
        // this.setLegend((IVectorLegend) aux.getDefaultLegend());
1023
        // this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1024
        // } else {
1025
        // this.setLegend(LegendFactory.createSingleSymbolLegend(
1026
        // this.getShapeType()));
1027
        // }
1028
        // }
1029
        //
1030
        // } catch (LegendLayerException e) {
1031
        // this.setAvailable(false);
1032
        // throw new ReloadLayerException(getName(),e);
1033
        // } catch (ReadException e) {
1034
        // this.setAvailable(false);
1035
        // throw new ReloadLayerException(getName(),e);
1036
        // }
1037

    
1038
    }
1039

    
1040
    protected void setLoadSelection(Object xml) {
1041
        // this.loadSelection = xml;
1042
    }
1043

    
1044
    protected void setLoadLegend(IVectorLegend legend) {
1045
        this.loadLegend = legend;
1046
    }
1047

    
1048
    protected void putLoadSelection() {
1049
        // if (this.loadSelection == null) return;
1050
        // try {
1051
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1052
        // } catch (ReadDriverException e) {
1053
        // throw new XMLException(e);
1054
        // }
1055
        // this.loadSelection = null;
1056

    
1057
    }
1058

    
1059
    protected void putLoadLegend() throws LegendLayerException {
1060
        if (this.loadLegend == null) {
1061
            return;
1062
        }
1063
        this.setLegend(this.loadLegend);
1064
        this.loadLegend = null;
1065
    }
1066

    
1067
    protected void cleanLoadOptions() {
1068
        this.loadLegend = null;
1069
    }
1070

    
1071
    public boolean isWritable() {
1072
        return getFeatureStore().allowWrite();
1073
    }
1074

    
1075
    public FLayer cloneLayer() throws Exception {
1076
        FLyrVect clonedLayer = new FLyrVect();
1077
        clonedLayer.setDataStore(getDataStore());
1078
        // if (isJoined()) {
1079
        // clonedLayer.setIsJoined(true);
1080
        // }
1081
        clonedLayer.setVisible(isVisible());
1082
        // clonedLayer.setISpatialIndex(getISpatialIndex());
1083
        clonedLayer.setName(getName());
1084
        clonedLayer.setCoordTrans(getCoordTrans());
1085

    
1086
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
1087

    
1088
        clonedLayer.setIsLabeled(isLabeled());
1089
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
1090
        if (labelingStrategy != null) {
1091
            clonedLayer.setLabelingStrategy(labelingStrategy);
1092
        }
1093

    
1094
        return clonedLayer;
1095
    }
1096

    
1097
    protected boolean isOnePoint(AffineTransform graphicsTransform,
1098
        ViewPort viewPort,
1099
        double dpi,
1100
        CartographicSupport csSym,
1101
        Geometry geom,
1102
        int[] xyCoords) {
1103
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
1104
        && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
1105
    }
1106

    
1107
    private boolean isOnePoint(AffineTransform graphicsTransform,
1108
        ViewPort viewPort,
1109
        Geometry geom,
1110
        int[] xyCoords) {
1111
        boolean onePoint = false;
1112
        int type = geom.getType();
1113
        if (type == Geometry.TYPES.NULL) {
1114
            return false;
1115
        }
1116
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
1117

    
1118
            Envelope geomBounds = geom.getEnvelope();
1119

    
1120
            // ICoordTrans ct = getCoordTrans();
1121

    
1122
            // Se supone que la geometria ya esta reproyectada
1123
            // if (ct!=null) {
1124
            // // geomBounds = ct.getInverted().convert(geomBounds);
1125
            // geomBounds = geomBounds.convert(ct);
1126
            // }
1127

    
1128
            double dist1Pixel = viewPort.getDist1pixel();
1129

    
1130
            onePoint =
1131
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
1132

    
1133
            if (onePoint) {
1134
                // avoid out of range exceptions
1135
                org.gvsig.fmap.geom.primitive.Point p;
1136
                try {
1137
                    p =
1138
                        geomManager.createPoint(geomBounds.getMinimum(0),
1139
                            geomBounds.getMinimum(1),
1140
                            SUBTYPES.GEOM2D);
1141
                    p.transform(viewPort.getAffineTransform());
1142
                    p.transform(graphicsTransform);
1143
                    xyCoords[0] = (int) p.getX();
1144
                    xyCoords[1] = (int) p.getY();
1145
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1146
                    logger.error("Error creating a point", e);
1147
                }
1148

    
1149
            }
1150

    
1151
        }
1152
        return onePoint;
1153
    }
1154

    
1155
    /*
1156
     * jaume. Stuff from ILabeled.
1157
     */
1158

    
1159
    public boolean isLabeled() {
1160
        return isLabeled;
1161
    }
1162

    
1163
    public void setIsLabeled(boolean isLabeled) {
1164
        this.isLabeled = isLabeled;
1165
    }
1166

    
1167
    public ILabelingStrategy getLabelingStrategy() {
1168
        return strategy;
1169
    }
1170

    
1171
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1172
        this.strategy = strategy;
1173
        if (strategy == null) {
1174
            return;
1175
        }
1176
        strategy.setLayer(this);
1177
    }
1178

    
1179
    public void drawLabels(BufferedImage image,
1180
        Graphics2D g,
1181
        ViewPort viewPort,
1182
        Cancellable cancel,
1183
        double scale,
1184
        double dpi) throws ReadException {
1185
        if (strategy != null && isWithinScale(scale)) {
1186
            strategy.draw(image, g, viewPort, cancel, dpi);
1187
        }
1188
    }
1189

    
1190
    public void printLabels(Graphics2D g,
1191
        ViewPort viewPort,
1192
        Cancellable cancel,
1193
        double scale,
1194
        PrintAttributes properties) throws ReadException {
1195
        if (strategy != null) {
1196
            strategy.print(g, viewPort, cancel, properties);
1197
        }
1198
    }
1199

    
1200
    // M?todos para el uso de HyperLinks en capas FLyerVect
1201

    
1202
    /**
1203
     * Return true, because a Vectorial Layer supports HyperLink
1204
     */
1205
    public boolean allowLinks() {
1206
        return true;
1207
    }
1208

    
1209
    /**
1210
     * Returns an instance of AbstractLinkProperties that contains the
1211
     * information
1212
     * of the HyperLink
1213
     * 
1214
     * @return Abstra
1215
     */
1216
    // public AbstractLinkProperties getLinkProperties()
1217
    // {
1218
    // return linkProperties;
1219
    // }
1220

    
1221
    /**
1222
     * Provides an array with URIs. Returns one URI by geometry that includes
1223
     * the point
1224
     * in its own geometry limits with a allowed tolerance.
1225
     * 
1226
     * @param layer
1227
     *            , the layer
1228
     * @param point
1229
     *            , the point to check that is contained or not in the
1230
     *            geometries in the layer
1231
     * @param tolerance
1232
     *            , the tolerance allowed. Allowed margin of error to detect if
1233
     *            the point
1234
     *            is contained in some geometries of the layer
1235
     * @return
1236
     * @throws ReadException
1237
     * @throws BehaviorException
1238
     */
1239
    // public URI[] getLink(Point2D point, double tolerance) throws
1240
    // ReadException
1241
    // {
1242
    // //return linkProperties.getLink(this)
1243
    // return linkProperties.getLink(this,point,tolerance);
1244
    // }
1245

    
1246
    public void load() throws LoadLayerException {
1247
        super.load();
1248
    }
1249

    
1250
    public FeatureStore getFeatureStore() {
1251
        return (FeatureStore) getDataStore();
1252
    }
1253

    
1254
    /**
1255
     * @deprecated use instead {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
1256
     */
1257
    public FeatureSet queryByPoint(Point2D mapPoint,
1258
        double tol,
1259
        FeatureType featureType) throws DataException {
1260
        logger.warn("Deprecated use of queryByPoint.");
1261
        GeometryManager manager = GeometryLocator.getGeometryManager();
1262
        org.gvsig.fmap.geom.primitive.Point center;
1263
        try {
1264
            center =
1265
                (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
1266
                    SUBTYPES.GEOM2D);
1267
            center.setX(mapPoint.getX());
1268
            center.setY(mapPoint.getY());
1269
            Circle circle =
1270
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
1271
            circle.setPoints(center, tol);
1272
            return queryByGeometry(circle, featureType);
1273
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1274
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
1275
        }
1276
    }
1277

    
1278
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
1279
        double tol,
1280
        FeatureType featureType) throws DataException {
1281
        GeometryManager manager = GeometryLocator.getGeometryManager();
1282
        try {
1283
            Circle circle =
1284
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
1285
            circle.setPoints(point, tol);
1286
            return queryByGeometry(circle, featureType);
1287
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1288
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
1289
        }
1290
    }
1291

    
1292
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
1293
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
1294
        String geomName =
1295
            featureStore.getDefaultFeatureType()
1296
            .getDefaultGeometryAttributeName();
1297
        featureQuery.setFeatureType(featureType);
1298
        IntersectsGeometryEvaluator iee =
1299
            new IntersectsGeometryEvaluator(geom,
1300
                getMapContext().getViewPort().getProjection(),
1301
                featureStore.getDefaultFeatureType(),
1302
                geomName);
1303
        featureQuery.setFilter(iee);
1304
        return getFeatureStore().getFeatureSet(featureQuery);
1305

    
1306
    }
1307

    
1308
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1309
        return queryByEnvelope(envelope, featureType, null);
1310
    }
1311

    
1312
    public FeatureSet queryByEnvelope(Envelope envelope,
1313
        FeatureType featureType,
1314
        String[] names) throws DataException {
1315
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
1316
        if (names == null) {
1317
            featureQuery.setFeatureType(featureType);
1318
        } else {
1319
            featureQuery.setAttributeNames(names);
1320
            featureQuery.setFeatureTypeId(featureType.getId());
1321
        }
1322
        String geomName =
1323
            featureStore.getDefaultFeatureType()
1324
            .getDefaultGeometryAttributeName();
1325
        ContainsEnvelopeEvaluator iee =
1326
            new ContainsEnvelopeEvaluator(envelope,
1327
                getMapContext().getViewPort().getProjection(),
1328
                featureStore.getDefaultFeatureType(),
1329
                geomName);
1330
        featureQuery.setFilter(iee);
1331
        return getFeatureStore().getFeatureSet(featureQuery);
1332

    
1333
    }
1334

    
1335
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1336
    DataException {
1337

    
1338
        return getInfo(p, tolerance, cancel, true);
1339
    }
1340

    
1341
    public DynObjectSet getInfo(Point p,
1342
        double tolerance,
1343
        Cancellable cancel,
1344
        boolean fast) throws LoadLayerException, DataException {
1345
        Point2D infop = new Point2D.Double(p.x, p.y);
1346
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1347
        return queryByPoint(pReal,
1348
            tolerance,
1349
            getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1350
    }
1351

    
1352
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1353
        double tolerance) throws LoadLayerException, DataException {
1354
        return queryByPoint(p,tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(true);
1355
    }
1356
    
1357
    public void legendCleared(LegendClearEvent event) {
1358
        // this.updateDrawVersion(); TODO
1359
        LegendChangedEvent e =
1360
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1361
        this.callLegendChanged(e);
1362
    }
1363

    
1364
    public boolean symbolChanged(SymbolLegendEvent e) {
1365
        LegendChangedEvent ev =
1366
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1367
        this.callLegendChanged(ev);
1368
        return true;
1369
    }
1370

    
1371
    public void update(Observable observable, Object notification) {
1372
        if (observable.equals(this.featureStore)) {
1373
            if (notification instanceof FeatureStoreNotification) {
1374
                FeatureStoreNotification event =
1375
                    (FeatureStoreNotification) notification;
1376
                if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING
1377
                    || event.getType() == FeatureStoreNotification.AFTER_DELETE
1378
                    || event.getType() == FeatureStoreNotification.AFTER_UNDO
1379
                    || event.getType() == FeatureStoreNotification.AFTER_REDO
1380
                    || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1381
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1382
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1383
                    || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1384
                    || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1385
                    this.updateDrawVersion();
1386

    
1387
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE){
1388
                    //If a transform has to be applied, try to reload the layer.
1389
                    try {
1390
                        reload();
1391
                    } catch (ReloadLayerException e) {
1392
                        this.setAvailable(false);
1393
                    }
1394
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1395
                    this.setAvailable(false);
1396
                } else         if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1397
                    this.setAvailable(true);
1398
                }
1399
            }
1400
        }
1401
        // Only if its an event from our own legend
1402
        else
1403
            // I comment this line because a legend doesn't implements the
1404
            // Observable interface.
1405
            // This code is necessary on edition.
1406
            // if (observable == getLegend()) {
1407
            if (notification instanceof FeatureDrawnNotification) {
1408
                Geometry geometry =
1409
                    ((FeatureDrawnNotification) notification).getDrawnGeometry();
1410
                spatialCache.insert(geometry.getEnvelope(), geometry);
1411
                // }
1412
            }
1413

    
1414
    }
1415

    
1416
    /*
1417
     * (non-Javadoc)
1418
     * 
1419
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1420
     */
1421
    public Set getMetadataChildren() {
1422
        Set ret = new TreeSet();
1423
        ret.add(this.featureStore);
1424
        return ret;
1425
    }
1426

    
1427
    /*
1428
     * (non-Javadoc)
1429
     * 
1430
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1431
     */
1432
    public Object getMetadataID() throws MetadataException {
1433
        return "Layer(" + this.getName() + "):"
1434
        + this.featureStore.getMetadataID();
1435
    }
1436

    
1437

    
1438

    
1439
    public GeometryType getTypeVectorLayer() throws DataException,
1440
    LocatorException,
1441
    GeometryTypeNotSupportedException,
1442
    GeometryTypeNotValidException {
1443
        // FIXME Esto deberia de pedirse a FType!!!!
1444
        FeatureStore fs = this.getFeatureStore();
1445
        FeatureType fType = fs.getDefaultFeatureType();
1446
        FeatureAttributeDescriptor attr =
1447
            fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1448
        GeometryType geomType =
1449
            GeometryLocator.getGeometryManager()
1450
            .getGeometryType(attr.getGeometryType(),
1451
                attr.getGeometrySubType());
1452
        return geomType;
1453
    }
1454

    
1455
    public static void registerPersistent() {
1456
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1457
        if (manager.getDefinition(FLyrDefault.class) == null) {
1458
            FLyrDefault.registerPersistent();
1459
        }
1460
        DynStruct definition =
1461
            manager.addDefinition(FLyrVect.class,
1462
                "FLyrVect",
1463
                "FLyrVect Persistence definition",
1464
                null,
1465
                null);
1466
        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1467
        "FLyrDefault");
1468

    
1469
        definition.addDynFieldObject("legend")
1470
        .setClassOfValue(IVectorLegend.class)
1471
        .setMandatory(true);
1472
        definition.addDynFieldObject("featureStore")
1473
        .setClassOfValue(FeatureStore.class)
1474
        .setMandatory(true);
1475
        definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1476
        definition.addDynFieldInt("typeShape").setMandatory(true);
1477
        definition.addDynFieldObject("labelingStrategy")
1478
        .setClassOfValue(ILabelingStrategy.class)
1479
        .setMandatory(false);
1480

    
1481
    }
1482

    
1483
    protected void doDispose() throws BaseException {
1484
        dispose(featureStore);
1485
        spatialCache.clearAll();
1486
    }
1487
}