Statistics
| Revision:

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

History | View | Annotate | Download (21.3 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.geom.Point2D;
45
import java.awt.geom.Rectangle2D;
46
import java.awt.image.BufferedImage;
47
import java.io.IOException;
48
import java.util.ArrayList;
49
import java.util.BitSet;
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.DataSource;
56
import com.hardcode.gdbms.engine.data.DataSourceFactory;
57
import com.hardcode.gdbms.engine.data.NoSuchTableException;
58
import com.hardcode.gdbms.engine.instruction.FieldNotFoundException;
59
import com.hardcode.gdbms.engine.values.DoubleValue;
60
import com.hardcode.gdbms.engine.values.FloatValue;
61
import com.hardcode.gdbms.engine.values.NullValue;
62
import com.hardcode.gdbms.engine.values.NumericValue;
63
import com.hardcode.gdbms.engine.values.Value;
64
import com.iver.cit.gvsig.fmap.DriverException;
65
import com.iver.cit.gvsig.fmap.ViewPort;
66
import com.iver.cit.gvsig.fmap.core.IGeometry;
67
import com.iver.cit.gvsig.fmap.core.v02.FLabel;
68
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
69
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
70
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
71
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
72
import com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver;
73
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
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.Labelable;
77
import com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData;
78
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
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.operations.Cancellable;
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.utiles.IPersistance;
92
import com.iver.utiles.PostProcessSupport;
93
import com.iver.utiles.XMLEntity;
94
import com.vividsolutions.jts.geom.Coordinate;
95
import com.vividsolutions.jts.geom.Envelope;
96
import com.vividsolutions.jts.index.quadtree.Quadtree;
97

    
98

    
99
/**
100
 * Capa b?sica Vectorial.
101
 *
102
 * @author Fernando Gonz?lez Cort?s
103
 */
104

    
105
//TODO Cuando no sea para pruebas debe no ser public
106
public class FLyrVect extends FLyrDefault implements Labelable, Selectable,
107
        AlphanumericData, ClassifiableVectorial, SingleLayer, VectorialData,
108
        RandomVectorialData {
109
        private static Logger logger = Logger.getLogger(FLyrVect.class.getName());
110

    
111
        /** Leyenda de la capa vectorial */
112
        private VectorialLegend legend;
113
        private int typeShape = -1;
114
        private SelectionSupport selectionSupport = new SelectionSupport();
115
        private LayerChangeSupport layerChangeSupport = new LayerChangeSupport();
116
        private VectorialAdapter source;
117
        private SelectableDataSource sds;
118
    
119
    private Quadtree spatialIndex = null;
120
    
121
    private boolean bHasJoin = false;
122

    
123
        /**
124
         * A?ade un SelectionListener a la lista de listeners.
125
         *
126
         * @param listener SelectionListener.
127
         */
128
        public void addSelectionListener(SelectionListener listener) {
129
                selectionSupport.addSelectionListener(listener);
130
        }
131

    
132
        /**
133
         * Borra un selectionListener de la lista de listeners.
134
         *
135
         * @param listener SelectionListener
136
         */
137
        public void removeSelectionListener(SelectionListener listener) {
138
                selectionSupport.removeSelectionListener(listener);
139
        }
140

    
141
        /**
142
         * Cuando ocurre un evento de cambio en la selecci?n, ?ste puede ser uno de
143
         * una gran cantidad de eventos. Con el fin de no propagar todos estos
144
         * eventos, se realiza la propagaci?n de manera manual al final de la
145
         * "r?faga" de eventos
146
         */
147
        public void fireSelectionEvents() {
148
                selectionSupport.fireSelectionEvents();
149
        }
150

    
151
        /**
152
         * Devuelve el VectorialAdapater de la capa.
153
         *
154
         * @return VectorialAdapter.
155
         */
156
        public VectorialAdapter getSource() {
157
                return source;
158
        }
159

    
160
        /**
161
         * Inserta el VectorialAdapter a la capa.
162
         *
163
         * @param va VectorialAdapter.
164
         */
165
        public void setSource(VectorialAdapter va) {
166
                source = va;
167
        }
168

    
169
        /**
170
         * @see com.iver.cit.gvsig.fmap.layers.LayerOperations#getFullExtent()
171
         */
172
        public Rectangle2D getFullExtent() throws DriverException {
173
                try {
174
                        Rectangle2D rAux;
175
                        logger.debug("source.start()");
176
                        source.start();
177
                        rAux = source.getFullExtent();
178
                        logger.debug("source.stop()");
179
                        source.stop();
180

    
181
                        // Si existe reproyecci?n, reproyectar el extent
182
                        ICoordTrans ct = getCoordTrans();
183

    
184
                        if (ct != null) {
185
                                Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
186
                                Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
187
                                pt1 = ct.convert(pt1, null);
188
                                pt2 = ct.convert(pt2, null);
189
                                rAux = new Rectangle2D.Double();
190
                                rAux.setFrameFromDiagonal(pt1, pt2);
191
                        }
192

    
193
                        return rAux;
194
                } catch (DriverIOException e) {
195
                        throw new DriverException(e);
196
                }
197
        }
198

    
199
        /**
200
         * @see com.iver.cit.gvsig.fmap.layers.LayerOperations#draw(java.awt.image.BufferedImage,
201
         *                 java.awt.Graphics2D, com.iver.cit.gvsig.fmap.ViewPort)
202
         */
203
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
204
                Cancellable cancel,double scale) throws DriverException {
205
            
206
                if (isWithinScale(scale)){        
207
            // Las que solo tienen etiquetado sin pintar el shape,
208
            // no pasamos por ellas
209
            boolean bDrawShapes = true;
210
            if (legend instanceof SingleSymbolLegend)
211
            {
212
                if (legend.getDefaultSymbol().isShapeVisible() == false)
213
                    bDrawShapes = false;
214
            }
215
            if (bDrawShapes)
216
            {
217
                Strategy strategy = StrategyManager.getStrategy(this);    
218
                strategy.draw(image, g, viewPort, cancel);
219
            }
220
    
221
                    if (getVirtualLayers() != null) {
222
                            getVirtualLayers().draw(image, g, viewPort, cancel,scale);
223
                    }
224
    
225
                    if (getLayerText() != null) {
226
                            getLayerText().draw(image, g, viewPort, cancel,scale);
227
                    }
228
                }
229
        }
230

    
231
        /**
232
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
233
         *                 com.iver.cit.gvsig.fmap.ViewPort,
234
         *                 com.iver.cit.gvsig.fmap.operations.Cancellable)
235
         */
236
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,double scale)
237
                throws DriverException {
238
                if (isVisible() && isWithinScale(scale)){        
239
                Strategy strategy = StrategyManager.getStrategy(this);
240

    
241
                strategy.print(g, viewPort, cancel);
242

    
243
                if (getLayerText() != null) {
244
                        getLayerText().draw(null, g, viewPort, cancel,scale);
245
                }
246
                }
247
        }
