Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / layers / vectorial / FLyrVect.java @ 37491

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

    
113
/**
114
 * Capa b?sica Vectorial.
115
 * 
116
 * @author Fernando Gonz?lez Cort?s
117
 */
118

    
119
public class FLyrVect extends FLyrDefault implements VectorLayer,
120
    LegendContentsChangedListener, Observer {
121

    
122
    final static private org.slf4j.Logger logger =
123
        LoggerFactory.getLogger(FLyrVect.class);
124
    private final GeometryManager geomManager =
125
        GeometryLocator.getGeometryManager();
126

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

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

    
139
    private boolean isLabeled;
140
    protected ILabelingStrategy strategy;
141
//        private ReprojectDefaultGeometry reprojectTransform;
142

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

    
147
    /**
148
     * Devuelve el VectorialAdapater de la capa.
149
     * 
150
     * @return VectorialAdapter.
151
     */
152
    public DataStore getDataStore() {
153
        if (!this.isAvailable()) {
154
            return null;
155
        }
156
        return featureStore;
157
    }
158
    
159
//    public void setCoordTrans(ICoordTrans ct) {
160
//            super.setCoordTrans(ct);
161
//            if (ct != null){
162
//                    if (this.reprojectTransform == null){
163
//                            this.reprojectTransform = new ReprojectDefaultGeometry(ct);
164
//                    } else {
165
//                            this.reprojectTransform.setCoordTrans(ct);
166
//                    }
167
//                    try {
168
//                            this.getFeatureStore().getTransforms().add(this.reprojectTransform);
169
//                    } catch (DataException e) {
170
//                            throw new RuntimeException(e);
171
//                    }
172
//            }
173
//    }
174

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

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

    
280
        featureStore = (FeatureStore) dataStore;
281

    
282
        MapContextManager mapContextManager =
283
            MapContextLocator.getMapContextManager();
284
        
285
        //Set the legend
286
        IVectorLegend legend =
287
            (IVectorLegend)mapContextManager.getLegend(dataStore);
288

    
289
        if (legend == null) {
290
            throw new LegendLayerException(this.getName());
291
        }
292

    
293
        this.setLegend(legend);
294

    
295
        //Set the labeling strategy
296
        ILabelingStrategy labeler = 
297
            (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
298

    
299
        if (labeler != null) {
300
            labeler.setLayer(this);
301
            this.setLabelingStrategy(labeler);
302
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
303
                                     // etiquetes?????
304
        }
305

    
306
        this.delegate(dataStore);
307

    
308
        dataStore.addObserver(this);
309

    
310
        ToolsLocator.getDisposableManager().bind(dataStore);
311
    }
312

    
313
    public Envelope getFullEnvelope() throws ReadException {
314
        Envelope rAux;
315
        try {
316
            rAux = getFeatureStore().getEnvelope();
317
        } catch (BaseException e) {
318
            throw new ReadException(getName(), e);
319
        }
320

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

    
361
    }
362

    
363
    /**
364
     * Draws using IFeatureIterator. This method will replace the old draw(...)
365
     * one.
366
     * 
367
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
368
     * @param image
369
     * @param g
370
     * @param viewPort
371
     * @param cancel
372
     * @param scale
373
     * @throws ReadDriverException
374
     */
375
    public void draw(BufferedImage image,
376
        Graphics2D g,
377
        ViewPort viewPort,
378
        Cancellable cancel,
379
        double scale) throws ReadException {
380

    
381
        if (legend == null) {
382
            return;
383
        }
384

    
385
        if (!this.isWithinScale(scale)) {
386
            return;
387
        }
388
        if (cancel.isCanceled()) {
389
            return;
390
        }
391

    
392
        if (spatialCache.isEnabled()) {
393
            spatialCache.clearAll();
394
            legend.addDrawingObserver(this);
395
        }
396

    
397
        FeatureQuery featureQuery = null;
398
        try {
399
            FeatureAttributeDescriptor featureAttributeDescriptor =
400
                getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
401

    
402
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)){
403
                featureQuery = getFeatureStore().createFeatureQuery();
404
                IntersectsTimeEvaluator intersectsTimeEvaluator =
405
                    new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
406
                featureQuery.addFilter(intersectsTimeEvaluator);
407
            }
408
        } catch (DataException e1) {
409
            logger.error("Impossible to get the temporal filter", e1);
410
        }
