Statistics
| Revision:

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

History | View | Annotate | Download (51.8 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.persistence.exception.PersistenceRuntimeException;
115
import org.gvsig.tools.task.Cancellable;
116

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

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

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

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

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

    
143
    private boolean isLabeled;
144
    protected ILabelingStrategy strategy;
145
//        private ReprojectDefaultGeometry reprojectTransform;
146

    
147
    public FLyrVect() {
148
        super();
149
    }
150

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

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

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

    
284
        featureStore = (FeatureStore) dataStore;
285

    
286
        IVectorLegend legend =
287
            (IVectorLegend) MapContextLocator.getMapContextManager().getLegend(dataStore);
288

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

    
293
        this.setLegend(legend);
294

    
295
        ILabelingStrategy labeler = null;
296
        try {
297
            labeler =
298
                (ILabelingStrategy) dataStore.invokeDynMethod("getLabeling",
299
                    null);
300
        } catch (DynMethodNotSupportedException e1) {
301
            labeler = null;
302
        } catch (DynMethodException e1) {
303
            logger.error("Can't load the specific lebeling strategy provided for the layer {}.",
304
                this.getName(),
305
                e1);
306
        }
307

    
308
        if (labeler != null) {
309
            labeler.setLayer(this);
310
            this.setLabelingStrategy(labeler);
311
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
312
            // etiquetes?????
313
        }
314

    
315
        this.delegate(dataStore);
316

    
317
        dataStore.addObserver(this);
318

    
319
        ToolsLocator.getDisposableManager().bind(dataStore);
320
    }
321

    
322
    public Envelope getFullEnvelope() throws ReadException {
323
        Envelope rAux;
324
        try {
325
            rAux = getFeatureStore().getEnvelope();
326
        } catch (BaseException e) {
327
            throw new ReadException(getName(), e);
328
        }
329

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

    
370
    }
371

    
372
    /**
373
     * Draws using IFeatureIterator. This method will replace the old draw(...)
374
     * one.
375
     * 
376
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
377
     * @param image
378
     * @param g
379
     * @param viewPort
380
     * @param cancel
381
     * @param scale
382
     * @throws ReadDriverException
383
     */
384
    public void draw(BufferedImage image,
385
        Graphics2D g,
386
        ViewPort viewPort,
387
        Cancellable cancel,
388
        double scale) throws ReadException {
389

    
390
        if (legend == null) {
391
            return;
392
        }
393

    
394
        if (!this.isWithinScale(scale)) {
395
            return;
396
        }
397
        if (cancel.isCanceled()) {
398
            return;
399
        }
400

    
401
        if (spatialCache.isEnabled()) {
402
            spatialCache.clearAll();
403
            legend.addDrawingObserver(this);
404
        }
405

    
406
        FeatureQuery featureQuery = null;
407
        try {
408
            FeatureAttributeDescriptor featureAttributeDescriptor =
409
                getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
410

    
411
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)){
412
                featureQuery = getFeatureStore().createFeatureQuery();
413
                IntersectsTimeEvaluator intersectsTimeEvaluator =
414
                    new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
415
                featureQuery.addFilter(intersectsTimeEvaluator);
416
            }
417
        } catch (DataException e1) {
418
            logger.error("Impossible to get the temporal filter", e1);
419
        }
420

    
421
        try {
422
            legend.draw(image,
423
                g,
424
                viewPort,
425
                cancel,
426
                scale,
427
                null,
428
                getCoordTrans(),
429
                getFeatureStore(),
430
                featureQuery);
431

    
432
        } catch (LegendException e) {
433
            this.setVisible(false);
434
            this.setActive(false);
435
            throw new ReadException(getName(), e);
436
        } finally {
437
            if (spatialCache.isEnabled()) {
438
                legend.deleteDrawingObserver(this);
439
            }
440
        }
441
    }
