Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / layers / FLyrVect.java @ 5794

History | View | Annotate | Download (33.6 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 com.iver.cit.gvsig.fmap.layers;
42

    
43
import java.awt.Graphics2D;
44
import java.awt.Point;
45
import java.awt.geom.Point2D;
46
import java.awt.geom.Rectangle2D;
47
import java.awt.image.BufferedImage;
48
import java.io.File;
49
import java.io.IOException;
50

    
51
import org.apache.log4j.Logger;
52
import org.cresques.cts.ICoordTrans;
53

    
54
import com.hardcode.driverManager.DriverLoadException;
55
import com.hardcode.gdbms.engine.data.DataSourceFactory;
56
import com.hardcode.gdbms.engine.data.NoSuchTableException;
57
import com.hardcode.gdbms.engine.instruction.FieldNotFoundException;
58
import com.iver.cit.gvsig.fmap.DriverException;
59
import com.iver.cit.gvsig.fmap.ViewPort;
60
import com.iver.cit.gvsig.fmap.core.IGeometry;
61
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
62
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
63
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
64
import com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver;
65
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
66
import com.iver.cit.gvsig.fmap.drivers.shp.IndexedShpDriver;
67
import com.iver.cit.gvsig.fmap.edition.AnnotationEditableAdapter;
68
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
69
import com.iver.cit.gvsig.fmap.edition.EditionException;
70
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
71
import com.iver.cit.gvsig.fmap.edition.VectorialEditableDBAdapter;
72
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
73
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
74
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
75
import com.iver.cit.gvsig.fmap.layers.layerOperations.Labelable;
76
import com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData;
77
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
78
import com.iver.cit.gvsig.fmap.layers.layerOperations.SingleLayer;
79
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData;
80
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialXMLItem;
81
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
82
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
83
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
84
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
85
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
86
import com.iver.cit.gvsig.fmap.rendering.Legend;
87
import com.iver.cit.gvsig.fmap.rendering.LegendChangedEvent;
88
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
89
import com.iver.cit.gvsig.fmap.rendering.SingleSymbolLegend;
90
import com.iver.cit.gvsig.fmap.rendering.VectorialLegend;
91
import com.iver.cit.gvsig.fmap.spatialindex.IPersistentSpatialIndex;
92
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
93
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeGt2;
94
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
95
import com.iver.cit.gvsig.fmap.spatialindex.RTreeJsi;
96
import com.iver.cit.gvsig.fmap.spatialindex.RTreeSptLib;
97
import com.iver.cit.gvsig.fmap.spatialindex.SpatialIndexException;
98
import com.iver.utiles.FileUtils;
99
import com.iver.utiles.IPersistance;
100
import com.iver.utiles.PostProcessSupport;
101
import com.iver.utiles.XMLEntity;
102
import com.iver.utiles.swing.threads.Cancellable;
103
import com.iver.utiles.swing.threads.CancellableMonitorable;
104

    
105
/**
106
 * Capa b?sica Vectorial.
107
 *
108
 * @author Fernando Gonz?lez Cort?s
109
 */
110

    
111
// TODO Cuando no sea para pruebas debe no ser public
112
public class FLyrVect extends FLyrDefault implements Labelable,
113
                ClassifiableVectorial, SingleLayer, VectorialData, RandomVectorialData,
114
                AlphanumericData, InfoByPoint {
115
        private static Logger logger = Logger.getLogger(FLyrVect.class.getName());
116

    
117
        /** Leyenda de la capa vectorial */
118
        private VectorialLegend legend;
119

    
120
        private int typeShape = -1;
121

    
122
        private LayerChangeSupport layerChangeSupport = new LayerChangeSupport();
123

    
124
        private ReadableVectorial source;
125

    
126
        private SelectableDataSource sds;
127

    
128
        private SelectionSupport selectionSupport = new SelectionSupport();
129

    
130
        private SpatialCache spatialCache = null;
131
        private boolean spatialCacheEnabled = false;
132

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

    
139
        private boolean bHasJoin = false;
140

    
141
        /**
142
         * A?ade un SelectionListener a la lista de listeners.
143
         *
144
         * @param listener
145
         *            SelectionListener.
146
         */
147
        /*
148
         * public void addSelectionListener(SelectionListener listener) { try {
149
         * getRecordset().addSelectionListener(listener); } catch (DriverException
150
         * e) { // TODO Auto-generated catch block e.printStackTrace(); } }
151
         */
152
        /**
153
         * Borra un selectionListener de la lista de listeners.
154
         *
155
         * @param listener
156
         *            SelectionListener
157
         */
158
        /*
159
         * public void removeSelectionListener(SelectionListener listener) { try {
160
         * getRecordset().removeSelectionListener(listener); } catch
161
         * (DriverException e) { // TODO Auto-generated catch block
162
         * e.printStackTrace(); } }
163
         */
164
        /**
165
         * Cuando ocurre un evento de cambio en la selecci?n, ?ste puede ser uno de
166
         * una gran cantidad de eventos. Con el fin de no propagar todos estos
167
         * eventos, se realiza la propagaci?n de manera manual al final de la
168
         * "r?faga" de eventos
169
         */
170
        /*
171
         * public void fireSelectionEvents() { try {
172
         * getRecordset().fireSelectionEvents(); } catch (DriverException e) { //
173
         * TODO Auto-generated catch block e.printStackTrace(); } }
174
         */
175
        /**
176
         * Devuelve el VectorialAdapater de la capa.
177
         *
178
         * @return VectorialAdapter.
179
         */
180
        public ReadableVectorial getSource() {
181
                return source;
182
        }
183

    
184
        /**
185
         * If we use a persistent spatial index associated with this layer, and the
186
         * index is not intrisic to the layer (for example spatial databases) this
187
         * method looks for existent spatial index, and loads it.
188
         *
189
         */
190
        private void loadSpatialIndex() {
191
                //FIXME: Al abrir el indice en fichero...
192
                //?C?mo lo liberamos? un metodo Layer.shutdown()
193

    
194

    
195
                ReadableVectorial source = getSource();
196
                //REVISAR QUE PASA CON LOS DRIVERS DXF, DGN, etc.
197
                //PUES SON VECTORIALFILEADAPTER
198
                if (!(source instanceof VectorialFileAdapter)) {
199
                        // we are not interested in db adapters
200
                        return;
201
                }
202
                VectorialDriver driver = source.getDriver();
203
                if (!(driver instanceof BoundedShapes)) {
204
                        // we dont spatially index layers that are not bounded
205
                        return;
206
                }
207
                File file = ((VectorialFileAdapter) source).getFile();
208
                String fileName = file.getAbsolutePath();
209
                File sptFile = new File(fileName + ".qix");
210
                if (!sptFile.exists() || (!(sptFile.length() > 0))) {
211
                        // before to exit, look for it in temp path
212
                        String tempPath = System.getProperty("java.io.tmpdir");
213
                        fileName = tempPath + File.separator + sptFile.getName();
214
                        sptFile = new File(fileName);
215
                        // it doesnt exists, must to create
216
                        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
217
                                return;
218
                        }// if
219
                }// if
220

    
221
                try {
222
                        source.start();
223
                        spatialIndex = new QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
224
                                        "NM", source.getFullExtent(), source.getShapeCount(), false);
225
                } catch (SpatialIndexException e) {
226
                        spatialIndex = null;
227
                        e.printStackTrace();
228
                        return;
229
                } catch (DriverIOException e) {
230
                        // TODO Auto-generated catch block
231
                        e.printStackTrace();
232
                }
233

    
234
        }