411

    
412
        try {
413
            legend.draw(image,
414
                g,
415
                viewPort,
416
                cancel,
417
                scale,
418
                null,
419
                getCoordTrans(),
420
                getFeatureStore(),
421
                null);
422

    
423
        } catch (LegendException e) {
424
            this.setVisible(false);
425
            this.setActive(false);
426
            throw new ReadException(getName(), e);
427
        } finally {
428
            if (spatialCache.isEnabled()) {
429
                legend.deleteDrawingObserver(this);
430
            }
431
        }
432
    }
433

    
434
    public void print(Graphics2D g,
435
        ViewPort viewPort,
436
        Cancellable cancel,
437
        double scale,
438
        PrintAttributes properties) throws ReadException {
439
        if (!this.isWithinScale(scale)) {
440
            return;
441
        }
442
        if (cancel.isCanceled()) {
443
            return;
444
        }
445

    
446
        try {
447
            legend.print(g,
448
                viewPort,
449
                cancel,
450
                scale,
451
                null,
452
                getCoordTrans(),
453
                getFeatureStore(),
454
                null,
455
                properties);
456

    
457
        } catch (LegendException e) {
458
            this.setVisible(false);
459
            this.setActive(false);
460
            throw new ReadException(getName(), e);
461
        }
462
    }
463

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

    
546
    // public void createSpatialIndex() {
547
    // createSpatialIndex(null);
548
    // }
549

    
550
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
551
        if (this.legend == legend) {
552
            return;
553
        }
554
        if (this.legend != null && this.legend.equals(legend)) {
555
            return;
556
        }
557
        IVectorLegend oldLegend = this.legend;
558
        this.legend = legend;
559
        if (oldLegend != null) {
560
            oldLegend.removeLegendListener(this);
561
            oldLegend.deleteDrawingObserver(this);
562
        }
563
        if (legend != null) {
564
            this.legend.addDrawingObserver(this);
565
            this.legend.addLegendListener(this);
566
        }
567
        LegendChangedEvent e =
568
            LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
569
        e.setLayer(this);
570
        callLegendChanged(e);
571
    }
572

    
573
    /**
574
     * Devuelve la Leyenda de la capa.
575
     * 
576
     * @return Leyenda.
577
     */
578
    public ILegend getLegend() {
579
        return legend;
580
    }
581

    
582
    public int getShapeType() throws ReadException {
583
            if (typeShape == -1) {
584
                    FeatureType featureType = null;
585
                    try {
586
                            if( getDataStore()!=null ){
587
                                    featureType =
588
                                            (((FeatureStore) getDataStore()).getDefaultFeatureType());
589
                            }
590
                    } catch (DataException e) {
591
                            throw new ReadException(getName(), e);
592
                    }
593
                    if( featureType!=null ){
594
                            int indexGeom = featureType.getDefaultGeometryAttributeIndex();
595
                            typeShape =
596
                                    featureType.getAttributeDescriptor(indexGeom).getGeometryType();
597
                    }
598
            }
599
            return typeShape;
600
    }
601

    
602
    /**
603
     * Returns the layer's geometry type
604
     * 
605
     * @return the geometry type
606
     * 
607
     * @throws ReadException
608
     *             if there is an error getting the geometry type
609
     */
610
    public GeometryType getGeometryType() throws ReadException {
611
        FeatureType featureType = null;
612
        try {
613
            if (getDataStore() != null) {
614
                featureType =
615
                    (((FeatureStore) getDataStore()).getDefaultFeatureType());
616
            }
617
        } catch (DataException e) {
618
            throw new ReadException(getName(), e);
619
        }
620
        return featureType == null ? null : featureType
621
            .getDefaultGeometryAttribute().getGeomType();
622
    }