442

    
443
    public void print(Graphics2D g,
444
        ViewPort viewPort,
445
        Cancellable cancel,
446
        double scale,
447
        PrintAttributes properties) throws ReadException {
448
        if (!this.isWithinScale(scale)) {
449
            return;
450
        }
451
        if (cancel.isCanceled()) {
452
            return;
453
        }
454

    
455
        try {
456
            legend.print(g,
457
                viewPort,
458
                cancel,
459
                scale,
460
                null,
461
                getCoordTrans(),
462
                getFeatureStore(),
463
                null,
464
                properties);
465

    
466
        } catch (LegendException e) {
467
            this.setVisible(false);
468
            this.setActive(false);
469
            throw new ReadException(getName(), e);
470
        }
471
    }
472

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

    
555
    // public void createSpatialIndex() {
556
    // createSpatialIndex(null);
557
    // }
558

    
559
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
560
        if (this.legend == legend) {
561
            return;
562
        }
563
        if (this.legend != null && this.legend.equals(legend)) {
564
            return;
565
        }
566
        IVectorLegend oldLegend = this.legend;
567
        this.legend = legend;
568
        if (oldLegend != null) {
569
            oldLegend.removeLegendListener(this);
570
            oldLegend.deleteDrawingObserver(this);
571
        }
572
        if (legend != null) {
573
            this.legend.addDrawingObserver(this);
574
            this.legend.addLegendListener(this);
575
        }
576
        LegendChangedEvent e =
577
            LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
578
        e.setLayer(this);
579
        callLegendChanged(e);
580
    }
581

    
582
    /**
583
     * Devuelve la Leyenda de la capa.
584
     * 
585
     * @return Leyenda.
586
     */
587
    public ILegend getLegend() {
588
        return legend;
589
    }
590

    
591
    /**
592
     * Devuelve el tipo de shape que contiene la capa.
593
     * 
594
     * @return tipo de shape.
595
     * 
596
     * @throws ReadException
597
     */
598
    public int getShapeType() throws ReadException {
599
            if (typeShape == -1) {
600
                    FeatureType featureType = null;
601
                    try {
602
                            if( getDataStore()!=null ){
603
                                    featureType =
604
                                            (((FeatureStore) getDataStore()).getDefaultFeatureType());
605
                            }
606
                    } catch (DataException e) {
607
                            throw new ReadException(getName(), e);
608
                    }
609
                    if( featureType!=null ){
610
                            int indexGeom = featureType.getDefaultGeometryAttributeIndex();
611
                            typeShape =
612
                                    featureType.getAttributeDescriptor(indexGeom).getGeometryType();
613
                    }
614
            }
615
            return typeShape;
616
    }
617

    
618
    public void saveToState(PersistentState state) throws PersistenceException {
619

    
620
        if (!this.isAvailable()) {
621
            return;
622
        }
623

    
624
        super.saveToState(state);
625

    
626
        if (getLegend() != null) {
627
            state.set("legend", getLegend());
628
        }
629

    
630
        FeatureStore fst = null;
631
        fst = getFeatureStore();
632

    
633
        if (fst != null) {
634
            state.set("featureStore", fst);
635
        }
636

    
637
        state.set("isLabeled", isLabeled);
638

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

    
643
        if (getLinkProperties() != null) {
644
            state.set("linkProperties", getLinkProperties());
645
        }
646

    
647
        // state.set("bHasJoin", bHasJoin);
648
        state.set("typeShape", typeShape);
649
    }
