Statistics
| Revision:

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

History | View | Annotate | Download (35.4 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.Color;
44
import java.awt.Font;
45
import java.awt.Graphics2D;
46
import java.awt.Point;
47
import java.awt.geom.Point2D;
48
import java.awt.geom.Rectangle2D;
49
import java.awt.image.BufferedImage;
50
import java.io.File;
51
import java.io.IOException;
52

    
53
import org.apache.log4j.Logger;
54
import org.cresques.cts.ICoordTrans;
55

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

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

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

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

    
119
        private int typeShape = -1;
120

    
121
        private LayerChangeSupport layerChangeSupport = new LayerChangeSupport();
122

    
123
        private ReadableVectorial source;
124

    
125
        private SelectableDataSource sds;
126

    
127
        private SelectionSupport selectionSupport = new SelectionSupport();
128

    
129
        private SpatialCache spatialCache = new SpatialCache();
130
        private boolean spatialCacheEnabled = false;
131

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

    
138
        private boolean bHasJoin = false;
139

    
140
        private XMLEntity orgXMLEntity = null;
141

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

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

    
196

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

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

    
236
        }
237

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

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

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

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

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

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

    
313
                        //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
314
                        if (rAux.getWidth()==0 && rAux.getHeight()==0) {
315
                                rAux=new Rectangle2D.Double(0,0,100,100);
316
                        }
317

    
318
                        return rAux;
319
                } catch (DriverIOException e) {
320
                        throw new DriverException(e);
321
                }
322
        }
323

    
324
        /**
325
         * @see com.iver.cit.gvsig.fmap.layers.LayerOperations#draw(java.awt.image.BufferedImage,
326
         *      java.awt.Graphics2D, com.iver.cit.gvsig.fmap.ViewPort)
327
         */
328
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
329
                        Cancellable cancel, double scale) throws DriverException {
330

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

    
354
                        if (getLayerText() != null) {
355
                                getLayerText().draw(image, g, viewPort, cancel, scale);
356
                        }
357
                }
358
        }
359

    
360
        /**
361
         * Se llama antes de empezar a pintar.
362
         * Es ?til para preparar la cache a emplear, las leyendas, etc.
363
         * @param image
364
         * @param g
365
         * @param viewPort
366
         */
367
        private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
368

    
369
        }
370

    
371
        /**
372
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
373
         *      com.iver.cit.gvsig.fmap.ViewPort,
374
         *      com.iver.utiles.swing.threads.Cancellable)
375
         */
376
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
377
                        double scale) throws DriverException {
378
                if (isVisible() && isWithinScale(scale)) {
379
                        Strategy strategy = StrategyManager.getStrategy(this);
380

    
381
                        strategy.print(g, viewPort, cancel);
382

    
383
                        if (getLayerText() != null) {
384
                                getLayerText().draw(null, g, viewPort, cancel, scale);
385
                        }
386
                }
387
        }
388

    
389
        /**
390
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#createLabelLayer(int)
391
         */
392
        // public FLayer createLabelLayer(int fieldId) {
393
        public FLayer createLabelLayer(SelectableDataSource ds) {
394
                FLyrText layerText = null;
395
                try {
396
                        layerText = new FLyrText();
397
                        layerText.setLegend((VectorialLegend) getLegend());
398
                        layerText.createLabels(this);
399
                } catch (FieldNotFoundException e1) {
400
                        // TODO Auto-generated catch block
401
                        e1.printStackTrace();
402
                } catch (DriverException e1) {
403
                        // TODO Auto-generated catch block
404
                        e1.printStackTrace();
405
                }
406

    
407
                setLayerText(layerText);
408
                layerText.setCoordTrans(getCoordTrans());
409
                return layerText;
410
        }
411

    
412
        /**
413
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#removeLabels()
414
         */
415
        public void removeLabels() {
416
                setLayerText(null);
417
        }
418

    
419
        /*
420
         * (non-Javadoc)
421
         *
422
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#deleteSpatialIndex()
423
         */
424
        public void deleteSpatialIndex() {
425
                //must we delete possible spatial indexes files?
426
                spatialIndex = null;
427
        }