623

    
624
    public void saveToState(PersistentState state) throws PersistenceException {
625

    
626
        if (!this.isAvailable()) {
627
            return;
628
        }
629

    
630
        super.saveToState(state);
631

    
632
        if (getLegend() != null) {
633
            state.set("legend", getLegend());
634
        }
635

    
636
        FeatureStore fst = null;
637
        fst = getFeatureStore();
638

    
639
        if (fst != null) {
640
            state.set("featureStore", fst);
641
        }
642

    
643
        state.set("isLabeled", isLabeled);
644

    
645
        if (strategy != null) {
646
            state.set("labelingStrategy", strategy);
647
        }
648

    
649
        if (getLinkProperties() != null) {
650
            state.set("linkProperties", getLinkProperties());
651
        }
652

    
653
        // state.set("bHasJoin", bHasJoin);
654
        state.set("typeShape", typeShape);
655
    }
656

    
657
    // public XMLEntity getXMLEntity() throws XMLException {
658
    //
659
    // if (!this.isAvailable() && this.orgXMLEntity != null) {
660
    // return this.orgXMLEntity;
661
    // }
662
    // XMLEntity xml = super.getXMLEntity();
663
    // if (getLegend()!=null){
664
    // XMLEntity xmlLegend=getLegend().getXMLEntity();
665
    // xmlLegend.putProperty("tagName","legend");
666
    // xml.addChild(xmlLegend);
667
    // }
668
    // try {
669
    // PersistenceManager manager = ToolsLocator.getPersistenceManager();
670
    // PersistentState stateFeatureStore=manager.getState(getFeatureStore());
671
    // stateFeatureStore.set("tagName","featureStore");
672
    // xml.addChild(((XMLEntityState)stateFeatureStore).getXMLEntity());
673
    // } catch (ReadException e) {
674
    // throw new XMLLayerException(getName(),e);
675
    // } catch (PersistenceException e) {
676
    // throw new XMLLayerException(getName(),e);
677
    // }
678
    // // properties from ILabelable
679
    // xml.putProperty("isLabeled", isLabeled);
680
    // if (strategy != null) {
681
    // XMLEntity strategyXML = strategy.getXMLEntity();
682
    // strategyXML.putProperty("tagName", "labelingStrategy");
683
    // xml.addChild(strategy.getXMLEntity());
684
    // }
685
    // xml.addChild(getLinkProperties().getXMLEntity());
686
    // return xml;
687
    // }
688

    
689
    public void loadFromState(PersistentState state) throws PersistenceException {
690

    
691
        super.loadFromState(state);
692
        DataStore store = null;
693
        try {
694
                store = (DataStore) state.get("featureStore");
695
        } catch (PersistenceRuntimeException e) {
696
                        this.setAvailable(false);
697
                        return;
698
                }
699
        try {
700
            this.setDataStore(store);
701
        } catch (LoadLayerException e) {
702
            throw new PersistenceException("While loading FLyrVect from state.",
703
                e);
704
        }
705

    
706
        IVectorLegend lgnd = (IVectorLegend) state.get("legend");
707
        try {
708
            this.setLegend(lgnd);
709
        } catch (LegendLayerException e) {
710
            throw new PersistenceException("While loading FLyrVect from state.",
711
                e);
712
        }
713

    
714
        Boolean isLbl = new Boolean(false);
715
        ILabelingStrategy lblst = null;
716

    
717
        try {
718
            isLbl = (Boolean) state.get("isLabeled");
719
            if (isLbl.booleanValue()) {
720
                lblst = (ILabelingStrategy) state.get("labelingStrategy");
721
            }
722
        } catch (Exception ex) {
723
            throw new PersistenceException("While loading FLyrVect from state.",
724
                ex);
725
        }
726

    
727
        /*
728
         * String _labelFieldName = null;
729
         * String _labelfield = null;
730
         */
731

    
732
        if (isLbl.booleanValue()) {
733
            this.setIsLabeled(true);
734
            this.setLabelingStrategy(lblst);
735
        } else {
736
            this.setIsLabeled(false);
737
            this.setLabelingStrategy(null);
738
        }
739

    
740
        // try {
741
        // linkProperties = (FLyrVectLinkProperties)
742
        // state.get("linkProperties");
743
        // } catch (PersistenceException pex) {
744
        // // not mandatory
745
        // linkProperties = null;
746
        // }
747

    
748
        // bHasJoin = state.getBoolean("bHasJoin");
749
        typeShape = state.getInt("typeShape");
750

    
751
        // try { _labelFieldName = state.getString("labelFieldName"); } catch
752
        // (PersistenceException ex) {
753
        // _labelFieldName = null;
754
        // }
755
        // try { _labelfield = state.getString("labelfield"); } catch
756
        // (PersistenceException ex) {
757
        // _labelfield = null;
758
        // }
759

    
760
        // ILabelingStrategy not implemented
761
        // if (_labelFieldName != null) {
762
        //
763
        // AttrInTableLabelingStrategy labeling = new
764
        // AttrInTableLabelingStrategy();
765
        // try {
766
        // labeling.setLayer(this);
767
        // } catch (ReadException e) {
768
        // logger.error("While setting layer to AttrInTableLabelingStrategy: " +
769
        // e.getMessage());
770
        // }
771
        // labeling.setUsesFixedSize(true);
772
        // labeling.setFixedSize(10);
773
        // labeling.setTextField(_labelFieldName);
774
        // labeling.setHeightField(state.getString("labelHeightFieldName"));
775
        // labeling.setRotationField(state.getString("labelRotationFieldName"));
776
        // setLabelingStrategy(labeling);
777
        // setIsLabeled(true);
778
        //
779
        // } else {
780
        // if (_labelfield != null) {
781
        //
782
        // AttrInTableLabelingStrategy labeling = new
783
        // AttrInTableLabelingStrategy();
784
        // try {
785
        // labeling.setLayer(this);
786
        // } catch (ReadException e) {
787
        // logger.error("While setting layer to AttrInTableLabelingStrategy: " +
788
        // e.getMessage());
789
        // }
790
        // labeling.setUsesFixedSize(true);
791
        // labeling.setFixedSize(10);
792
        // labeling.setTextField(_labelfield);
793
        // labeling.setHeightField(state.getString("labelFieldHeight"));
794
        // labeling.setRotationField(state.getString("labelFieldRotation"));
795
        // setLabelingStrategy(labeling);
796
        // setIsLabeled(true);
797
        // }
798
        // }
799

    
800
    }