650

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

    
683
    public void loadFromState(PersistentState state) throws PersistenceException {
684

    
685
        super.loadFromState(state);
686
        DataStore store = null;
687
        try {
688
                store = (DataStore) state.get("featureStore");
689
        } catch (PersistenceRuntimeException e) {
690
                        this.setAvailable(false);
691
                        return;
692
                }
693
        try {
694
            this.setDataStore(store);
695
        } catch (LoadLayerException e) {
696
            throw new PersistenceException("While loading FLyrVect from state.",
697
                e);
698
        }
699

    
700
        IVectorLegend lgnd = (IVectorLegend) state.get("legend");
701
        try {
702
            this.setLegend(lgnd);
703
        } catch (LegendLayerException e) {
704
            throw new PersistenceException("While loading FLyrVect from state.",
705
                e);
706
        }
707

    
708
        Boolean isLbl = new Boolean(false);
709
        ILabelingStrategy lblst = null;
710

    
711
        try {
712
            isLbl = (Boolean) state.get("isLabeled");
713
            if (isLbl.booleanValue()) {
714
                lblst = (ILabelingStrategy) state.get("labelingStrategy");
715
            }
716
        } catch (Exception ex) {
717
            throw new PersistenceException("While loading FLyrVect from state.",
718
                ex);
719
        }
720

    
721
        /*
722
         * String _labelFieldName = null;
723
         * String _labelfield = null;
724
         */
725

    
726
        if (isLbl.booleanValue()) {
727
            this.setIsLabeled(true);
728
            this.setLabelingStrategy(lblst);
729
        } else {
730
            this.setIsLabeled(false);
731
            this.setLabelingStrategy(null);
732
        }
733

    
734
        // try {
735
        // linkProperties = (FLyrVectLinkProperties)
736
        // state.get("linkProperties");
737
        // } catch (PersistenceException pex) {
738
        // // not mandatory
739
        // linkProperties = null;
740
        // }
741

    
742
        // bHasJoin = state.getBoolean("bHasJoin");
743
        typeShape = state.getInt("typeShape");
744

    
745
        // try { _labelFieldName = state.getString("labelFieldName"); } catch
746
        // (PersistenceException ex) {
747
        // _labelFieldName = null;
748
        // }
749
        // try { _labelfield = state.getString("labelfield"); } catch
750
        // (PersistenceException ex) {
751
        // _labelfield = null;
752
        // }
753

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

    
794
    }
795

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

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

    
902
        return "layer" + ret.substring(ret.indexOf('@') + 1);
903
    }
904

    
905
    // public boolean isJoined() {
906
    // return bHasJoin;
907
    // }
908

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

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

    
963
    public void setEditing(boolean b) throws StartEditionLayerException {
964
        super.setEditing(b);
965
        FeatureStore fs = getFeatureStore();
966
        if (b) {
967
            try {
968
                fs.edit();
969
            } catch (ReadException e) {
970
                throw new StartEditionLayerException(getName(), e);
971
            } catch (DataException e) {
972
                throw new StartEditionLayerException(getName(), e);
973
            }
974
        }
975
        setSpatialCacheEnabled(b);
976
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
977
    }
978

    
979
    /**
980
     * @deprecated Use {@link #getSpatialCache()}
981
     */
982
    public void clearSpatialCache() {
983
        spatialCache.clearAll();
984
    }
985

    
986
    /**
987
     * @deprecated Use {@link #getSpatialCache()}
988
     */
989
    public boolean isSpatialCacheEnabled() {
990
        return spatialCache.isEnabled();
991
    }
992

    
993
    /**
994
     * @deprecated Use {@link #getSpatialCache()}
995
     */
996
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
997
        spatialCache.setEnabled(spatialCacheEnabled);
998
    }
999

    
1000
    public SpatialCache getSpatialCache() {
1001
        return spatialCache;
1002
    }
1003

    
1004
    /**
1005
     * Siempre es un numero mayor de 1000
1006
     * 
1007
     * @param maxFeatures
1008
     */
1009
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1010
        if (maxFeatures > spatialCache.getMaxFeatures()) {
1011
            spatialCache.setMaxFeatures(maxFeatures);
1012
        }
1013

    
1014
    }
1015

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

    
1029
    public void reload() throws ReloadLayerException {
1030
        super.reload();
1031
        try {
1032
            getFeatureStore().refresh();
1033
        } catch (Exception e) {
1034
            throw new ReloadLayerException(getName(), e);
1035
        }
1036
    }
1037

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

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

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

    
1055
    }
1056

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

    
1065
    protected void cleanLoadOptions() {
1066
        this.loadLegend = null;
1067
    }
1068

    
1069
    public boolean isWritable() {
1070
        return getFeatureStore().allowWrite();
1071
    }
1072

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

    
1084
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
1085

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

    
1092
        return clonedLayer;
1093
    }
1094

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

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

    
1116
            Envelope geomBounds = geom.getEnvelope();
1117

    
1118
            // ICoordTrans ct = getCoordTrans();
1119

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

    
1126
            double dist1Pixel = viewPort.getDist1pixel();
1127

    
1128
            onePoint =
1129
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
1130

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

    
1147
            }
1148

    
1149
        }