235

    
236
        /**
237
         * Checks if it has associated an external spatial index
238
         * (an spatial index file).
239
         *
240
         * It looks for it in main file path, or in temp system path.
241
         * If main file is rivers.shp, it looks for a file called
242
         * rivers.shp.qix.
243

244
         * @return
245
         */
246
        public boolean isExternallySpatiallyIndexed() {
247
                /*
248
                 * FIXME (AZABALA): Independizar del tipo de fichero de ?ndice
249
                  * con el que se trabaje (ahora mismo considera la extension .qix,
250
             * pero esto depender? del tipo de ?ndice)
251
                 * */
252
                ReadableVectorial source = getSource();
253
                if (!(source instanceof VectorialFileAdapter)) {
254
                        // we are not interested in db adapters.
255
                        // think in non spatial dbs, like HSQLDB
256
                        return false;
257
                }
258
                File file = ((VectorialFileAdapter) source).getFile();
259
                String fileName = file.getAbsolutePath();
260
                File sptFile = new File(fileName + ".qix");
261
                if (!sptFile.exists() || (!(sptFile.length() > 0))) {
262
                        // before to exit, look for it in temp path
263
                        // it doesnt exists, must to create
264
                        String tempPath = System.getProperty("java.io.tmpdir");
265
                        fileName = tempPath + File.separator + sptFile.getName();
266
                        sptFile = new File(fileName);
267
                        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
268
                                return false;
269
                        }// if
270
                }// if