801

    
802
    // public void setXMLEntity(XMLEntity xml) throws XMLException {
803
    // try {
804
    // super.setXMLEntity(xml);
805
    // XMLEntity legendXML = xml.firstChild("tagName","legend");
806
    // IVectorLegend leg = LegendFactory.createFromXML(legendXML);
807
    //
808
    // // PersistentState persistentState=new XMLEntityState(new
809
    // XMLEntityManager());
810
    // XMLEntity xmlStore=xml.firstChild("tagName","featureStore");
811
    // XMLEntityManager xmlManger = new XMLEntityManager();
812
    // PersistentState state = xmlManger.createState(xmlStore);
813
    // DataStore store = (DataStore)
814
    // ToolsLocator.getPersistenceManager().create(state);
815
    // // persistentState.createState(xmlStore);
816
    //
817
    // // DataManager dm=DALLocator.getDataManager();
818
    //
819
    // this.setDataStore(store);
820
    // /* end patch */
821
    // try {
822
    // setLegend(leg);
823
    // } catch (LegendLayerException e) {
824
    // throw new XMLLegendException(e);
825
    // }
826
    // // set properties for ILabelable
827
    //
828
    // if (xml.contains("isLabeled")
829
    // && xml.getBooleanProperty(("isLabeled"))) {
830
    // XMLEntity labelingXML = xml.firstChild("tagName", "labelingStrategy");
831
    // if (labelingXML != null){
832
    //
833
    // isLabeled = true;
834
    // try {
835
    // this.strategy = LabelingFactory.createStrategyFromXML(labelingXML, this);
836
    // } catch (NotExistInXMLEntity neXMLEX) {
837
    // // no strategy was set, just continue;
838
    // logger.warn("Reached what should be unreachable code");
839
    // }
840
    // } else {
841
    // isLabeled = false;
842
    // }
843
    // } else if (legendXML.contains("labelFieldName")||
844
    // legendXML.contains("labelfield")) {
845
    // /* (jaume) begin patch;
846
    // * for backward compatibility purposes. Since gvSIG v1.1 labeling is
847
    // * no longer managed by the Legend but by the ILabelingStrategy. The
848
    // * following allows restoring older projects' labelings.
849
    // */
850
    // String labelTextField = null;
851
    // if (legendXML.contains("labelFieldName")){
852
    // labelTextField = legendXML.getStringProperty("labelFieldName");