248

    
249
        /**
250
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#createLabelLayer(int)
251
         */
252
        // public FLayer createLabelLayer(int fieldId) {
253
    public FLayer createLabelLayer(SelectableDataSource ds) {
254
                FLyrText layerText = null;
255
        try {
256
            layerText = new FLyrText();
257
                        layerText.setLegend((VectorialLegend) getLegend());
258
            layerText.createLabels(this);
259
                } catch (FieldNotFoundException e1) {
260
                        // TODO Auto-generated catch block
261
                        e1.printStackTrace();
262
                } catch (DriverException e1) {
263
                        // TODO Auto-generated catch block
264
                        e1.printStackTrace();
265
        }
266

    
267

    
268
                setLayerText(layerText);
269

    
270
                return layerText;
271
        }
272

    
273
        /**
274
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#removeLabels()
275
         */
276
        public void removeLabels() {
277
                setLayerText(null);
278
        }
279

    
280
        /* (non-Javadoc)
281
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#createIndex()
282
         */
283
        public void createSpatialIndex() {
284
        // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
285
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
286
        // para que acepten recorrer sin geometria, solo con rectangulos.
287
        spatialIndex = new Quadtree();
288
        VectorialAdapter va = getSource();
289
        ICoordTrans ct = getCoordTrans();
290
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
291
        try {
292
            va.start();
293

    
294
            for (int i=0; i < va.getShapeCount(); i++)
295
            {               
296
                Rectangle2D r = shapeBounds.getShapeBounds(i);
297
                // TODO: MIRAR COMO SE TRAGAR?A ESTO LO DE LAS REPROYECCIONES
298
                if (ct != null) {
299
                    r = ct.convert(r);
300
                }
301
                Coordinate c1 = new Coordinate(r.getMinX(), r.getMinY());
302
                Coordinate c2 = new Coordinate(r.getMaxX(), r.getMaxY());
303
                Envelope env = new Envelope(c1, c2);
304
                spatialIndex.insert(env, new Integer(i));
305
            } // for
306
            va.stop();
307
        } catch (DriverIOException e) {
308
            // TODO Auto-generated catch block
309
            e.printStackTrace();
310
        } catch (IOException e) {
311
            // TODO Auto-generated catch block
312
            e.printStackTrace();
313
        }
314
        
315
        }