428

    
429

    
430

    
431
   /**
432
    * <p>
433
    * Creates an spatial index associated to this layer.
434
    * The spatial index will used
435
    * the native projection of the layer, so if the layer is reprojected, it will
436
    * be ignored.
437
    * </p>
438
    * @param cancelMonitor instance of CancellableMonitorable that allows
439
    * to monitor progress of spatial index creation, and cancel the process
440
    */
441
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
442
             // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
443
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
444
        // para que acepten recorrer sin geometria, solo con rectangulos.
445

    
446
            //If this vectorial layer is based in a spatial database, the spatial
447
                //index is already implicit. We only will index file drivers
448
            ReadableVectorial va = getSource();
449
            //We must think in non spatial databases, like HSQLDB
450
                if(!(va instanceof VectorialFileAdapter)){
451
                        return;
452
                }
453
                if (!(va.getDriver() instanceof BoundedShapes)) {
454
                        return;
455
                }
456
                File file = ((VectorialFileAdapter) va).getFile();
457
                String fileName = file.getAbsolutePath();
458
                ISpatialIndex localCopy = null;
459
                try {
460
                        va.start();
461
                        localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
462
                                        va.getShapeCount(), true);
463

    
464
                } catch (SpatialIndexException e1) {
465
                        // Probably we dont have writing permissions
466
                        String directoryName = System.getProperty("java.io.tmpdir");
467
                        File newFile = new File(directoryName +
468
                                        File.separator +
469
                                        file.getName());
470
                        String newFileName = newFile.getName();
471
                        try {
472
                                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
473
                                                va.getShapeCount(), true);
474
                        } catch (SpatialIndexException e) {
475
                                // if we cant build a file based spatial index, we'll build
476
                                // a pure memory spatial index
477
                                localCopy = new QuadtreeJts();
478
                        } catch (DriverIOException e) {
479
                                // TODO Auto-generated catch block
480
                                e.printStackTrace();
481
                        }
482

    
483
                }catch(Exception e){
484
                        e.printStackTrace();
485
                }//try
486
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
487
        try {
488
            for (int i=0; i < va.getShapeCount(); i++)
489
            {
490
                    if(cancelMonitor != null){
491
                            if(cancelMonitor.isCanceled())
492
                                    return;
493
                            cancelMonitor.reportStep();
494
                    }
495
                Rectangle2D r = shapeBounds.getShapeBounds(i);
496
                if(r != null)
497
                        localCopy.insert(r, i);
498
            } // for
499
            va.stop();
500
            if(localCopy instanceof IPersistentSpatialIndex)
501
                    ((IPersistentSpatialIndex) localCopy).flush();
502
            spatialIndex = localCopy;
503
        } catch (DriverIOException e) {
504
            // TODO Auto-generated catch block
505
            e.printStackTrace();
506
        } catch (IOException e) {
507
            // TODO Auto-generated catch block
508
            e.printStackTrace();
509
        }
510
    }
511

    
512
        /**
513
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#createIndex()
514
         */
515
        public void createSpatialIndex() {
516
                createSpatialIndex(null);
517
        }
518

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

    
529
        /**
530
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor)
531
         */
532
        public void process(FeatureVisitor visitor) throws DriverException,
533
                        VisitException {
534
                Strategy s = StrategyManager.getStrategy(this);
535
                s.process(visitor);
536
        }
537

    
538
        /**
539
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor,
540
         *      Rectangle2D)
541
         */
542
        public void process(FeatureVisitor visitor, Rectangle2D rect)
543
                        throws DriverException, VisitException {
544
                Strategy s = StrategyManager.getStrategy(this);
545
                s.process(visitor, rect);
546
        }
547

    
548
        /**
549
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#setSelection(com.iver.cit.gvsig.fmap.operations.selection.VectorialSubSet)
550
         */
551
        /*
552
         * public void setSelection(FBitSet selection) { try {
553
         * getRecordset().setSelection(selection); } catch (DriverException e) { //
554
         * TODO Auto-generated catch block e.printStackTrace(); }
555
         * fireSelectionEvents(); }
556
         */
557
        /**
558
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#isSelected(int)
559
         */
560
        /*
561
         * public boolean isSelected(int index) { try { return
562
         * getRecordset().isSelected(index); } catch (DriverException e) { // TODO
563
         * Auto-generated catch block e.printStackTrace(); } return false; }
564
         */
565
        /**
566
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getSelection()
567
         */