853
    // if (labelTextField != null) {
854
    // AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
855
    // labeling.setLayer(this);
856
    // labeling.setUsesFixedSize(true);
857
    // labeling.setFixedSize(10);
858
    // labeling.setTextField(labelTextField);
859
    // labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
860
    // labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
861
    // this.setLabelingStrategy(labeling);
862
    // this.setIsLabeled(true);
863
    // }
864
    // }else{
865
    // labelTextField = legendXML.getStringProperty("labelfield");
866
    // if (labelTextField != null) {
867
    // AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
868
    // labeling.setLayer(this);
869
    // labeling.setUsesFixedSize(true);
870
    // labeling.setFixedSize(10);
871
    // labeling.setTextField(labelTextField);
872
    // labeling.setHeightField(legendXML.getStringProperty("labelFieldHeight"));
873
    // labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
874
    // this.setLabelingStrategy(labeling);
875
    // this.setIsLabeled(true);
876
    // }
877
    // }
878
    // }else{
879
    // isLabeled = false;
880
    // }
881
    // XMLEntity xmlLinkProperties=xml.firstChild("typeChild","linkProperties");
882
    // if (xmlLinkProperties != null){
883
    // getLinkProperties().setXMLEntity(xmlLinkProperties);
884
    // }
885
    // } catch (Exception e) {
886
    // e.printStackTrace();
887
    // this.setAvailable(false);
888
    // this.orgXMLEntity = xml;
889
    //
890
    // }
891
    // //
892
    //
893
    // }
894

    
895
    /**
896
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
897
     * identifiquen la capa.
898
     * 
899
     * @return DOCUMENT ME!
900
     */
901
    public String toString() {
902
        /*
903
         * Se usa internamente para que la parte de datos identifique de forma
904
         * un?voca las tablas
905
         */
906
        String ret = super.toString();
907

    
908
        return "layer" + ret.substring(ret.indexOf('@') + 1);
909
    }
910

    
911
    // public boolean isJoined() {
912
    // return bHasJoin;
913
    // }
914

    
915
    /**
916
     * Returns if a layer is spatially indexed
917
     * 
918
     * @return if this layer has the ability to proces spatial queries without
919
     *         secuential scans.
920
     * @throws StopEditionLayerException 
921
     */
922
    // public boolean isSpatiallyIndexed() {
923
    // ReadableVectorial source = getSource();
924
    // if (source instanceof ISpatialDB)
925
    // return true;
926
    //
927
    // //FIXME azabala
928
    // /*
929
    // * Esto es muy dudoso, y puede cambiar.
930
    // * Estoy diciendo que las que no son fichero o no son
931
    // * BoundedShapes estan indexadas. Esto es mentira, pero
932
    // * as? quien pregunte no querr? generar el indice.
933
    // * Esta por ver si interesa generar el indice para capas
934
    // * HSQLDB, WFS, etc.
935
    // */
936
    // if(!(source instanceof VectorialFileAdapter)){
937
    // return true;
938
    // }
939
    // if (!(source.getDriver() instanceof BoundedShapes)) {
940
    // return true;
941
    // }
942
    //
943
    // if (getISpatialIndex() != null)
944
    // return true;
945
    // return false;
946
    // }
947
    //
948
    // public void setIsJoined(boolean hasJoin) {
949
    // bHasJoin = hasJoin;
950
    // }
951

    
952
    // /**
953
    // * @return Returns the spatialIndex.
954
    // */
955
    // public ISpatialIndex getISpatialIndex() {
956
    // return spatialIndex;
957
    // }
958
    // /**
959
    // * Sets the spatial index. This could be useful if, for some
960
    // * reasons, you want to work with a distinct spatial index
961
    // * (for example, a spatial index which could makes nearest
962
    // * neighbour querys)
963
    // * @param spatialIndex
964
    // */
965
    // public void setISpatialIndex(ISpatialIndex spatialIndex){
966
    // this.spatialIndex = spatialIndex;
967
    // }
968

    
969
    public void setEditing(boolean b) throws StartEditionLayerException {
970
        super.setEditing(b);
971
        FeatureStore fs = getFeatureStore();
972
        if (b) {
973
            try {
974
                fs.edit();
975
            } catch (ReadException e) {
976
                throw new StartEditionLayerException(getName(), e);
977
            } catch (DataException e) {
978
                throw new StartEditionLayerException(getName(), e);
979
            }
980
        }
981
        setSpatialCacheEnabled(b);
982
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
983
    }