271
                return true;
272
        }
273

    
274
        /**
275
         * Inserta el VectorialAdapter a la capa.
276
         *
277
         * @param va
278
         *            VectorialAdapter.
279
         */
280
        public void setSource(ReadableVectorial rv) {
281
                source = rv;
282
                // azabala: we check if this layer could have a file spatial index
283
                // and load it if it exists
284
                loadSpatialIndex();
285
        }
286

    
287
        /**
288
         * @see com.iver.cit.gvsig.fmap.layers.LayerOperations#getFullExtent()
289
         */
290
        public Rectangle2D getFullExtent() throws DriverException {
291
                try {
292
                        Rectangle2D rAux;
293
                        logger.debug(getName() + "_source.start()");
294
                        source.start();
295
                        rAux = source.getFullExtent();
296
                        logger.debug(getName() + "_source.stop()");
297
                        source.stop();
298

    
299
                        // Si existe reproyecci?n, reproyectar el extent
300
                        ICoordTrans ct = getCoordTrans();
301

    
302
                        if (ct != null) {
303
                                Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
304
                                Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
305
                                pt1 = ct.convert(pt1, null);
306
                                pt2 = ct.convert(pt2, null);
307
                                rAux = new Rectangle2D.Double();
308
                                rAux.setFrameFromDiagonal(pt1, pt2);
309
                        }
310

    
311
                        return rAux;
312
                } catch (DriverIOException e) {
313
                        throw new DriverException(e);
314
                }
315
        }
316

    
317
        /**
318
         * @see com.iver.cit.gvsig.fmap.layers.LayerOperations#draw(java.awt.image.BufferedImage,
319
         *      java.awt.Graphics2D, com.iver.cit.gvsig.fmap.ViewPort)
320
         */
321
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
322
                        Cancellable cancel, double scale) throws DriverException {
323

    
324
                if (isWithinScale(scale)) {
325
                        // Las que solo tienen etiquetado sin pintar el shape,
326
                        // no pasamos por ellas
327
                        boolean bDrawShapes = true;
328
                        if (legend instanceof SingleSymbolLegend) {
329
                                if (legend.getDefaultSymbol().isShapeVisible() == false)
330
                                        bDrawShapes = false;
331
                        }
332
                        if (bDrawShapes) {
333
                                Strategy strategy = StrategyManager.getStrategy(this);
334
                                try {
335
                                        strategy.draw(image, g, viewPort, cancel);
336
                                } catch (DriverException e) {
337
                                        this.setVisible(false);
338
                                        this.setActive(false);
339
                                        throw e;
340
                                }
341
                        }
342
                        if (getVirtualLayers() != null) {
343
                                getVirtualLayers().draw(image, g, viewPort, cancel, scale);
344
                        }
345

    
346
                        if (getLayerText() != null) {
347
                                getLayerText().draw(image, g, viewPort, cancel, scale);
348
                        }
349
                }
350
        }
351

    
352
        /**
353
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
354
         *      com.iver.cit.gvsig.fmap.ViewPort,
355
         *      com.iver.utiles.swing.threads.Cancellable)
356
         */
357
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
358
                        double scale) throws DriverException {
359
                if (isVisible() && isWithinScale(scale)) {
360
                        Strategy strategy = StrategyManager.getStrategy(this);
361

    
362
                        strategy.print(g, viewPort, cancel);
363

    
364
                        if (getLayerText() != null) {
365
                                getLayerText().draw(null, g, viewPort, cancel, scale);
366
                        }
367
                }
368
        }
369

    
370
        /**
371
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#createLabelLayer(int)
372
         */
373
        // public FLayer createLabelLayer(int fieldId) {
374
        public FLayer createLabelLayer(SelectableDataSource ds) {
375
                FLyrText layerText = null;
376
                try {
377
                        layerText = new FLyrText();
378
                        layerText.setLegend((VectorialLegend) getLegend());
379
                        layerText.createLabels(this);
380
                } catch (FieldNotFoundException e1) {
381
                        // TODO Auto-generated catch block
382
                        e1.printStackTrace();
383
                } catch (DriverException e1) {
384
                        // TODO Auto-generated catch block
385
                        e1.printStackTrace();
386
                }
387

    
388
                setLayerText(layerText);
389
                layerText.setCoordTrans(getCoordTrans());
390
                return layerText;
391
        }
392

    
393
        /**
394
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#removeLabels()
395
         */
396
        public void removeLabels() {
397
                setLayerText(null);
398
        }