316

    
317
        /**
318
         * @see com.iver.cit.gvsig.fmap.layers.VectorialOperations#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor,
319
         *                 FBitSet)
320
         */
321
        public void process(FeatureVisitor visitor, FBitSet subset)
322
                throws DriverException, VisitException {
323
                Strategy s = StrategyManager.getStrategy(this);
324
                s.process(visitor, subset);
325
        }
326

    
327
        /**
328
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData#process(com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor)
329
         */
330
        public void process(FeatureVisitor visitor)
331
                throws DriverException, VisitException {
332
                Strategy s = StrategyManager.getStrategy(this);
333
                s.process(visitor);
334
        }
335

    
336
        /**
337
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#setSelection(com.iver.cit.gvsig.fmap.operations.selection.VectorialSubSet)
338
         */
339
        public void setSelection(FBitSet selection) {
340
                selectionSupport.setSelection(selection);
341
                fireSelectionEvents();
342
        }
343

    
344
        /**
345
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#isSelected(int)
346
         */
347
        public boolean isSelected(int index) {
348
                return selectionSupport.isSelected(index);
349
        }
350

    
351
        /**
352
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getSelection()
353
         */
354
        public FBitSet getSelection() {
355
                return selectionSupport.getSelection();
356
        }
357

    
358
        /**
359
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#clearSelection()
360
         */
361
        public void clearSelection() {
362
                selectionSupport.clearSelection();
363
        }
364

    
365
        /* (non-Javadoc)
366
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData#queryByRect(java.awt.geom.Rectangle2D)
367
         */
368
        public FBitSet queryByRect(Rectangle2D rect) throws DriverException {
369
                Strategy s = StrategyManager.getStrategy(this);
370

    
371
                return s.queryByRect(rect);
372
        }
373

    
374
    public FBitSet queryByPoint(Point2D p, double tolerance) throws DriverException
375
    {
376
        Strategy s = StrategyManager.getStrategy(this);
377
        return s.queryByPoint(p, tolerance);       
378
    }
379
    
380
    public FBitSet queryByShape(IGeometry g, int relationship) throws DriverException, VisitException
381
    {
382
        Strategy s = StrategyManager.getStrategy(this);
383
        return s.queryByShape(g, relationship);        
384
    }
385
        /**
386
         * @throws DriverException
387
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#getRecordset()
388
         */
389
        public SelectableDataSource getRecordset() throws DriverException {
390
                if (sds == null){
391
                        try {
392
                                DataSource ds = source.getRecordset();
393

    
394
                                if (ds == null) {
395
                                        return null;
396
                                }
397

    
398
                                sds = new SelectableDataSource(ds);
399
                                sds.setSelectionSupport(selectionSupport);
400
                                
401
                                return sds;
402
                        } catch (DriverLoadException e) {
403
                                throw new DriverException(e);
404
                        } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
405
                                throw new DriverException(e);
406
            }
407
                }
408
                return sds;
409
        }
410
    
411
    /**
412
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo.
413
     * De esta forma, podr?s poner leyendas basadas en el nuevo
414
     * recordset
415
     * @param newSds
416
     * @throws DriverException 
417
     * @throws FieldNotFoundException 
418
     * @throws FieldNotFoundException 
419
     */
420
    public void setRecordset(SelectableDataSource newSds) throws DriverException, FieldNotFoundException
421
    {
422
        sds = newSds;
423
        sds.setSelectionSupport(selectionSupport);
424
        legend.setDataSource(sds);
425
        logger.debug("Recordset cambiado a " + sds.getName());
426
    }
427

    
428
        /**
429
         * @see com.iver.cit.gvsig.fmap.layers.CommonOperations#setLegend(int,
430
         *                 com.iver.cit.gvsig.fmap.rendering.Legend)
431
         */