984

    
985
    /**
986
     * @deprecated Use {@link #getSpatialCache()}
987
     */
988
    public void clearSpatialCache() {
989
        spatialCache.clearAll();
990
    }
991

    
992
    /**
993
     * @deprecated Use {@link #getSpatialCache()}
994
     */
995
    public boolean isSpatialCacheEnabled() {
996
        return spatialCache.isEnabled();
997
    }
998

    
999
    /**
1000
     * @deprecated Use {@link #getSpatialCache()}
1001
     */
1002
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1003
        spatialCache.setEnabled(spatialCacheEnabled);
1004
    }
1005

    
1006
    public SpatialCache getSpatialCache() {
1007
        return spatialCache;
1008
    }
1009

    
1010
    /**
1011
     * Siempre es un numero mayor de 1000
1012
     * 
1013
     * @param maxFeatures
1014
     */
1015
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1016
        if (maxFeatures > spatialCache.getMaxFeatures()) {
1017
            spatialCache.setMaxFeatures(maxFeatures);
1018
        }
1019

    
1020
    }
1021

    
1022
    /**
1023
     * This method returns a boolean that is used by the FPopMenu
1024
     * to make visible the properties menu or not. It is visible by
1025
     * default, and if a later don't have to show this menu only
1026
     * has to override this method.
1027
     * 
1028
     * @return
1029
     *         If the properties menu is visible (or not)
1030
     */
1031
    public boolean isPropertiesMenuVisible() {
1032
        return true;
1033
    }
1034

    
1035
    public void reload() throws ReloadLayerException {
1036
        super.reload();
1037
        try {
1038
            getFeatureStore().refresh();
1039
        } catch (Exception e) {
1040
            throw new ReloadLayerException(getName(), e);
1041
        }
1042
    }
1043

    
1044
    protected void setLoadSelection(Object xml) {
1045
        // this.loadSelection = xml;
1046
    }
1047

    
1048
    protected void setLoadLegend(IVectorLegend legend) {
1049
        this.loadLegend = legend;
1050
    }
1051

    
1052
    protected void putLoadSelection() {
1053
        // if (this.loadSelection == null) return;
1054
        // try {
1055
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1056
        // } catch (ReadDriverException e) {
1057
        // throw new XMLException(e);
1058
        // }
1059
        // this.loadSelection = null;
1060

    
1061
    }
1062

    
1063
    protected void putLoadLegend() throws LegendLayerException {
1064
        if (this.loadLegend == null) {
1065
            return;
1066
        }
1067
        this.setLegend(this.loadLegend);
1068
        this.loadLegend = null;
1069
    }
1070

    
1071
    protected void cleanLoadOptions() {
1072
        this.loadLegend = null;
1073
    }
1074

    
1075
    public boolean isWritable() {
1076
        return getFeatureStore().allowWrite();
1077
    }
1078

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

    
1090
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
1091

    
1092
        clonedLayer.setIsLabeled(isLabeled());
1093
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
1094
        if (labelingStrategy != null) {
1095
            clonedLayer.setLabelingStrategy(labelingStrategy);
1096
        }
1097

    
1098
        return clonedLayer;
1099
    }
1100

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

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

    
1122
            Envelope geomBounds = geom.getEnvelope();
1123

    
1124
            // ICoordTrans ct = getCoordTrans();
1125

    
1126
            // Se supone que la geometria ya esta reproyectada
1127
            // if (ct!=null) {
1128
            // // geomBounds = ct.getInverted().convert(geomBounds);
1129
            // geomBounds = geomBounds.convert(ct);
1130
            // }
1131

    
1132
            double dist1Pixel = viewPort.getDist1pixel();
1133

    
1134
            onePoint =
1135
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
1136

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

    
1153
            }
1154

    
1155
        }
1156
        return onePoint;
1157
    }
1158

    
1159
    /*
1160
     * jaume. Stuff from ILabeled.
1161
     */
1162

    
1163
    public boolean isLabeled() {
1164
        return isLabeled;
1165
    }