399

    
400
        /*
401
         * (non-Javadoc)
402
         *
403
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#deleteSpatialIndex()
404
         */
405
        public void deleteSpatialIndex() {
406
                //must we delete possible spatial indexes files?
407
                spatialIndex = null;
408
        }
409

    
410

    
411

    
412
   /**
413
    * <p>
414
    * Creates an spatial index associated to this layer.
415
    * The spatial index will used
416
    * the native projection of the layer, so if the layer is reprojected, it will
417
    * be ignored.
418
    * </p>
419
    * @param cancelMonitor instance of CancellableMonitorable that allows
420
    * to monitor progress of spatial index creation, and cancel the process
421
    */
422
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
423
             // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
424
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
425
        // para que acepten recorrer sin geometria, solo con rectangulos.
426

    
427
            //If this vectorial layer is based in a spatial database, the spatial
428
                //index is already implicit. We only will index file drivers
429
            ReadableVectorial va = getSource();
430
            //We must think in non spatial databases, like HSQLDB
431
                if(!(va instanceof VectorialFileAdapter)){
432
                        return;
433
                }
434
                if (!(va.getDriver() instanceof BoundedShapes)) {
435
                        return;
436
                }
437
                File file = ((VectorialFileAdapter) va).getFile();
438
                String fileName = file.getAbsolutePath();
439
                ISpatialIndex localCopy = null;
440
                try {
441
                        va.start();
442
                        localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
443
                                        va.getShapeCount(), true);
444

    
445
                } catch (SpatialIndexException e1) {
446
                        // Probably we dont have writing permissions
447
                        String directoryName = System.getProperty("java.io.tmpdir");
448
                        File newFile = new File(directoryName +
449
                                        File.separator +
450
                                        file.getName());
451
                        String newFileName = newFile.getName();
452
                        try {
453
                                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
454
                                                va.getShapeCount(), true);
455
                        } catch (SpatialIndexException e) {
456
                                // if we cant build a file based spatial index, we'll build
457
                                // a pure memory spatial index
458
                                localCopy = new QuadtreeJts();
459
                        } catch (DriverIOException e) {
460
                                // TODO Auto-generated catch block
461
                                e.printStackTrace();
462
                        }
463

    
464
                }catch(Exception e){
465
                        e.printStackTrace();
466
                }//try
467
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
468
        try {
469
            for (int i=0; i < va.getShapeCount(); i++)
470
            {
471
                    if(cancelMonitor != null){
472
                            if(cancelMonitor.isCanceled())
473
                                    return;
474
                            cancelMonitor.reportStep();
475
                    }
476
                Rectangle2D r = shapeBounds.getShapeBounds(i);
477
                localCopy.insert(r, i);
478
            } // for
479
            va.stop();
480
            if(localCopy instanceof IPersistentSpatialIndex)
481
                    ((IPersistentSpatialIndex) localCopy).flush();
482
            spatialIndex = localCopy;
483
        } catch (DriverIOException e) {
484
            // TODO Auto-generated catch block
485
            e.printStackTrace();
486
        } catch (IOException e) {
487
            // TODO Auto-generated catch block
488
            e.printStackTrace();
489
        }
490
    }
491

    
492
        /**
493
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#createIndex()
494
         */
495
        public void createSpatialIndex() {
496
                createSpatialIndex(null);
497
        }
498

    
499
        /**
500
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor,
501
         *      FBitSet)
502
         */
503
        public void process(FeatureVisitor visitor, FBitSet subset)
504
                        throws DriverException, VisitException {
505
                Strategy s = StrategyManager.getStrategy(this);
506
                s.process(visitor, subset);
507
        }
508

    
509
        /**
510
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor)
511
         */
512
        public void process(FeatureVisitor visitor) throws DriverException,
513
                        VisitException {
514
                Strategy s = StrategyManager.getStrategy(this);
515
                s.process(visitor);
516
        }
517

    
518
        /**
519
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor,
520
         *      Rectangle2D)
521
         */
522
        public void process(FeatureVisitor visitor, Rectangle2D rect)
523
                        throws DriverException, VisitException {
524
                Strategy s = StrategyManager.getStrategy(this);
525
                s.process(visitor, rect);
526
        }
527

    
528
        /**
529
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#setSelection(com.iver.cit.gvsig.fmap.operations.selection.VectorialSubSet)
530
         */
531
        /*
532
         * public void setSelection(FBitSet selection) { try {
533
         * getRecordset().setSelection(selection); } catch (DriverException e) { //
534
         * TODO Auto-generated catch block e.printStackTrace(); }
535
         * fireSelectionEvents(); }
536
         */