568
        /*
569
         * public FBitSet getSelection() { try { return
570
         * getRecordset().getSelection(); } catch (DriverException e) { // TODO
571
         * Auto-generated catch block e.printStackTrace(); } return new FBitSet(); }
572
         */
573
        /**
574
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#clearSelection()
575
         */
576
        /*
577
         * public void clearSelection() { try { getRecordset().clearSelection(); }
578
         * catch (DriverException e) { // TODO Auto-generated catch block
579
         * e.printStackTrace(); } }
580
         */
581

    
582
        /*
583
         * (non-Javadoc)
584
         *
585
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#queryByRect(java.awt.geom.Rectangle2D)
586
         */
587
        public FBitSet queryByRect(Rectangle2D rect) throws DriverException {
588
                Strategy s = StrategyManager.getStrategy(this);
589

    
590
                return s.queryByRect(rect);
591
        }
592

    
593
        public FBitSet queryByPoint(Point2D p, double tolerance)
594
                        throws DriverException {
595
                Strategy s = StrategyManager.getStrategy(this);
596
                return s.queryByPoint(p, tolerance);
597
        }
598

    
599
        public FBitSet queryByShape(IGeometry g, int relationship)
600
                        throws DriverException, VisitException {
601
                Strategy s = StrategyManager.getStrategy(this);
602
                return s.queryByShape(g, relationship);
603
        }
604

    
605
        public XMLItem[] getInfo(Point p, double tolerance) throws DriverException {
606
                Point2D pReal = this.getFMap().getViewPort().toMapPoint(p);
607
                FBitSet bs = queryByPoint(pReal, tolerance);
608
                VectorialXMLItem[] item = new VectorialXMLItem[1];
609
                item[0] = new VectorialXMLItem(bs, this);
610

    
611
                return item;
612
        }
613

    
614
        /**
615
         * @throws DriverException
616
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getRecordset()
617
         */
618
        /*
619
         * public SelectableDataSource getRecordset() throws DriverException { if
620
         * (sds == null){ try { DataSource ds = getSource().getRecordset();
621
         *
622
         * if (ds == null) { return null; }
623
         *
624
         * sds = new SelectableDataSource(ds);
625
         * //sds.setSelectionSupport(selectionSupport);
626
         *
627
         * return sds; } catch (DriverLoadException e) { throw new
628
         * DriverException(e); } catch
629
         * (com.hardcode.gdbms.engine.data.driver.DriverException e) { throw new
630
         * DriverException(e); } } return sds; }
631
         */
632
        /**
633
         * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
634
         * forma, podr?s poner leyendas basadas en el nuevo recordset
635
         *
636
         * @param newSds
637
         * @throws DriverException
638
         * @throws FieldNotFoundException
639
         * @throws FieldNotFoundException
640
         */
641
        /*
642
         * public void setRecordset(SelectableDataSource newSds) throws
643
         * DriverException, FieldNotFoundException { sds = newSds;
644
         * //sds.setSelectionSupport(selectionSupport); legend.setDataSource(sds);
645
         * logger.debug("Recordset cambiado a " + sds.getName()); }
646
         */
647
        /**
648
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#setLegend(int,
649
         *      com.iver.cit.gvsig.fmap.rendering.Legend)
650
         */
651
        public void setLegend(VectorialLegend r) throws DriverException,
652
                        FieldNotFoundException {
653
                VectorialLegend oldLegend = legend;
654
                legend = r;
655

    
656
                try {
657
                        legend.setDataSource(getRecordset());
658

    
659
                        if (legend.getLabelField() != null) {
660
                                // sds.start();
661
                                // int idLabelField =
662
                                // getRecordset().getFieldIndexByName(legend.getLabelField());
663
                                createLabelLayer(getSource().getRecordset());
664
                                // sds.stop();
665
                        } else
666
                                removeLabels();
667
                } catch (DriverException e) {
668
                        throw new DriverException(e);
669
                } catch (FieldNotFoundException e) {
670
                        // TODO Auto-generated catch block
671
                        e.printStackTrace();
672
                } catch (DriverLoadException e) {
673
                        // TODO Auto-generated catch block
674
                        e.printStackTrace();
675
                }
676

    
677
                LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
678
                                oldLegend, legend);
679
                callLegendChanged(e);