1166

    
1167
    public void setIsLabeled(boolean isLabeled) {
1168
        this.isLabeled = isLabeled;
1169
    }
1170

    
1171
    public ILabelingStrategy getLabelingStrategy() {
1172
        return strategy;
1173
    }
1174

    
1175
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1176
        this.strategy = strategy;
1177
        if (strategy == null) {
1178
            return;
1179
        }
1180
        strategy.setLayer(this);
1181
    }
1182

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

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

    
1204
    // M?todos para el uso de HyperLinks en capas FLyerVect
1205

    
1206
    /**
1207
     * Return true, because a Vectorial Layer supports HyperLink
1208
     */
1209
    public boolean allowLinks() {
1210
        return true;
1211
    }
1212

    
1213
    /**
1214
     * Returns an instance of AbstractLinkProperties that contains the
1215
     * information
1216
     * of the HyperLink
1217
     * 
1218
     * @return Abstra
1219
     */
1220
    // public AbstractLinkProperties getLinkProperties()
1221
    // {
1222
    // return linkProperties;
1223
    // }
1224

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

    
1250
    public void load() throws LoadLayerException {
1251
        super.load();
1252
    }
1253

    
1254
    public FeatureStore getFeatureStore() {
1255
        return (FeatureStore) getDataStore();
1256
    }
1257

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

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

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

    
1310
    }
1311

    
1312
    /**
1313
     * It return the {@link FeatureSet} that intersects with the envelope.
1314
     * @param envelope
1315
     *          envelope that defines the area for the query.
1316
     * @param featureType
1317
     *          only the features with this feature type are used in
1318
     *          the query.    
1319
     * @return
1320
     *          the set of features that intersect with the envelope.
1321
     * @throws DataException
1322
     */
1323
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1324
        return queryByEnvelope(envelope, featureType, null);
1325
    }
1326

    
1327
    /**
1328
     * It return the {@link FeatureSet} that intersects with the envelope.
1329
     * @param envelope
1330
     *          envelope that defines the area for the query.
1331
     * @param featureType
1332
     *          only the features with this feature type are used in
1333
     *          the query.
1334
     * @param names
1335
     *          the feature attributes that have to be checked.
1336
     * @return
1337
     *          the set of features that intersect with the envelope.
1338
     * @throws DataException
1339
     */
1340
    public FeatureSet queryByEnvelope(Envelope envelope,
1341
        FeatureType featureType,
1342
        String[] names) throws DataException {
1343
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
1344
        if (names == null) {
1345
            featureQuery.setFeatureType(featureType);
1346
        } else {
1347
            featureQuery.setAttributeNames(names);
1348
            featureQuery.setFeatureTypeId(featureType.getId());
1349
        }
1350
        String geomName =
1351
            featureStore.getDefaultFeatureType()
1352
                .getDefaultGeometryAttributeName();
1353
        IntersectsGeometryEvaluator iee =
1354
            new IntersectsGeometryEvaluator(envelope.getGeometry(),
1355
                getMapContext().getViewPort().getProjection(),
1356
                featureStore.getDefaultFeatureType(),
1357
                geomName);
1358
        featureQuery.setFilter(iee);
1359
        return getFeatureStore().getFeatureSet(featureQuery);
1360

    
1361
    }
1362

    
1363
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1364
        DataException {
1365

    
1366
        return getInfo(p, tolerance, cancel, true);
1367
    }