537
        /**
538
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#isSelected(int)
539
         */
540
        /*
541
         * public boolean isSelected(int index) { try { return
542
         * getRecordset().isSelected(index); } catch (DriverException e) { // TODO
543
         * Auto-generated catch block e.printStackTrace(); } return false; }
544
         */
545
        /**
546
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getSelection()
547
         */
548
        /*
549
         * public FBitSet getSelection() { try { return
550
         * getRecordset().getSelection(); } catch (DriverException e) { // TODO
551
         * Auto-generated catch block e.printStackTrace(); } return new FBitSet(); }
552
         */
553
        /**
554
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#clearSelection()
555
         */
556
        /*
557
         * public void clearSelection() { try { getRecordset().clearSelection(); }
558
         * catch (DriverException e) { // TODO Auto-generated catch block
559
         * e.printStackTrace(); } }
560
         */
561

    
562
        /*
563
         * (non-Javadoc)
564
         *
565
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#queryByRect(java.awt.geom.Rectangle2D)
566
         */
567
        public FBitSet queryByRect(Rectangle2D rect) throws DriverException {
568
                Strategy s = StrategyManager.getStrategy(this);
569

    
570
                return s.queryByRect(rect);
571
        }
572

    
573
        public FBitSet queryByPoint(Point2D p, double tolerance)
574
                        throws DriverException {
575
                Strategy s = StrategyManager.getStrategy(this);
576
                return s.queryByPoint(p, tolerance);
577
        }
578

    
579
        public FBitSet queryByShape(IGeometry g, int relationship)
580
                        throws DriverException, VisitException {
581
                Strategy s = StrategyManager.getStrategy(this);
582
                return s.queryByShape(g, relationship);
583
        }
584

    
585
        public XMLItem[] getInfo(Point p, double tolerance) throws DriverException {
586
                Point2D pReal = this.getFMap().getViewPort().toMapPoint(p);
587
                FBitSet bs = queryByPoint(pReal, tolerance);
588
                VectorialXMLItem[] item = new VectorialXMLItem[1];
589
                item[0] = new VectorialXMLItem(bs, this);
590

    
591
                return item;
592
        }
593

    
594
        /**
595
         * @throws DriverException
596
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getRecordset()
597
         */
598
        /*
599
         * public SelectableDataSource getRecordset() throws DriverException { if
600
         * (sds == null){ try { DataSource ds = getSource().getRecordset();
601
         *
602
         * if (ds == null) { return null; }
603
         *
604
         * sds = new SelectableDataSource(ds);
605
         * //sds.setSelectionSupport(selectionSupport);
606
         *
607
         * return sds; } catch (DriverLoadException e) { throw new
608
         * DriverException(e); } catch
609
         * (com.hardcode.gdbms.engine.data.driver.DriverException e) { throw new
610
         * DriverException(e); } } return sds; }
611
         */
612
        /**
613
         * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
614
         * forma, podr?s poner leyendas basadas en el nuevo recordset
615
         *
616
         * @param newSds
617
         * @throws DriverException
618
         * @throws FieldNotFoundException
619
         * @throws FieldNotFoundException
620
         */
621
        /*
622
         * public void setRecordset(SelectableDataSource newSds) throws
623
         * DriverException, FieldNotFoundException { sds = newSds;
624
         * //sds.setSelectionSupport(selectionSupport); legend.setDataSource(sds);
625
         * logger.debug("Recordset cambiado a " + sds.getName()); }
626
         */
627
        /**
628
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#setLegend(int,
629
         *      com.iver.cit.gvsig.fmap.rendering.Legend)
630
         */
631
        public void setLegend(VectorialLegend r) throws DriverException,
632
                        FieldNotFoundException {
633
                VectorialLegend oldLegend = legend;
634
                legend = r;
635

    
636
                try {
637
                        legend.setDataSource(getRecordset());
638

    
639
                        if (legend.getLabelField() != null) {
640
                                // sds.start();
641
                                // int idLabelField =
642
                                // getRecordset().getFieldIndexByName(legend.getLabelField());
643
                                createLabelLayer(getSource().getRecordset());
644
                                // sds.stop();
645
                        } else
646
                                removeLabels();
647
                } catch (DriverException e) {
648
                        throw new DriverException(e);
649
                } catch (FieldNotFoundException e) {
650
                        // TODO Auto-generated catch block
651
                        e.printStackTrace();
652
                } catch (DriverLoadException e) {
653
                        // TODO Auto-generated catch block
654
                        e.printStackTrace();
655
                }
656

    
657
                LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
658
                                oldLegend, legend);