680
        }
681

    
682
        /**
683
         * Devuelve la Leyenda de la capa.
684
         *
685
         * @return Leyenda.
686
         */
687
        public Legend getLegend() {
688
                return legend;
689
        }
690

    
691
        /**
692
         * Devuelve el tipo de shape que contiene la capa.
693
         *
694
         * @return tipo de shape.
695
         *
696
         * @throws DriverException
697
         */
698
        public int getShapeType() throws DriverException {
699
                if (typeShape == -1) {
700
                        try {
701
                                logger.debug("source.start()");
702
                                getSource().start();
703
                                typeShape = getSource().getShapeType();
704
                                logger.debug("source.stop()");
705
                                getSource().stop();
706
                        } catch (DriverIOException e) {
707
                                throw new DriverException(e);
708
                        }
709
                }
710

    
711
                return typeShape;
712
        }
713

    
714
        /**
715
         * @throws XMLException
716
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getProperties()
717
         */
718
        public XMLEntity getXMLEntity() throws XMLException {
719
                if (this.orgXMLEntity != null) {
720
                        return this.orgXMLEntity;
721
                }
722
                XMLEntity xml = super.getXMLEntity();
723
                xml.addChild(getLegend().getXMLEntity());
724
                try {
725
                        xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
726

    
727
                } catch (DriverException e1) {
728
                        e1.printStackTrace();
729
                        throw new XMLException(e1);
730
                }
731
                //Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
732
                ReadableVectorial rv=getSource();
733
                if (getSource() instanceof VectorialEditableAdapter) {
734
                        setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
735
                }
736
                if (getSource() instanceof VectorialFileAdapter) {
737
                        xml.putProperty("type", "vectorial");
738
                        xml.putProperty("file", ((VectorialFileAdapter) getSource())
739
                                        .getFile());
740
                        // try {
741
                        try {
742
                                xml.putProperty("recordset-name", getSource().getRecordset()
743
                                                .getName());
744
                        } catch (DriverLoadException e) {
745
                                // TODO Auto-generated catch block
746
                                e.printStackTrace();
747
                        }
748
                        // } catch (DriverException e) {
749
                        // throw new XMLException(e);
750
                        // }
751
                } else if (source instanceof VectorialDBAdapter) {
752
                        xml.putProperty("type", "vectorial");
753

    
754
                        VectorialDatabaseDriver dbDriver = (VectorialDatabaseDriver) getSource()
755
                                        .getDriver();
756

    
757
                        // Guardamos el nombre del driver para poder recuperarlo
758
                        // con el DriverManager de Fernando.
759
                        xml.putProperty("db", dbDriver.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
                        xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
772
                                                                                                        // metido la leyenda y el
773
                                                                                                        // selection support
774
                } else if (source instanceof VectorialAdapter) {
775
                        // Se supone que hemos hecho algo gen?rico.
776
                        xml.putProperty("type", "vectorial");
777

    
778
                        VectorialDriver driver = (VectorialDriver) getSource().getDriver();
779

    
780
                        // Guardamos el nombre del driver para poder recuperarlo
781
                        // con el DriverManager de Fernando.
782
                        xml.putProperty("other", driver.getName());
783
                        // try {
784
                        try {
785
                                xml.putProperty("recordset-name", getSource().getRecordset()
786
                                                .getName());
787
                        } catch (DriverLoadException e) {
788
                                // TODO Auto-generated catch block
789
                                e.printStackTrace();
790
                        }
791
                        // } catch (DriverException e) {
792
                        // throw new XMLException(e);
793
                        // }
794
                        if (driver instanceof IPersistance) {
795
                                // xml.putProperty("className", driver.getClass().getName());
796
                                IPersistance persist = (IPersistance) driver;
797
                                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
798
                                                                                                                // hemos metido la
799
                                                                                                                // leyenda y el
800
                                                                                                                // selection support
801
                        }
802
                }
803
                setSource(rv);
804
                xml.putProperty("driverName", getSource().getDriver().getName());
805
                if (bHasJoin)
806
                        xml.putProperty("hasJoin", "true");
807

    
808
                return xml;
809
        }
810

    
811
        /**
812
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
813
         */
814
        public void setXMLEntity03(XMLEntity xml) throws XMLException {
815

    
816
                super.setXMLEntity(xml);
817
                legend = LegendFactory.createFromXML03(xml.getChild(0));
818

    
819
                try {
820
                        // legend.setDataSource(getRecordset());
821
                        setLegend(legend);
822
                } catch (FieldNotFoundException e) {
823
                        throw new XMLException(e);
824
                } catch (DriverException e) {
825
                        throw new XMLException(e);
826
                }
827

    
828
                try {
829
                        getRecordset().getSelectionSupport()
830
                                        .setXMLEntity03(xml.getChild(1));
831
                } catch (DriverException e) {
832
                        e.printStackTrace();
833
                }
834
        }
835

    
836
        /**
837
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
838
         */
839
        public void setXMLEntity(XMLEntity xml) throws XMLException {
840
                try {
841
                        super.setXMLEntity(xml);
842

    
843
                        VectorialLegend leg = LegendFactory.createFromXML(xml.getChild(0));
844
                        try {
845
                                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
846
                                String recordsetName = xml.getStringProperty("recordset-name");
847

    
848
                                LayerFactory.getDataSourceFactory().changeDataSourceName(
849
                                                getSource().getRecordset().getName(), recordsetName);
850
                                // Hacemos que el recordset que hemos creado antes (los
851
                                // recordset se crean antes que todo) sea el recordset
852
                                // de esta capa. Y del que se crea automaticamente
853
                                // en el setLegend del createLayer, nos olvidamos
854
                                SelectableDataSource sds = new SelectableDataSource(LayerFactory
855
                                                .getDataSourceFactory().createRandomDataSource(
856
                                                                recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
857
                                // sds.setSelectionSupport(selectionSupport);
858
                                // ((EditableAdapter)getSource()).setRecordSet(sds);
859
                        } catch (NoSuchTableException e1) {
860
                                this.setUnavailable(true);
861
                                throw new XMLException(e1);
862
                        } catch (com.hardcode.gdbms.engine.data.driver.DriverException e1) {
863
                                this.setUnavailable(true);
864
                                throw new XMLException(e1);
865
                        } catch (DriverLoadException e1) {
866
                                this.setUnavailable(true);
867
                                throw new XMLException(e1);
868
                        } catch (DriverException e1) {
869
                                this.setUnavailable(true);
870
                                throw new XMLException(e1);
871
                        }
872
                        // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
873
                        // el final
874
                        // de la lectura del proyecto
875
                        if (xml.contains("hasJoin")) {
876
                                setIsJoined(true);
877
                                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
878
                        } else {
879
                                try {
880
                                        // legend.setDataSource(getRecordset());
881
                                        setLegend(leg);
882
                                } catch (FieldNotFoundException e) {
883
                                        throw new XMLException(e);
884
                                } catch (DriverException e) {
885
                                        throw new XMLException(e);
886
                                }
887
                        }
888

    
889
                } catch (XMLException e) {
890
                        this.setUnavailable(true);
891
                        this.orgXMLEntity = xml;
892
                        //throw e;
893
                } catch (Exception e) {
894
                        this.setUnavailable(true);
895
                        this.orgXMLEntity = xml;
896
                        //throw new XMLException(e);
897
                }
898

    
899

    
900
        }
901

    
902
        /**
903
         * A?ade un LegendListener a la lista de Listeners.
904
         *
905
         * @param listener
906
         *            LegendListener.
907
         */
908
        public void addLegendListener(LegendListener listener) {
909
                layerChangeSupport.addLayerListener(listener);
910
        }
911

    
912
        /**
913
         * Llamada al m?todo callLegendChanged de los listener.
914
         *
915
         * @param e
916
         *            Evento.
917
         */
918
        private void callLegendChanged(LegendChangedEvent e) {
919
                layerChangeSupport.callLegendChanged(e);
920
        }
921

    
922
        /**
923
         * Borra un LegendListener de la lista de Listeners
924
         *
925
         * @param listener
926
         *            LegendListener.
927
         */
928
        public void removeLegendListener(LegendListener listener) {
929
                layerChangeSupport.removeLayerListener(listener);
930
        }
931

    
932
        /**
933
         * Sobreimplementaci?n del m?todo toString para que las bases de datos
934
         * identifiquen la capa.
935
         *
936
         * @return DOCUMENT ME!
937
         */
938
        public String toString() {
939
                /*
940
                 * Se usa internamente para que la parte de datos identifique de forma
941
                 * un?voca las tablas
942
                 */
943
                String ret = super.toString();
944

    
945
                return "layer" + ret.substring(ret.indexOf('@') + 1);
946
        }
947

    
948
        public boolean isJoined() {
949
                return bHasJoin;
950
        }
951

    
952
        /**
953
         * Returns if a layer is spatially indexed
954
         *
955
         * @return if this layer has the ability to proces spatial queries without
956
         *         secuential scans.
957
         */
958
        public boolean isSpatiallyIndexed() {
959
                ReadableVectorial source = getSource();
960
                if (source instanceof ISpatialDB)
961
                        return true;
962

    
963
//FIXME azabala
964
/*
965
 * Esto es muy dudoso, y puede cambiar.
966
 * Estoy diciendo que las que no son fichero o no son
967
 * BoundedShapes estan indexadas. Esto es mentira, pero
968
 * as? quien pregunte no querr? generar el indice.
969
 * Esta por ver si interesa generar el indice para capas
970
 * HSQLDB, WFS, etc.
971
 */
972
                if(!(source instanceof VectorialFileAdapter)){
973
                        return true;
974
                }
975
                if (!(source.getDriver() instanceof BoundedShapes)) {
976
                        return true;
977
                }
978

    
979
                if (getISpatialIndex() != null)
980
                        return true;
981
                return false;
982
        }
983

    
984
        public void setIsJoined(boolean hasJoin) {
985
                bHasJoin = hasJoin;
986
        }
987

    
988
        /**
989
         * @return Returns the spatialIndex.
990
         */
991
        public ISpatialIndex getISpatialIndex() {
992
                return spatialIndex;
993
        }
994
        /**
995
         * Sets the spatial index. This could be useful if, for some
996
         * reasons, you want to work with a distinct spatial index
997
         * (for example, a spatial index which could makes nearest
998
         * neighbour querys)
999
         * @param spatialIndex
1000
         */
1001
        public void setISpatialIndex(ISpatialIndex spatialIndex){
1002
                this.spatialIndex = spatialIndex;
1003
        }
1004

    
1005

    
1006
        /*
1007
         * public SelectableDataSource getRecordset() { try { return
1008
         * getSource().getRecordset(); } catch (DriverLoadException e) { // TODO
1009
         * Auto-generated catch block e.printStackTrace(); } return null; }
1010
         */
1011

    
1012
        /**
1013
         * @throws DriverException
1014
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getRecordset()
1015
         */
1016
        public SelectableDataSource getRecordset() throws DriverException {
1017
                if (this.isUnavailable()) return null;
1018
                if (sds == null) {
1019
                        try {
1020
                                SelectableDataSource ds = source.getRecordset();
1021

    
1022
                                if (ds == null) {
1023
                                        return null;
1024
                                }
1025

    
1026
                                sds = ds;
1027
                                sds.setSelectionSupport(selectionSupport);
1028

    
1029
                        } catch (DriverLoadException e) {
1030
                                throw new DriverException(e);
1031
                        }
1032
                }
1033
                return sds;
1034
        }
1035

    
1036
        /*
1037
         * (non-Javadoc)
1038
         *
1039
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setEditing(boolean)
1040
         */
1041
        public void setEditing(boolean b) throws EditionException {
1042
                super.setEditing(b);
1043
                try {
1044
                        if (b) {
1045
                                VectorialEditableAdapter vea = null;
1046
                                // TODO: Qu? pasa si hay m?s tipos de adapters?
1047
                                // FJP: Se podr?a pasar como argumento el
1048
                                // VectorialEditableAdapter
1049
                                // que se quiera usar para evitar meter c?digo aqu? de este
1050
                                // estilo.
1051
                                if (getSource() instanceof VectorialDBAdapter) {
1052
                                        vea = new VectorialEditableDBAdapter();
1053
                                } else if (this instanceof FLyrAnnotation) {
1054
                                        vea = new AnnotationEditableAdapter(
1055
                                                        (FLyrAnnotation) this);
1056
                                } else {
1057
                                        vea = new VectorialEditableAdapter();
1058
                                }
1059
                                vea.setOriginalVectorialAdapter(getSource());
1060

    
1061
                                // /vea.setSpatialIndex(getSpatialIndex());
1062
                                // /vea.setFullExtent(getFullExtent());
1063
                                vea.startEdition(EditionEvent.GRAPHIC);
1064
                                setSource(vea);
1065
                                getRecordset().setSelectionSupport(
1066
                                                vea.getOriginalAdapter().getRecordset()
1067
                                                                .getSelectionSupport());
1068

    
1069
                        } else {
1070
                                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1071
                                setSource(vea.getOriginalAdapter());
1072
                        }
1073
                        // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1074
                        // recordset
1075
                        setRecordset(getSource().getRecordset());
1076
                        if (getLegend() instanceof VectorialLegend) {
1077
                                VectorialLegend ley = (VectorialLegend) getLegend();
1078
                                ley.setDataSource(getSource().getRecordset());
1079
                                // Esto lo pongo para evitar que al dibujar sobre un
1080
                                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1081
                                // de la leyenda de textos "dibujar solo textos".
1082
                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1083
                                        FSymbol symbol=new FSymbol(getShapeType());
1084
                                        symbol.setFontSizeInPixels(false);
1085
                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1086
                                        Color color=symbol.getColor();
1087
                                        int alpha=symbol.getColor().getAlpha();
1088
                                        if (alpha>250) {
1089
                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1090
                                        }
1091
                                        ley.setDefaultSymbol(symbol);
1092
                                }
1093
                                ley.useDefaultSymbol(true);
1094
                        }
1095
                } catch (DriverLoadException e) {
1096
                        e.printStackTrace();
1097
                        throw new EditionException(e);
1098
                } catch (DriverException e) {
1099
                        e.printStackTrace();
1100
                        throw new EditionException(e);
1101
                } catch (FieldNotFoundException e) {
1102
                        e.printStackTrace();
1103
                        throw new EditionException(e);
1104
                }
1105

    
1106
                setSpatialCacheEnabled(b);
1107
                callEditionChanged(LayerEvent
1108
                                .createEditionChangedEvent(this, "edition"));
1109

    
1110
        }
1111

    
1112
        /**
1113
         * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1114
         * forma, podr?s poner leyendas basadas en el nuevo recordset
1115
         *
1116
         * @param newSds
1117
         */
1118
        public void setRecordset(SelectableDataSource newSds) {
1119
                sds = newSds;
1120
                sds.setSelectionSupport(selectionSupport);
1121
        }
1122
        /*
1123
         * public SelectionSupport getSelectionSupport() { return selectionSupport; }
1124
         *
1125
         * public void setSelectionSupport(SelectionSupport selectionSupport) {
1126
         * this.selectionSupport = selectionSupport; }
1127
         */
1128

    
1129
//        public SpatialCache createSpatialCache() {
1130
//               spatialCache = new SpatialCache();
1131
//                return spatialCache;
1132
//        }
1133
        public void clearSpatialCache()
1134
        {
1135
                spatialCache.clearAll();
1136
        }
1137

    
1138
//        public void setSpatialCache(SpatialCache spatialCache) {
1139
//                this.spatialCache = spatialCache;
1140
//        }
1141

    
1142
        public boolean isSpatialCacheEnabled() {
1143
                return spatialCacheEnabled;
1144
        }
1145

    
1146
        public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1147
                this.spatialCacheEnabled = spatialCacheEnabled;
1148
        }
1149

    
1150
        public SpatialCache getSpatialCache() {
1151
                return spatialCache;
1152
        }
1153

    
1154
        /**
1155
         * Siempre es un numero mayor de 1000
1156
         * @param maxFeatures
1157
         */
1158
        public void setMaxFeaturesInEditionCache(int maxFeatures) {
1159
                if (maxFeatures > spatialCache.maxFeatures)
1160
                        spatialCache.setMaxFeatures(maxFeatures);
1161

    
1162
        }
1163

    
1164
        /**
1165
         * This method returns a boolean that is used by the FPopMenu
1166
         * to make visible the properties menu or not. It is visible by
1167
         * default, and if a later don't have to show this menu only
1168
         * has to override this method.
1169
         * @return
1170
         * If the properties menu is visible (or not)
1171
         */
1172
        public boolean isPropertiesMenuVisible(){
1173
                return true;
1174
        }
1175

    
1176
}