1150
        return onePoint;
1151
    }
1152

    
1153
    /*
1154
     * jaume. Stuff from ILabeled.
1155
     */
1156

    
1157
    public boolean isLabeled() {
1158
        return isLabeled;
1159
    }
1160

    
1161
    public void setIsLabeled(boolean isLabeled) {
1162
        this.isLabeled = isLabeled;
1163
    }
1164

    
1165
    public ILabelingStrategy getLabelingStrategy() {
1166
        return strategy;
1167
    }
1168

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

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

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

    
1198
    // M?todos para el uso de HyperLinks en capas FLyerVect
1199

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

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

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

    
1244
    public void load() throws LoadLayerException {
1245
        super.load();
1246
    }
1247

    
1248
    public FeatureStore getFeatureStore() {
1249
        return (FeatureStore) getDataStore();
1250
    }
1251

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

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

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

    
1304
    }
1305

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

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

    
1355
    }
1356

    
1357
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1358
    DataException {
1359

    
1360
        return getInfo(p, tolerance, cancel, true);
1361
    }
1362

    
1363
    public DynObjectSet getInfo(Point p,
1364
        double tolerance,
1365
        Cancellable cancel,
1366
        boolean fast) throws LoadLayerException, DataException {
1367
        Point2D infop = new Point2D.Double(p.x, p.y);
1368
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1369
        return queryByPoint(pReal,
1370
            tolerance,
1371
            getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1372
    }
1373

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

    
1386
    public boolean symbolChanged(SymbolLegendEvent e) {
1387
        LegendChangedEvent ev =
1388
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1389
        this.callLegendChanged(ev);
1390
        return true;
1391
    }
1392

    
1393
    public void update(Observable observable, Object notification) {
1394
        if (observable.equals(this.featureStore)) {
1395
            if (notification instanceof FeatureStoreNotification) {
1396
                FeatureStoreNotification event =
1397
                    (FeatureStoreNotification) notification;
1398
                if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING
1399
                    || event.getType() == FeatureStoreNotification.AFTER_DELETE
1400
                    || event.getType() == FeatureStoreNotification.AFTER_UNDO
1401
                    || event.getType() == FeatureStoreNotification.AFTER_REDO
1402
                    || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1403
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1404
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1405
                    || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1406
                    || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1407
                    this.updateDrawVersion();
1408

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

    
1436
    }
1437

    
1438
    /*
1439
     * (non-Javadoc)
1440
     * 
1441
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1442
     */
1443
    public Set getMetadataChildren() {
1444
        Set ret = new TreeSet();
1445
        ret.add(this.featureStore);
1446
        return ret;
1447
    }
1448

    
1449
    /*
1450
     * (non-Javadoc)
1451
     * 
1452
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1453
     */
1454
    public Object getMetadataID() throws MetadataException {
1455
        return "Layer(" + this.getName() + "):"
1456
        + this.featureStore.getMetadataID();
1457
    }
1458

    
1459

    
1460

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

    
1477
    public static void registerPersistent() {
1478
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1479
        if (manager.getDefinition(FLyrDefault.class) == null) {
1480
            FLyrDefault.registerPersistent();
1481
        }
1482
        DynStruct definition =
1483
            manager.addDefinition(FLyrVect.class,
1484
                "FLyrVect",
1485
                "FLyrVect Persistence definition",
1486
                null,
1487
                null);
1488
        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1489
        "FLyrDefault");
1490

    
1491
        definition.addDynFieldObject("legend")
1492
        .setClassOfValue(IVectorLegend.class)
1493
        .setMandatory(true);
1494
        definition.addDynFieldObject("featureStore")
1495
        .setClassOfValue(FeatureStore.class)
1496
        .setMandatory(true);
1497
        definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1498
        definition.addDynFieldInt("typeShape").setMandatory(true);
1499
        definition.addDynFieldObject("labelingStrategy")
1500
        .setClassOfValue(ILabelingStrategy.class)
1501
        .setMandatory(false);
1502

    
1503
    }
1504

    
1505
    protected void doDispose() throws BaseException {
1506
        dispose(featureStore);
1507
        spatialCache.clearAll();
1508
    }
1509
}