659
                callLegendChanged(e);
660
        }
661

    
662
        /**
663
         * Devuelve la Leyenda de la capa.
664
         *
665
         * @return Leyenda.
666
         */
667
        public Legend getLegend() {
668
                return legend;
669
        }
670

    
671
        /**
672
         * Devuelve el tipo de shape que contiene la capa.
673
         *
674
         * @return tipo de shape.
675
         *
676
         * @throws DriverException
677
         */
678
        public int getShapeType() throws DriverException {
679
                if (typeShape == -1) {
680
                        try {
681
                                logger.debug("source.start()");
682
                                getSource().start();
683
                                typeShape = getSource().getShapeType();
684
                                logger.debug("source.stop()");
685
                                getSource().stop();
686
                        } catch (DriverIOException e) {
687
                                throw new DriverException(e);
688
                        }
689
                }
690

    
691
                return typeShape;
692
        }
693

    
694
        /**
695
         * @throws XMLException
696
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getProperties()
697
         */
698
        public XMLEntity getXMLEntity() throws XMLException {
699
                XMLEntity xml = super.getXMLEntity();
700
                xml.addChild(getLegend().getXMLEntity());
701
                try {
702
                        xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
703

    
704
                } catch (DriverException e1) {
705
                        e1.printStackTrace();
706
                        throw new XMLException(e1);
707
                }
708
                //Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
709
                ReadableVectorial rv=getSource();
710
                if (getSource() instanceof VectorialEditableAdapter) {
711
                        setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
712
                }
713
                if (getSource() instanceof VectorialFileAdapter) {
714
                        xml.putProperty("type", "vectorial");
715
                        xml.putProperty("file", ((VectorialFileAdapter) getSource())
716
                                        .getFile());
717
                        // try {
718
                        try {
719
                                xml.putProperty("recordset-name", getSource().getRecordset()
720
                                                .getName());
721
                        } catch (DriverLoadException e) {
722
                                // TODO Auto-generated catch block
723
                                e.printStackTrace();
724
                        }
725
                        // } catch (DriverException e) {
726
                        // throw new XMLException(e);
727
                        // }
728
                } else if (source instanceof VectorialDBAdapter) {
729
                        xml.putProperty("type", "vectorial");
730

    
731
                        VectorialDatabaseDriver dbDriver = (VectorialDatabaseDriver) getSource()
732
                                        .getDriver();
733

    
734
                        // Guardamos el nombre del driver para poder recuperarlo
735
                        // con el DriverManager de Fernando.
736
                        xml.putProperty("db", dbDriver.getName());
737
                        // try {
738
                        try {
739
                                xml.putProperty("recordset-name", getSource().getRecordset()
740
                                                .getName());
741
                        } catch (DriverLoadException e) {
742
                                // TODO Auto-generated catch block
743
                                e.printStackTrace();
744
                        }
745
                        // } catch (DriverException e) {
746
                        // throw new XMLException(e);
747
                        // }
748
                        xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
749
                                                                                                        // metido la leyenda y el
750
                                                                                                        // selection support
751
                } else if (source instanceof VectorialAdapter) {
752
                        // Se supone que hemos hecho algo gen?rico.
753
                        xml.putProperty("type", "vectorial");
754

    
755
                        VectorialDriver driver = (VectorialDriver) getSource().getDriver();
756

    
757
                        // Guardamos el nombre del driver para poder recuperarlo
758
                        // con el DriverManager de Fernando.
759
                        xml.putProperty("other", driver.getName());
760
                        // try {
761
                        try {
762
                                xml.putProperty("recordset-name", getSource().getRecordset()
763
                                                .getName());
764
                        } catch (DriverLoadException e) {
765
                                // TODO Auto-generated catch block
766
                                e.printStackTrace();
767
                        }
768
                        // } catch (DriverException e) {
769
                        // throw new XMLException(e);
770
                        // }
771
                        if (driver instanceof IPersistance) {
772
                                // xml.putProperty("className", driver.getClass().getName());
773
                                IPersistance persist = (IPersistance) driver;
774
                                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
775
                                                                                                                // hemos metido la
776
                                                                                                                // leyenda y el
777
                                                                                                                // selection support
778
                        }
779
                }
780
                setSource(rv);
781
                xml.putProperty("driverName", getSource().getDriver().getName());
782
                if (bHasJoin)
783
                        xml.putProperty("hasJoin", "true");
784

    
785
                return xml;
786
        }