432
        public void setLegend(VectorialLegend r)
433
                throws DriverException, FieldNotFoundException {
434
                VectorialLegend oldLegend = legend;
435
                legend = r;
436

    
437
                try {
438
                        legend.setDataSource(getRecordset());
439

    
440
                        if (legend.getLabelField() != null) {
441
                            // sds.start();
442
                                // int idLabelField = getRecordset().getFieldIndexByName(legend.getLabelField());
443
                                createLabelLayer(sds);
444
                                // sds.stop();
445
                        }
446
                        else
447
                            removeLabels();
448
                } catch (DriverException e) {
449
                        throw new DriverException(e);
450
                } catch (FieldNotFoundException e) {
451
                        // TODO Auto-generated catch block
452
                        e.printStackTrace();
453
        }
454

    
455
                LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, legend);
456
                callLegendChanged(e);
457
        }
458

    
459
        /**
460
         * Devuelve la Leyenda de la capa.
461
         *
462
         * @return Leyenda.
463
         */
464
        public Legend getLegend() {
465
                return legend;
466
        }
467

    
468
        /**
469
         * Devuelve el tipo de shape que contiene la capa.
470
         *
471
         * @return tipo de shape.
472
         *
473
         * @throws DriverException
474
         */
475
        public int getShapeType() throws DriverException {
476
                if (typeShape == -1) {
477
                        try {
478
                                logger.debug("source.start()");
479
                                source.start();
480
                                typeShape = source.getShapeType();
481
                                logger.debug("source.stop()");
482
                                source.stop();
483
                        } catch (DriverIOException e) {
484
                                throw new DriverException(e);
485
                        }
486
                }
487

    
488
                return typeShape;
489
        }
490

    
491
        /**
492
         * @throws XMLException
493
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getProperties()
494
         */
495
        public XMLEntity getXMLEntity() throws XMLException {
496
                XMLEntity xml = super.getXMLEntity();
497
        xml.addChild(legend.getXMLEntity());
498
        xml.addChild(selectionSupport.getXMLEntity());
499

    
500
                if (source instanceof VectorialFileAdapter) {
501
                        xml.putProperty("type", "vectorial");
502
                        xml.putProperty("file", ((VectorialFileAdapter) source).getFile());
503
                        try {
504
                                xml.putProperty("recordset-name", getRecordset().getName());
505
                        } catch (DriverException e) {
506
                                throw new XMLException(e);
507
                        }
508
                } else if (source instanceof VectorialDBAdapter) {
509
            xml.putProperty("type", "vectorial");
510
            
511
            VectorialDatabaseDriver dbDriver = (VectorialDatabaseDriver) source.getDriver();
512
            
513
            // Guardamos el nombre del driver para poder recuperarlo
514
            // con el DriverManager de Fernando.
515
            xml.putProperty("db", dbDriver.getName());            
516
            try {
517
                xml.putProperty("recordset-name", getRecordset().getName());
518
            } catch (DriverException e) {
519
                throw new XMLException(e);
520
            }
521
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos metido la leyenda y el selection support
522
        } else if (source instanceof VectorialAdapter) { 
523
            // Se supone que hemos hecho algo gen?rico.
524
            xml.putProperty("type", "vectorial");
525
            
526
            VectorialDriver driver = (VectorialDriver) source.getDriver();
527
            
528
            // Guardamos el nombre del driver para poder recuperarlo
529
            // con el DriverManager de Fernando.
530
            xml.putProperty("other", driver.getName());            
531
            try {
532
                xml.putProperty("recordset-name", getRecordset().getName());
533
            } catch (DriverException e) {
534
                throw new XMLException(e);
535
            }
536
            if (driver instanceof IPersistance)
537
            {
538
                // xml.putProperty("className", driver.getClass().getName());
539
                IPersistance persist = (IPersistance) driver;
540
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes hemos metido la leyenda y el selection support
541
            }
542
                } else if (source instanceof WFSAdapter) {
543
                }
544
                xml.putProperty("driverName", getSource().getDriver().getName());
545
        if (bHasJoin)
546
            xml.putProperty("hasJoin", "true");
547
        
548
        
549
                return xml;
550
        }
551

    
552
        /**
553
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
554
         */
555
        public void setXMLEntity03(XMLEntity xml)