1368

    
1369
    public DynObjectSet getInfo(Point p,
1370
        double tolerance,
1371
        Cancellable cancel,
1372
        boolean fast) throws LoadLayerException, DataException {
1373
        Point2D infop = new Point2D.Double(p.x, p.y);
1374
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1375
        return queryByPoint(pReal,
1376
            tolerance,
1377
            getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1378
    }
1379

    
1380
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1381
        double tolerance) throws LoadLayerException, DataException {
1382
        return queryByPoint(p,tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
1383
    }
1384
    
1385
    public void legendCleared(LegendClearEvent event) {
1386
        // this.updateDrawVersion(); TODO
1387
        LegendChangedEvent e =
1388
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1389
        this.callLegendChanged(e);
1390
    }
1391

    
1392
    public boolean symbolChanged(SymbolLegendEvent e) {
1393
        LegendChangedEvent ev =
1394
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1395
        this.callLegendChanged(ev);
1396
        return true;
1397
    }
1398

    
1399
    public void update(Observable observable, Object notification) {
1400
        if (observable.equals(this.featureStore)) {
1401
            if (notification instanceof FeatureStoreNotification) {
1402
                FeatureStoreNotification event =
1403
                    (FeatureStoreNotification) notification;
1404
                if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING
1405
                    || event.getType() == FeatureStoreNotification.AFTER_DELETE
1406
                    || event.getType() == FeatureStoreNotification.AFTER_UNDO
1407
                    || event.getType() == FeatureStoreNotification.AFTER_REDO
1408
                    || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1409
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1410
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1411
                    || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1412
                    || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1413
                    this.updateDrawVersion();
1414

    
1415
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE){
1416
                    //If a transform has to be applied, try to reload the layer.
1417
                    try {
1418
                        reload();
1419
                    } catch (ReloadLayerException e) {
1420
                        this.setAvailable(false);
1421
                    }
1422
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1423
                    this.setAvailable(false);
1424
                } else         if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1425
                    this.setAvailable(true);
1426
                }
1427
            }
1428
        }
1429
        // Only if its an event from our own legend
1430
        else
1431
            // I comment this line because a legend doesn't implements the
1432
            // Observable interface.
1433
            // This code is necessary on edition.
1434
            // if (observable == getLegend()) {
1435
            if (notification instanceof FeatureDrawnNotification) {
1436
                Geometry geometry =
1437
                    ((FeatureDrawnNotification) notification).getDrawnGeometry();
1438
                spatialCache.insert(geometry.getEnvelope(), geometry);
1439
                // }
1440
            }
1441

    
1442
    }
1443

    
1444
    /*
1445
     * (non-Javadoc)
1446
     * 
1447
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1448
     */
1449
    public Set getMetadataChildren() {
1450
        Set ret = new TreeSet();
1451
        ret.add(this.featureStore);
1452
        return ret;
1453
    }
1454

    
1455
    /*
1456
     * (non-Javadoc)
1457
     * 
1458
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1459
     */
1460
    public Object getMetadataID() throws MetadataException {
1461
        return "Layer(" + this.getName() + "):"
1462
            + this.featureStore.getMetadataID();
1463
    }
1464

    
1465
    
1466

    
1467
    public GeometryType getTypeVectorLayer() throws DataException,
1468
        LocatorException,
1469
        GeometryTypeNotSupportedException,
1470
        GeometryTypeNotValidException {
1471
        // FIXME Esto deberia de pedirse a FType!!!!
1472
        FeatureStore fs = this.getFeatureStore();
1473
        FeatureType fType = fs.getDefaultFeatureType();
1474
        FeatureAttributeDescriptor attr =
1475
            fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1476
        GeometryType geomType =
1477
            GeometryLocator.getGeometryManager()
1478
                .getGeometryType(attr.getGeometryType(),
1479
                    attr.getGeometrySubType());
1480
        return geomType;
1481
    }
1482

    
1483
    public static void registerPersistent() {
1484
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1485
        if (manager.getDefinition(FLyrDefault.class) == null) {
1486
            FLyrDefault.registerPersistent();
1487
        }
1488
        DynStruct definition =
1489
            manager.addDefinition(FLyrVect.class,
1490
                "FLyrVect",
1491
                "FLyrVect Persistence definition",
1492
                null,
1493
                null);
1494
        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1495
            "FLyrDefault");
1496

    
1497
        definition.addDynFieldObject("legend")
1498
            .setClassOfValue(IVectorLegend.class)
1499
            .setMandatory(true);
1500
        definition.addDynFieldObject("featureStore")
1501
            .setClassOfValue(FeatureStore.class)
1502
            .setMandatory(true);
1503
        definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1504
        definition.addDynFieldInt("typeShape").setMandatory(true);
1505
        definition.addDynFieldObject("labelingStrategy")
1506
            .setClassOfValue(ILabelingStrategy.class)
1507
            .setMandatory(false);
1508

    
1509
    }
1510

    
1511
    protected void doDispose() throws BaseException {
1512
        dispose(featureStore);
1513
        spatialCache.clearAll();
1514
    }
1515
}