787

    
788
        /**
789
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
790
         */
791
        public void setXMLEntity03(XMLEntity xml) throws XMLException {
792

    
793
                super.setXMLEntity(xml);
794
                legend = LegendFactory.createFromXML03(xml.getChild(0));
795

    
796
                try {
797
                        // legend.setDataSource(getRecordset());
798
                        setLegend(legend);
799
                } catch (FieldNotFoundException e) {
800
                        throw new XMLException(e);
801
                } catch (DriverException e) {
802
                        throw new XMLException(e);
803
                }
804

    
805
                try {
806
                        getRecordset().getSelectionSupport()
807
                                        .setXMLEntity03(xml.getChild(1));
808
                } catch (DriverException e) {
809
                        e.printStackTrace();
810
                }
811
        }
812

    
813
        /**
814
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
815
         */
816
        public void setXMLEntity(XMLEntity xml) throws XMLException {
817
                super.setXMLEntity(xml);
818

    
819
                VectorialLegend leg = LegendFactory.createFromXML(xml.getChild(0));
820
                try {
821
                        getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
822
                        String recordsetName = xml.getStringProperty("recordset-name");
823

    
824
                        LayerFactory.getDataSourceFactory().changeDataSourceName(
825
                                        getSource().getRecordset().getName(), recordsetName);
826
                        // Hacemos que el recordset que hemos creado antes (los
827
                        // recordset se crean antes que todo) sea el recordset
828
                        // de esta capa. Y del que se crea automaticamente
829
                        // en el setLegend del createLayer, nos olvidamos
830
                        SelectableDataSource sds = new SelectableDataSource(LayerFactory
831
                                        .getDataSourceFactory().createRandomDataSource(
832
                                                        recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
833
                        // sds.setSelectionSupport(selectionSupport);
834
                        // ((EditableAdapter)getSource()).setRecordSet(sds);
835
                } catch (NoSuchTableException e1) {
836
                        throw new XMLException(e1);
837
                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e1) {
838
                        throw new XMLException(e1);
839
                } catch (DriverLoadException e1) {
840
                        throw new XMLException(e1);
841
                } catch (DriverException e1) {
842
                        throw new XMLException(e1);
843
                }
844
                // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
845
                // el final
846
                // de la lectura del proyecto
847
                if (xml.contains("hasJoin")) {
848
                        setIsJoined(true);
849
                        PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
850
                } else {
851
                        try {
852
                                // legend.setDataSource(getRecordset());
853
                                setLegend(leg);
854
                        } catch (FieldNotFoundException e) {
855
                                throw new XMLException(e);
856
                        } catch (DriverException e) {
857
                                throw new XMLException(e);
858
                        }
859
                }
860

    
861
        }
862

    
863
        /**
864
         * A?ade un LegendListener a la lista de Listeners.
865
         *
866
         * @param listener
867
         *            LegendListener.
868
         */
869
        public void addLegendListener(LegendListener listener) {
870
                layerChangeSupport.addLayerListener(listener);
871
        }
872

    
873
        /**
874
         * Llamada al m?todo callLegendChanged de los listener.
875
         *
876
         * @param e
877
         *            Evento.
878
         */
879
        private void callLegendChanged(LegendChangedEvent e) {
880
                layerChangeSupport.callLegendChanged(e);
881
        }
882

    
883
        /**
884
         * Borra un LegendListener de la lista de Listeners
885
         *
886
         * @param listener
887
         *            LegendListener.
888
         */
889
        public void removeLegendListener(LegendListener listener) {
890
                layerChangeSupport.removeLayerListener(listener);
891
        }
892

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

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

    
909
        public boolean isJoined() {
910
                return bHasJoin;
911
        }
912

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

    
945
        public void setIsJoined(boolean hasJoin) {
946
                bHasJoin = hasJoin;
947
        }
948

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

    
967
        /*
968
         * public SelectableDataSource getRecordset() { try { return
969
         * getSource().getRecordset(); } catch (DriverLoadException e) { // TODO
970
         * Auto-generated catch block e.printStackTrace(); } return null; }
971
         */
972

    
973
        /**
974
         * @throws DriverException
975
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getRecordset()
976
         */
977
        public SelectableDataSource getRecordset() throws DriverException {
978
                if (sds == null) {
979
                        try {
980
                                SelectableDataSource ds = source.getRecordset();
981

    
982
                                if (ds == null) {
983
                                        return null;
984
                                }
985

    
986
                                sds = ds;
987
                                sds.setSelectionSupport(selectionSupport);
988

    
989
                        } catch (DriverLoadException e) {
990
                                throw new DriverException(e);
991
                        }
992
                }
993
                return sds;
994
        }
995

    
996
        /*
997
         * (non-Javadoc)
998
         *
999
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setEditing(boolean)
1000
         */
1001
        public void setEditing(boolean b) throws EditionException {
1002
                super.setEditing(b);
1003
                try {
1004
                        if (b) {
1005
                                VectorialEditableAdapter vea = null;
1006
                                // TODO: Qu? pasa si hay m?s tipos de adapters?
1007
                                // FJP: Se podr?a pasar como argumento el
1008
                                // VectorialEditableAdapter
1009
                                // que se quiera usar para evitar meter c?digo aqu? de este
1010
                                // estilo.
1011
                                if (getSource() instanceof VectorialDBAdapter) {
1012
                                        vea = new VectorialEditableDBAdapter();
1013
                                } else if (this instanceof FLyrAnnotation) {
1014
                                        vea = new AnnotationEditableAdapter(
1015
                                                        (FLyrAnnotation) this);
1016
                                } else {
1017
                                        vea = new VectorialEditableAdapter();
1018
                                }
1019
                                vea.setOriginalVectorialAdapter(getSource());
1020

    
1021
                                // /vea.setSpatialIndex(getSpatialIndex());
1022
                                // /vea.setFullExtent(getFullExtent());
1023
                                vea.startEdition(EditionEvent.GRAPHIC);
1024
                                setSource(vea);
1025
                                getRecordset().setSelectionSupport(
1026
                                                vea.getOriginalAdapter().getRecordset()
1027
                                                                .getSelectionSupport());
1028

    
1029
                        } else {
1030
                                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1031
                                setSource(vea.getOriginalAdapter());
1032
                        }
1033
                        // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1034
                        // recordset
1035
                        setRecordset(getSource().getRecordset());
1036
                        if (getLegend() instanceof VectorialLegend) {
1037
                                VectorialLegend ley = (VectorialLegend) getLegend();
1038
                                ley.setDataSource(getSource().getRecordset());
1039
                                // Esto lo pongo para evitar que al dibujar sobre un
1040
                                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1041
                                // de la leyenda de textos "dibujar solo textos".
1042
                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1043
                                        ley.setDefaultSymbol(new FSymbol(getShapeType()));
1044
                                }
1045
                                ley.useDefaultSymbol(true);
1046
                        }
1047
                } catch (DriverLoadException e) {
1048
                        e.printStackTrace();
1049
                        throw new EditionException(e);
1050
                } catch (DriverException e) {
1051
                        e.printStackTrace();
1052
                        throw new EditionException(e);
1053
                } catch (FieldNotFoundException e) {
1054
                        e.printStackTrace();
1055
                        throw new EditionException(e);
1056
                }
1057

    
1058
                setSpatialCacheEnabled(b);
1059
                callEditionChanged(LayerEvent
1060
                                .createEditionChangedEvent(this, "edition"));
1061

    
1062
        }
1063

    
1064
        /**
1065
         * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1066
         * forma, podr?s poner leyendas basadas en el nuevo recordset
1067
         *
1068
         * @param newSds
1069
         */
1070
        public void setRecordset(SelectableDataSource newSds) {
1071
                sds = newSds;
1072
                sds.setSelectionSupport(selectionSupport);
1073
        }
1074
        /*
1075
         * public SelectionSupport getSelectionSupport() { return selectionSupport; }
1076
         *
1077
         * public void setSelectionSupport(SelectionSupport selectionSupport) {
1078
         * this.selectionSupport = selectionSupport; }
1079
         */
1080

    
1081
        public SpatialCache createSpatialCache() {
1082
               spatialCache = new SpatialCache();
1083
                return spatialCache;
1084
        }
1085

    
1086
//        public void setSpatialCache(SpatialCache spatialCache) {
1087
//                this.spatialCache = spatialCache;
1088
//        }
1089

    
1090
        public boolean isSpatialCacheEnabled() {
1091
                return spatialCacheEnabled;
1092
        }
1093

    
1094
        public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1095
                this.spatialCacheEnabled = spatialCacheEnabled;
1096
        }
1097

    
1098
        public SpatialCache getSpatialCache() {
1099
                return spatialCache;
1100
        }
1101

    
1102
        public void setMaxFeaturesInEditionCache(int maxFeatures) {
1103
                getSpatialCache().setMaxFeatures(maxFeatures);
1104
                
1105
        }
1106

    
1107
}