556
                throws XMLException {
557
                
558
                super.setXMLEntity(xml);
559
                legend = LegendFactory.createFromXML03(xml.getChild(0));
560

    
561
                try {
562
                        // legend.setDataSource(getRecordset());
563
                        setLegend(legend);
564
                } catch (FieldNotFoundException e) {
565
                        throw new XMLException(e);
566
                } catch (DriverException e) {
567
                        throw new XMLException(e);
568
                }        
569

    
570
                selectionSupport.setXMLEntity03(xml.getChild(1));
571
        }
572

    
573
        /**
574
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
575
         */
576
        public void setXMLEntity(XMLEntity xml)
577
                throws XMLException {
578
        super.setXMLEntity(xml);
579
                
580
                legend = LegendFactory.createFromXML(xml.getChild(0));
581
                selectionSupport.setXMLEntity(xml.getChild(1));
582

    
583
                String recordsetName = xml.getStringProperty("recordset-name");
584
                try {
585
                        LayerFactory.getDataSourceFactory().changeDataSourceName(
586
                    getRecordset().getName(), recordsetName
587
                                        );
588
            // Hacemos que el recordset que hemos creado antes (los
589
            // recordset se crean antes que todo) sea el recordset
590
            // de esta capa. Y del que se crea automaticamente
591
            // en el setLegend del createLayer, nos olvidamos
592
            setRecordset(new SelectableDataSource(LayerFactory.getDataSourceFactory()
593
                        .createRandomDataSource(recordsetName, DataSourceFactory.AUTOMATIC_OPENING)));
594
                } catch (NoSuchTableException e1) {
595
                        throw new XMLException(e1);
596
                } catch (DriverException e1) {
597
                        throw new XMLException(e1);                
598
        } catch (com.hardcode.gdbms.engine.data.driver.DriverException e1) {
599
            throw new XMLException(e1);
600
        } catch (DriverLoadException e1) {
601
            throw new XMLException(e1);
602
        } catch (FieldNotFoundException e) {
603
            e.printStackTrace();
604
            throw new XMLException(e);
605
        }
606
        // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta el final
607
        // de la lectura del proyecto
608
        if (xml.contains("hasJoin"))
609
        {
610
            setIsJoined(true);
611
            PostProcessSupport.addToPostProcess(this,"setLegend", legend, 1);
612
        }
613
        else
614
        {
615
            try {
616
                // legend.setDataSource(getRecordset());
617
                setLegend(legend);
618
            } catch (FieldNotFoundException e) {
619
                throw new XMLException(e);
620
            } catch (DriverException e) {
621
                throw new XMLException(e);
622
            }   
623
        }       
624
        
625
        }
626

    
627
        /**
628
         * A?ade un LegendListener a la lista de Listeners.
629
         *
630
         * @param listener LegendListener.
631
         */
632
        public void addLegendListener(LegendListener listener) {
633
                layerChangeSupport.addLayerListener(listener);
634
        }
635

    
636
        /**
637
         * Llamada al m?todo callLegendChanged de los listener.
638
         *
639
         * @param e Evento.
640
         */
641
        private void callLegendChanged(LegendChangedEvent e) {
642
                layerChangeSupport.callLegendChanged(e);
643
        }
644

    
645
        /**
646
         * Borra un LegendListener de la lista de Listeners
647
         *
648
         * @param listener LegendListener.
649
         */
650
        public void removeLegendListener(LegendListener listener) {
651
                layerChangeSupport.removeLayerListener(listener);
652
        }
653

    
654
        /**
655
         * Sobreimplementaci?n del m?todo toString para que las bases de datos
656
         * identifiquen la capa.
657
         *
658
         * @return DOCUMENT ME!
659
         */
660
        public String toString() {
661
                /*
662
                 * Se usa internamente para que la parte de datos
663
                 * identifique de forma un?voca las tablas
664
                 */
665
                String ret = super.toString();
666

    
667
                return "layer" + ret.substring(ret.indexOf('@') + 1);
668
        }
669

    
670
    public boolean isJoined() {
671
        return bHasJoin;
672
    }
673

    
674
    public void setIsJoined(boolean hasJoin) {
675
        bHasJoin = hasJoin;
676
    }
677

    
678
    /**
679
     * @return Returns the spatialIndex.
680
     */
681
    public Quadtree getSpatialIndex() {
682
        return spatialIndex;
683
    }
684
}