Statistics
| Revision:

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

History | View | Annotate | Download (35.1 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

    
50
import javax.print.attribute.PrintRequestAttributeSet;
51

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

    
55
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
56
import com.hardcode.gdbms.engine.data.NoSuchTableException;
57
import com.hardcode.gdbms.engine.data.driver.DriverException;
58
import com.hardcode.gdbms.engine.instruction.FieldNotFoundException;
59
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
60
import com.iver.cit.gvsig.exceptions.layers.LegendLayerException;
61
import com.iver.cit.gvsig.exceptions.layers.ReloadLayerException;
62
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
63
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
64
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
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.ILabelable;
68
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
69
import com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver;
70
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
71
import com.iver.cit.gvsig.fmap.drivers.WithDefaultLegend;
72
import com.iver.cit.gvsig.fmap.edition.AnnotationEditableAdapter;
73
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
74
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
75
import com.iver.cit.gvsig.fmap.edition.IWriteable;
76
import com.iver.cit.gvsig.fmap.edition.IWriter;
77
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
78
import com.iver.cit.gvsig.fmap.edition.VectorialEditableDBAdapter;
79
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
80
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
81
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
82
import com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData;
83
import com.iver.cit.gvsig.fmap.layers.layerOperations.SingleLayer;
84
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData;
85
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialXMLItem;
86
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
87
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
88
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
89
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
90
import com.iver.cit.gvsig.fmap.rendering.Legend;
91
import com.iver.cit.gvsig.fmap.rendering.LegendChangedEvent;
92
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
93
import com.iver.cit.gvsig.fmap.rendering.SingleSymbolLegend;
94
import com.iver.cit.gvsig.fmap.rendering.VectorialLegend;
95
import com.iver.cit.gvsig.fmap.rendering.styling.AttrInTableLabeling;
96
import com.iver.cit.gvsig.fmap.rendering.styling.ILabelingStrategy;
97
import com.iver.cit.gvsig.fmap.rendering.styling.LabelingFactory;
98
import com.iver.cit.gvsig.fmap.spatialindex.IPersistentSpatialIndex;
99
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
100
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeGt2;
101
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
102
import com.iver.cit.gvsig.fmap.spatialindex.SpatialIndexException;
103
import com.iver.utiles.FileUtils;
104
import com.iver.utiles.IPersistance;
105
import com.iver.utiles.NotExistInXMLEntity;
106
import com.iver.utiles.PostProcessSupport;
107
import com.iver.utiles.XMLEntity;
108
import com.iver.utiles.swing.threads.Cancellable;
109
import com.iver.utiles.swing.threads.CancellableMonitorable;
110

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

    
117
// TODO Cuando no sea para pruebas debe no ser public
118
public class FLyrVect extends FLyrDefault implements ILabelable,
119
                ClassifiableVectorial, SingleLayer, VectorialData, RandomVectorialData,
120
                AlphanumericData, InfoByPoint {
121
        private static Logger logger = Logger.getLogger(FLyrVect.class.getName());
122

    
123
        /** Leyenda de la capa vectorial */
124
        private VectorialLegend legend;
125
        private int typeShape = -1;
126
        private LayerChangeSupport layerChangeSupport = new LayerChangeSupport();
127
        private ReadableVectorial source;
128
        private SelectableDataSource sds;
129
        private SelectionSupport selectionSupport = new SelectionSupport();
130
        private SpatialCache spatialCache = new SpatialCache();
131
        private boolean spatialCacheEnabled = false;
132

    
133
        /**
134
         * An implementation of gvSIG spatial index
135
         */
136
        protected ISpatialIndex spatialIndex = null;
137
        private boolean bHasJoin = false;
138
        private XMLEntity orgXMLEntity = null;
139
        private XMLEntity loadSelection = null;
140
        private VectorialLegend loadLegend = null;
141

    
142
        /**
143
         * Devuelve el VectorialAdapater de la capa.
144
         *
145
         * @return VectorialAdapter.
146
         */
147
        public ReadableVectorial getSource() {
148
                if (!this.isAvailable()) return null;
149
                return source;
150
        }
151

    
152
        /**
153
         * If we use a persistent spatial index associated with this layer, and the
154
         * index is not intrisic to the layer (for example spatial databases) this
155
         * method looks for existent spatial index, and loads it.
156
         *
157
         */
158
        private void loadSpatialIndex() {
159
                //FIXME: Al abrir el indice en fichero...
160
                //?C?mo lo liberamos? un metodo Layer.shutdown()
161

    
162

    
163
                ReadableVectorial source = getSource();
164
                //REVISAR QUE PASA CON LOS DRIVERS DXF, DGN, etc.
165
                //PUES SON VECTORIALFILEADAPTER
166
                if (!(source instanceof VectorialFileAdapter)) {
167
                        // we are not interested in db adapters
168
                        return;
169
                }
170
                VectorialDriver driver = source.getDriver();
171
                if (!(driver instanceof BoundedShapes)) {
172
                        // we dont spatially index layers that are not bounded
173
                        return;
174
                }
175
                File file = ((VectorialFileAdapter) source).getFile();
176
                String fileName = file.getAbsolutePath();
177
                File sptFile = new File(fileName + ".qix");
178
                if (!sptFile.exists() || (!(sptFile.length() > 0))) {
179
                        // before to exit, look for it in temp path
180
                        String tempPath = System.getProperty("java.io.tmpdir");
181
                        fileName = tempPath + File.separator + sptFile.getName();
182
                        sptFile = new File(fileName);
183
                        // it doesnt exists, must to create
184
                        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
185
                                return;
186
                        }// if
187
                }// if
188

    
189
                try {
190
                        source.start();
191
                        spatialIndex = new QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
192
                                        "NM", source.getFullExtent(), source.getShapeCount(), false);
193
                        source.setSpatialIndex(spatialIndex);
194
                } catch (SpatialIndexException e) {
195
                        spatialIndex = null;
196
                        e.printStackTrace();
197
                        return;
198
                } catch (ReadDriverException e) {
199
                        spatialIndex = null;
200
                        e.printStackTrace();
201
                        return;
202
                } catch (ExpansionFileReadException e) {
203
                        spatialIndex = null;
204
                        e.printStackTrace();
205
                        return;
206
                }
207

    
208
        }
209

    
210
        /**
211
         * Checks if it has associated an external spatial index
212
         * (an spatial index file).
213
         *
214
         * It looks for it in main file path, or in temp system path.
215
         * If main file is rivers.shp, it looks for a file called
216
         * rivers.shp.qix.
217

218
         * @return
219
         */
220
        public boolean isExternallySpatiallyIndexed() {
221
                /*
222
                 * FIXME (AZABALA): Independizar del tipo de fichero de ?ndice
223
                  * con el que se trabaje (ahora mismo considera la extension .qix,
224
             * pero esto depender? del tipo de ?ndice)
225
                 * */
226
                ReadableVectorial source = getSource();
227
                if (!(source instanceof VectorialFileAdapter)) {
228
                        // we are not interested in db adapters.
229
                        // think in non spatial dbs, like HSQLDB
230
                        return false;
231
                }
232
                File file = ((VectorialFileAdapter) source).getFile();
233
                String fileName = file.getAbsolutePath();
234
                File sptFile = new File(fileName + ".qix");
235
                if (!sptFile.exists() || (!(sptFile.length() > 0))) {
236
                        // before to exit, look for it in temp path
237
                        // it doesnt exists, must to create
238
                        String tempPath = System.getProperty("java.io.tmpdir");
239
                        fileName = tempPath + File.separator + sptFile.getName();
240
                        sptFile = new File(fileName);
241
                        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
242
                                return false;
243
                        }// if
244
                }// if
245
                return true;
246
        }
247

    
248
        /**
249
         * Inserta el VectorialAdapter a la capa.
250
         *
251
         * @param va
252
         *            VectorialAdapter.
253
         */
254
        public void setSource(ReadableVectorial rv) {
255
                source = rv;
256
                // azabala: we check if this layer could have a file spatial index
257
                // and load it if it exists
258
                loadSpatialIndex();
259
        }
260

    
261
        public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
262
                        Rectangle2D rAux;
263
                        source.start();
264
                        rAux = (Rectangle2D)source.getFullExtent().clone();
265
                        source.stop();
266

    
267
                        // Si existe reproyecci?n, reproyectar el extent
268
                        ICoordTrans ct = getCoordTrans();
269

    
270
                        if (ct != null) {
271
                                Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
272
                                Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
273
                                pt1 = ct.convert(pt1, null);
274
                                pt2 = ct.convert(pt2, null);
275
                                rAux = new Rectangle2D.Double();
276
                                rAux.setFrameFromDiagonal(pt1, pt2);
277
                        }
278

    
279
                        //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
280
                        if (rAux.getWidth()==0 && rAux.getHeight()==0) {
281
                                rAux=new Rectangle2D.Double(0,0,100,100);
282
                        }
283

    
284
                        return rAux;
285
        }
286

    
287
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
288
                        Cancellable cancel, double scale) throws ReadDriverException {
289

    
290
                if (isWithinScale(scale)) {
291
                        // Las que solo tienen etiquetado sin pintar el shape,
292
                        // no pasamos por ellas
293
                        boolean bDrawShapes = true;
294
                        if (legend instanceof SingleSymbolLegend) {
295
                                if (legend.getDefaultSymbol().isShapeVisible() == false)
296
                                        bDrawShapes = false;
297
                        }
298
                        if (bDrawShapes) {
299
                                Strategy strategy = StrategyManager.getStrategy(this);
300
                                try {
301
                                        prepareDrawing(image, g, viewPort);
302
                                        strategy.draw(image, g, viewPort, cancel);
303
                                } catch (ReadDriverException e) {
304
                                        this.setVisible(false);
305
                                        this.setActive(false);
306
                                        throw e;
307
                                }
308
                        }
309
                        if (getVirtualLayers() != null) {
310
                                getVirtualLayers().draw(image, g, viewPort, cancel, scale);
311
                        }
312
                }
313
        }
314

    
315
        /**
316
         * Se llama antes de empezar a pintar.
317
         * Es ?til para preparar la cache a emplear, las leyendas, etc.
318
         * @param image
319
         * @param g
320
         * @param viewPort
321
         */
322
        private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
323

    
324
        }
325

    
326
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
327
                        double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
328
                if (isVisible() && isWithinScale(scale)) {
329
                        Strategy strategy = StrategyManager.getStrategy(this);
330

    
331
                        strategy.print(g, viewPort, cancel, properties);
332
                        ILabelingStrategy labeling;
333
                        if ( (labeling = getLabelingStrategy() ) != null) {
334
                                // contains labels
335
                                labeling.print(g, viewPort, cancel, properties);
336
                        }
337
                }
338
        }
339

    
340
        public void deleteSpatialIndex() {
341
                //must we delete possible spatial indexes files?
342
                spatialIndex = null;
343
        }
344

    
345

    
346

    
347
   /**
348
    * <p>
349
    * Creates an spatial index associated to this layer.
350
    * The spatial index will used
351
    * the native projection of the layer, so if the layer is reprojected, it will
352
    * be ignored.
353
    * </p>
354
    * @param cancelMonitor instance of CancellableMonitorable that allows
355
    * to monitor progress of spatial index creation, and cancel the process
356
    */
357
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
358
             // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
359
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
360
        // para que acepten recorrer sin geometria, solo con rectangulos.
361

    
362
            //If this vectorial layer is based in a spatial database, the spatial
363
                //index is already implicit. We only will index file drivers
364
            ReadableVectorial va = getSource();
365
            //We must think in non spatial databases, like HSQLDB
366
                if(!(va instanceof VectorialFileAdapter)){
367
                        return;
368
                }
369
                if (!(va.getDriver() instanceof BoundedShapes)) {
370
                        return;
371
                }
372
                File file = ((VectorialFileAdapter) va).getFile();
373
                String fileName = file.getAbsolutePath();
374
                ISpatialIndex localCopy = null;
375
                try {
376
                        va.start();
377
                        localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
378
                                        va.getShapeCount(), true);
379

    
380
                } catch (SpatialIndexException e1) {
381
                        // Probably we dont have writing permissions
382
                        String directoryName = System.getProperty("java.io.tmpdir");
383
                        File newFile = new File(directoryName +
384
                                        File.separator +
385
                                        file.getName());
386
                        String newFileName = newFile.getName();
387
                        try {
388
                                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
389
                                                va.getShapeCount(), true);
390
                        } catch (SpatialIndexException e) {
391
                                // if we cant build a file based spatial index, we'll build
392
                                // a pure memory spatial index
393
                                localCopy = new QuadtreeJts();
394
                        } catch (ReadDriverException e) {
395
                                localCopy = new QuadtreeJts();
396
                        } catch (ExpansionFileReadException e) {
397
                                localCopy = new QuadtreeJts();
398
                        }
399

    
400
                }catch(Exception e){
401
                        e.printStackTrace();
402
                }//try
403
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
404
        try {
405
            for (int i=0; i < va.getShapeCount(); i++)
406
            {
407
                    if(cancelMonitor != null){
408
                            if(cancelMonitor.isCanceled())
409
                                    return;
410
                            cancelMonitor.reportStep();
411
                    }
412
                Rectangle2D r = shapeBounds.getShapeBounds(i);
413
                if(r != null)
414
                        localCopy.insert(r, i);
415
            } // for
416
            va.stop();
417
            if(localCopy instanceof IPersistentSpatialIndex)
418
                    ((IPersistentSpatialIndex) localCopy).flush();
419
            spatialIndex = localCopy;
420
            //vectorial adapter needs a reference to the spatial index, to solve
421
            //request for feature iteration based in spatial queries
422
            source.setSpatialIndex(spatialIndex);
423
        } catch (ReadDriverException e) {
424
                        // TODO Auto-generated catch block
425
                        e.printStackTrace();
426
                } catch (ExpansionFileReadException e) {
427
                        // TODO Auto-generated catch block
428
                        e.printStackTrace();
429
                }
430
    }
431

    
432
        public void createSpatialIndex() {
433
                createSpatialIndex(null);
434
        }
435

    
436
        public void process(FeatureVisitor visitor, FBitSet subset)
437
                        throws ReadDriverException, ExpansionFileReadException, VisitorException {
438
                Strategy s = StrategyManager.getStrategy(this);
439
                s.process(visitor, subset);
440
        }
441

    
442
        public void process(FeatureVisitor visitor) throws ReadDriverException, VisitorException {
443
                Strategy s = StrategyManager.getStrategy(this);
444
                s.process(visitor);
445
        }
446

    
447
        public void process(FeatureVisitor visitor, Rectangle2D rect)
448
                        throws ReadDriverException, ExpansionFileReadException, VisitorException {
449
                Strategy s = StrategyManager.getStrategy(this);
450
                s.process(visitor, rect);
451
        }
452

    
453
        public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
454
                Strategy s = StrategyManager.getStrategy(this);
455

    
456
                return s.queryByRect(rect);
457
        }
458

    
459
        public FBitSet queryByPoint(Point2D p, double tolerance)
460
                        throws ReadDriverException, VisitorException {
461
                Strategy s = StrategyManager.getStrategy(this);
462
                return s.queryByPoint(p, tolerance);
463
        }
464

    
465
        public FBitSet queryByShape(IGeometry g, int relationship)
466
                        throws ReadDriverException, VisitorException {
467
                Strategy s = StrategyManager.getStrategy(this);
468
                return s.queryByShape(g, relationship);
469
        }
470

    
471
        public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
472
                Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
473
                FBitSet bs = queryByPoint(pReal, tolerance);
474
                VectorialXMLItem[] item = new VectorialXMLItem[1];
475
                item[0] = new VectorialXMLItem(bs, this);
476

    
477
                return item;
478
        }
479

    
480
        public void setLegend(VectorialLegend r) throws LegendLayerException {
481
                VectorialLegend oldLegend = legend;
482
                legend = r;
483
                try {
484
                        legend.setDataSource(getRecordset());
485
                } catch (FieldNotFoundException e1) {
486
                        throw new LegendLayerException(getName(),e1);
487
                } catch (ReadDriverException e1) {
488
                        throw new LegendLayerException(getName(),e1);
489
                }
490
                LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
491
                                oldLegend, legend);
492
                callLegendChanged(e);
493
        }
494

    
495
        /**
496
         * Devuelve la Leyenda de la capa.
497
         *
498
         * @return Leyenda.
499
         */
500
        public Legend getLegend() {
501
                return legend;
502
        }
503

    
504
        /**
505
         * Devuelve el tipo de shape que contiene la capa.
506
         *
507
         * @return tipo de shape.
508
         *
509
         * @throws DriverException
510
         */
511
        public int getShapeType() throws ReadDriverException {
512
                if (typeShape == -1) {
513
                        getSource().start();
514
                        typeShape = getSource().getShapeType();
515
                        getSource().stop();
516
                }
517

    
518
                return typeShape;
519
        }
520

    
521
        public XMLEntity getXMLEntity() throws XMLException {
522
                if (!this.isAvailable() && this.orgXMLEntity != null) {
523
                        return this.orgXMLEntity;
524
                }
525
                XMLEntity xml = super.getXMLEntity();
526
                xml.addChild(getLegend().getXMLEntity());
527
                try {
528
                        xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
529

    
530
                } catch (ReadDriverException e1) {
531
                        e1.printStackTrace();
532
                        throw new XMLException(e1);
533
                }
534
                // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
535
                ReadableVectorial rv=getSource();
536
                if (getSource() instanceof VectorialEditableAdapter) {
537
                        setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
538
                }
539
                if (getSource() instanceof VectorialFileAdapter) {
540
                        xml.putProperty("type", "vectorial");
541
                        xml.putProperty("file", ((VectorialFileAdapter) getSource())
542
                                        .getFile());
543
                        try {
544
                                xml.putProperty("recordset-name", getSource().getRecordset()
545
                                                .getName());
546
                        } catch (ReadDriverException e) {
547
                                throw new XMLException(e);
548
                        }
549
                } else if (source instanceof VectorialDBAdapter) {
550
                        xml.putProperty("type", "vectorial");
551

    
552
                        VectorialDatabaseDriver dbDriver = (VectorialDatabaseDriver) getSource()
553
                                        .getDriver();
554

    
555
                        // Guardamos el nombre del driver para poder recuperarlo
556
                        // con el DriverManager de Fernando.
557
                        xml.putProperty("db", dbDriver.getName());
558
                        try {
559
                                xml.putProperty("recordset-name", getSource().getRecordset()
560
                                                .getName());
561
                        } catch (ReadDriverException e) {
562
                                throw new XMLException(e);
563
                        }
564
                        xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
565
                                                                                                        // metido la leyenda y el
566
                                                                                                        // selection support
567
                } else if (source instanceof VectorialAdapter) {
568
                        // Se supone que hemos hecho algo gen?rico.
569
                        xml.putProperty("type", "vectorial");
570

    
571
                        VectorialDriver driver = getSource().getDriver();
572

    
573
                        // Guardamos el nombre del driver para poder recuperarlo
574
                        // con el DriverManager de Fernando.
575
                        xml.putProperty("other", driver.getName());
576
                        // try {
577
                        try {
578
                                xml.putProperty("recordset-name", getSource().getRecordset()
579
                                                .getName());
580
                        } catch (ReadDriverException e) {
581
                                throw new XMLException(e);
582
                        }
583
                        if (driver instanceof IPersistance) {
584
                                // xml.putProperty("className", driver.getClass().getName());
585
                                IPersistance persist = (IPersistance) driver;
586
                                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
587
                                                                                                                // hemos metido la
588
                                                                                                                // leyenda y el
589
                                                                                                                // selection support
590
                        }
591
                }
592
                setSource(rv);
593
                xml.putProperty("driverName", getSource().getDriver().getName());
594
                if (bHasJoin)
595
                        xml.putProperty("hasJoin", "true");
596

    
597
                // properties from ILabelable
598
                xml.putProperty("isLabeled", isLabeled);
599
                if (strategy != null) {
600
                        XMLEntity strategyXML = strategy.getXMLEntity();
601
                        strategyXML.putProperty("Strategy", strategy.getClassName());
602
                        xml.addChild(strategy.getXMLEntity());
603
                }
604
                return xml;
605
        }
606

    
607
        /**
608
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
609
         */
610
        public void setXMLEntity03(XMLEntity xml) throws XMLException {
611

    
612
                super.setXMLEntity(xml);
613
                legend = LegendFactory.createFromXML03(xml.getChild(0));
614

    
615
                try {
616
                        setLegend(legend);
617
                } catch (LegendLayerException e) {
618
                        throw new XMLException(e);
619
                }
620

    
621
                try {
622
                        getRecordset().getSelectionSupport()
623
                                        .setXMLEntity03(xml.getChild(1));
624
                } catch (ReadDriverException e) {
625
                        e.printStackTrace();
626
                }
627
        }
628

    
629
        /*
630
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
631
         */
632
        public void setXMLEntity(XMLEntity xml) throws XMLException {
633
                try {
634
                        super.setXMLEntity(xml);
635
                        XMLEntity legendXML = xml.getChild(0);
636
                        VectorialLegend leg = LegendFactory.createFromXML(legendXML);
637
                        /* (jaume) begin patch;
638
                     * for backward compatibility purposes. Since gvSIG v1.1 labeling is
639
                     * no longer managed by the Legend but by the ILabelingStrategy. The
640
                     * following allows restoring older projects' labelings.
641
                     */
642
                        if (legendXML.contains("labelFieldName")) {
643
                            AttrInTableLabeling labeling = new AttrInTableLabeling();
644
                            labeling.setLayer(this);
645
                            labeling.setTextField(legendXML.getStringProperty("labelFieldName"));
646
                            labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
647
                            labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
648
                            this.setLabelingStrategy(labeling);
649
                            this.setIsLabeled(true);
650
                      }
651
                    /* end patch */
652
                        try {
653
                                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
654
                                // JMVIVO: Esto sirve para algo????
655
                                String recordsetName = xml.getStringProperty("recordset-name");
656

    
657
                                LayerFactory.getDataSourceFactory().changeDataSourceName(
658
                                                getSource().getRecordset().getName(), recordsetName);
659
                        } catch (NoSuchTableException e1) {
660
                                this.setAvailable(false);
661
                                throw new XMLException(e1);
662
                        } catch (ReadDriverException e1) {
663
                                this.setAvailable(false);
664
                                throw new XMLException(e1);
665
                        }
666
                        // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
667
                        // el final
668
                        // de la lectura del proyecto
669
                        if (xml.contains("hasJoin")) {
670
                                setIsJoined(true);
671
                                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
672
                        } else {
673
                                try {
674

    
675
                                        setLegend(leg);
676
                                } catch (LegendLayerException e) {
677
                                        throw new XMLException(e);
678
                                }
679
                        }
680

    
681
                        // set properties for ILabelable
682
                        for (int i = 0; i < xml.getChildrenCount(); i++) {
683
                                try {
684
                                        if (xml.getChild(i).contains("Strategy")) {
685
                                                XMLEntity xmlStrategy = xml.getChild(i);
686
                                                this.strategy = LabelingFactory.createStrategyFromXML(xmlStrategy.getChild(0));
687
                                        }
688
                                } catch (NotExistInXMLEntity neXMLEX) {
689
                                        // no strategy was set, just continue;
690
                                        logger.warn("Reached what should be unreachable code");
691
                                }
692
                        }
693
                } catch (XMLException e) {
694
                        this.setAvailable(false);
695
                        this.orgXMLEntity = xml;
696
                } catch (Exception e) {
697
                        this.setAvailable(false);
698
                        this.orgXMLEntity = xml;
699

    
700
                }
701

    
702

    
703
        }
704

    
705
        public void setXMLEntityNew(XMLEntity xml) throws XMLException {
706
                try {
707
                        super.setXMLEntity(xml);
708

    
709
                        XMLEntity legendXML = xml.getChild(0);
710
                        VectorialLegend leg = LegendFactory.createFromXML(legendXML);
711
                        /* (jaume) begin patch;
712
                     * for backward compatibility purposes. Since gvSIG v1.1 labeling is
713
                     * no longer managed by the Legend but by the ILabelingStrategy. The
714
                     * following allows restoring older projects' labelings.
715
                     */
716
                    if (legendXML.contains("labelFieldHeight")) {
717
                            AttrInTableLabeling labeling = new AttrInTableLabeling();
718
                            labeling.setLayer(this);
719
                            labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
720
                            labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
721
                            this.setLabelingStrategy(labeling);
722
                            this.setIsLabeled(true);
723
                      }
724
                    /* end patch */
725
                        try {
726
                                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
727

    
728
                                this.setLoadSelection(xml.getChild(1));
729
                        } catch (ReadDriverException e1) {
730
                                this.setAvailable(false);
731
                                throw new XMLException(e1);
732
                        }
733
                        // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
734
                        // el final
735
                        // de la lectura del proyecto
736
                        if (xml.contains("hasJoin")) {
737
                                setIsJoined(true);
738
                                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
739
                        } else {
740
                                this.setLoadLegend(leg);
741
                        }
742

    
743
                } catch (XMLException e) {
744
                        this.setAvailable(false);
745
                        this.orgXMLEntity = xml;
746
                } catch (Exception e) {
747
                        this.setAvailable(false);
748
                        this.orgXMLEntity = xml;
749
                }
750

    
751

    
752
        }
753

    
754
        /**
755
         * A?ade un LegendListener a la lista de Listeners.
756
         *
757
         * @param listener
758
         *            LegendListener.
759
         */
760
        public void addLegendListener(LegendListener listener) {
761
                layerChangeSupport.addLayerListener(listener);
762
        }
763

    
764
        /**
765
         * Llamada al m?todo callLegendChanged de los listener.
766
         *
767
         * @param e
768
         *            Evento.
769
         */
770
        private void callLegendChanged(LegendChangedEvent e) {
771
                layerChangeSupport.callLegendChanged(e);
772
        }
773

    
774
        /**
775
         * Borra un LegendListener de la lista de Listeners
776
         *
777
         * @param listener
778
         *            LegendListener.
779
         */
780
        public void removeLegendListener(LegendListener listener) {
781
                layerChangeSupport.removeLayerListener(listener);
782
        }
783

    
784
        /**
785
         * Sobreimplementaci?n del m?todo toString para que las bases de datos
786
         * identifiquen la capa.
787
         *
788
         * @return DOCUMENT ME!
789
         */
790
        public String toString() {
791
                /*
792
                 * Se usa internamente para que la parte de datos identifique de forma
793
                 * un?voca las tablas
794
                 */
795
                String ret = super.toString();
796

    
797
                return "layer" + ret.substring(ret.indexOf('@') + 1);
798
        }
799

    
800
        public boolean isJoined() {
801
                return bHasJoin;
802
        }
803

    
804
        /**
805
         * Returns if a layer is spatially indexed
806
         *
807
         * @return if this layer has the ability to proces spatial queries without
808
         *         secuential scans.
809
         */
810
        public boolean isSpatiallyIndexed() {
811
                ReadableVectorial source = getSource();
812
                if (source instanceof ISpatialDB)
813
                        return true;
814

    
815
//FIXME azabala
816
/*
817
 * Esto es muy dudoso, y puede cambiar.
818
 * Estoy diciendo que las que no son fichero o no son
819
 * BoundedShapes estan indexadas. Esto es mentira, pero
820
 * as? quien pregunte no querr? generar el indice.
821
 * Esta por ver si interesa generar el indice para capas
822
 * HSQLDB, WFS, etc.
823
 */
824
                if(!(source instanceof VectorialFileAdapter)){
825
                        return true;
826
                }
827
                if (!(source.getDriver() instanceof BoundedShapes)) {
828
                        return true;
829
                }
830

    
831
                if (getISpatialIndex() != null)
832
                        return true;
833
                return false;
834
        }
835

    
836
        public void setIsJoined(boolean hasJoin) {
837
                bHasJoin = hasJoin;
838
        }
839

    
840
        /**
841
         * @return Returns the spatialIndex.
842
         */
843
        public ISpatialIndex getISpatialIndex() {
844
                return spatialIndex;
845
        }
846
        /**
847
         * Sets the spatial index. This could be useful if, for some
848
         * reasons, you want to work with a distinct spatial index
849
         * (for example, a spatial index which could makes nearest
850
         * neighbour querys)
851
         * @param spatialIndex
852
         */
853
        public void setISpatialIndex(ISpatialIndex spatialIndex){
854
                this.spatialIndex = spatialIndex;
855
        }
856

    
857
        public SelectableDataSource getRecordset() throws ReadDriverException {
858
                if (!this.isAvailable()) return null;
859
                if (sds == null) {
860

    
861
                                SelectableDataSource ds = source.getRecordset();
862

    
863
                                if (ds == null) {
864
                                        return null;
865
                                }
866

    
867
                                sds = ds;
868
                                sds.setSelectionSupport(selectionSupport);
869

    
870
                }
871
                return sds;
872
        }
873
        
874
        public void setEditing(boolean b) throws StartEditionLayerException {
875
                super.setEditing(b);
876
                try {
877
                        if (b) {
878
                                VectorialEditableAdapter vea = null;
879
                                // TODO: Qu? pasa si hay m?s tipos de adapters?
880
                                // FJP: Se podr?a pasar como argumento el
881
                                // VectorialEditableAdapter
882
                                // que se quiera usar para evitar meter c?digo aqu? de este
883
                                // estilo.
884
                                if (getSource() instanceof VectorialDBAdapter) {
885
                                        vea = new VectorialEditableDBAdapter();
886
                                } else if (this instanceof FLyrAnnotation) {
887
                                        vea = new AnnotationEditableAdapter(
888
                                                        (FLyrAnnotation) this);
889
                                } else {
890
                                        vea = new VectorialEditableAdapter();
891
                                }
892
                                vea.setOriginalVectorialAdapter(getSource());
893
//                                azo: implementations of readablevectorial need
894
                                //references of projection and spatial index
895
                                vea.setProjection(getProjection());
896
                                vea.setSpatialIndex(spatialIndex);
897
                                
898
                                
899
                                // /vea.setSpatialIndex(getSpatialIndex());
900
                                // /vea.setFullExtent(getFullExtent());
901
                                vea.startEdition(EditionEvent.GRAPHIC);
902
                                setSource(vea);
903
                                getRecordset().setSelectionSupport(
904
                                                vea.getOriginalAdapter().getRecordset()
905
                                                                .getSelectionSupport());
906

    
907
                        } else {
908
                                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
909
                                setSource(vea.getOriginalAdapter());
910
                        }
911
                        // Si tenemos una leyenda, hay que pegarle el cambiazo a su
912
                        // recordset
913
                        setRecordset(getSource().getRecordset());
914
                        if (getLegend() instanceof VectorialLegend) {
915
                                VectorialLegend ley = (VectorialLegend) getLegend();
916
                                ley.setDataSource(getSource().getRecordset());
917
                                // Esto lo pongo para evitar que al dibujar sobre un
918
                                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
919
                                // de la leyenda de textos "dibujar solo textos".
920
//jaume
921
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
922
//                                        FSymbol symbol=new FSymbol(getShapeType());
923
//                                        symbol.setFontSizeInPixels(false);
924
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
925
//                                        Color color=symbol.getColor();
926
//                                        int alpha=symbol.getColor().getAlpha();
927
//                                        if (alpha>250) {
928
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
929
//                                        }
930
//                                        ley.setDefaultSymbol(symbol);
931
//                                }
932
//jaume//
933
                                ley.useDefaultSymbol(true);
934
                        }
935
                } catch (ReadDriverException e) {
936
                        throw new StartEditionLayerException(getName(),e);
937
                } catch (FieldNotFoundException e) {
938
                        throw new StartEditionLayerException(getName(),e);
939
                } catch (StartWriterVisitorException e) {
940
                        throw new StartEditionLayerException(getName(),e);
941
                }
942

    
943
                setSpatialCacheEnabled(b);
944
                callEditionChanged(LayerEvent
945
                                .createEditionChangedEvent(this, "edition"));
946

    
947
        }
948

    
949
        /**
950
         * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
951
         * forma, podr?s poner leyendas basadas en el nuevo recordset
952
         *
953
         * @param newSds
954
         */
955
        public void setRecordset(SelectableDataSource newSds) {
956
                sds = newSds;
957
                sds.setSelectionSupport(selectionSupport);
958
        }
959

    
960
        public void clearSpatialCache()
961
        {
962
                spatialCache.clearAll();
963
        }
964

    
965
        public boolean isSpatialCacheEnabled() {
966
                return spatialCacheEnabled;
967
        }
968

    
969
        public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
970
                this.spatialCacheEnabled = spatialCacheEnabled;
971
        }
972

    
973
        public SpatialCache getSpatialCache() {
974
                return spatialCache;
975
        }
976

    
977
        /**
978
         * Siempre es un numero mayor de 1000
979
         * @param maxFeatures
980
         */
981
        public void setMaxFeaturesInEditionCache(int maxFeatures) {
982
                if (maxFeatures > spatialCache.maxFeatures)
983
                        spatialCache.setMaxFeatures(maxFeatures);
984

    
985
        }
986

    
987
        /**
988
         * This method returns a boolean that is used by the FPopMenu
989
         * to make visible the properties menu or not. It is visible by
990
         * default, and if a later don't have to show this menu only
991
         * has to override this method.
992
         * @return
993
         * If the properties menu is visible (or not)
994
         */
995
        public boolean isPropertiesMenuVisible(){
996
                return true;
997
        }
998

    
999
        public void reload() throws ReloadLayerException {
1000
                this.setAvailable(true);
1001
                super.reload();
1002
                try {
1003
                        this.source.getDriver().reload();
1004
                        if (this.getLegend() == null) {
1005
                    if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1006
                        WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1007
                        this.setLegend((VectorialLegend) aux.getDefaultLegend());
1008
                        this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1009
                    } else {
1010
                        this.setLegend(LegendFactory.createSingleSymbolLegend(
1011
                                this.getShapeType()));
1012
                    }
1013
                        }
1014

    
1015
                } catch (LegendLayerException e) {
1016
                        this.setAvailable(false);
1017
                        throw new ReloadLayerException(getName(),e);
1018
                } catch (ReadDriverException e) {
1019
                        this.setAvailable(false);
1020
                        throw new ReloadLayerException(getName(),e);
1021
                }
1022

    
1023
        }
1024

    
1025
        protected void setLoadSelection(XMLEntity xml) {
1026
                this.loadSelection = xml;
1027
        }
1028

    
1029
        protected void setLoadLegend(VectorialLegend legend) {
1030
                this.loadLegend = legend;
1031
        }
1032

    
1033
        protected void putLoadSelection() throws XMLException {
1034
                if (this.loadSelection == null) return;
1035
                try {
1036
                        this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1037
                } catch (ReadDriverException e) {
1038
                        throw new XMLException(e);
1039
                }
1040
                this.loadSelection = null;
1041

    
1042
        }
1043
        protected void putLoadLegend() throws LegendLayerException {
1044
                if (this.loadLegend == null) return;
1045
                this.setLegend(this.loadLegend);
1046
                this.loadLegend = null;
1047
        }
1048

    
1049
        protected void cleanLoadOptions() {
1050
                this.loadLegend = null;
1051
                this.loadSelection = null;
1052
        }
1053

    
1054
        public boolean isWritable() {
1055
                VectorialDriver drv = getSource().getDriver();
1056
                if (!drv.isWritable())
1057
                        return false;
1058
                if (drv instanceof IWriteable)
1059
                {
1060
                        IWriter writer = ((IWriteable)drv).getWriter();
1061
                        if (writer != null)
1062
                        {
1063
                                if (writer instanceof ISpatialWriter)
1064
                                        return true;
1065
                        }
1066
                }
1067
                return false;
1068

    
1069
        }
1070

    
1071
//        public void beforePrinting(PrintRequestAttributeSet properties) {
1072
//                VectorialLegend vl=(VectorialLegend)getLegend();
1073
//                if (vl instanceof ClassifiedLegendInfo) {
1074
//                        ClassifiedLegendInfo clsfLegend = (ClassifiedLegendInfo) vl;
1075
//                        IPrintable[] symbols=clsfLegend.getSymbols();
1076
//                        for (int i=0;i<symbols.length;i++) {
1077
//                                symbols[i].setPrintingProperties(properties);
1078
//                        }
1079
//                }
1080
//                if (vl.getDefaultSymbol()!=null) {
1081
//                        ((IPrintable)vl.getDefaultSymbol()).setPrintingProperties(properties);
1082
//                }
1083
//        }
1084
//
1085
//        public void afterPrinting() {
1086
//                VectorialLegend vl=(VectorialLegend)getLegend();
1087
//                if (vl instanceof ClassifiedLegendInfo) {
1088
//                        ClassifiedLegendInfo clsfLegend = (ClassifiedLegendInfo) vl;
1089
//                        IPrintable[] symbols=clsfLegend.getSymbols();
1090
//                        for (int i=0;i<symbols.length;i++) {
1091
//                                symbols[i].setPrintingProperties(null);
1092
//                        }
1093
//                }
1094
//                if (vl.getDefaultSymbol()!=null) {
1095
//                        ((IPrintable)vl.getDefaultSymbol()).setPrintingProperties(null);
1096
//                }
1097
//
1098
//        }
1099

    
1100
        public FLayer cloneLayer() throws Exception {
1101
                FLyrVect clonedLayer = new FLyrVect();
1102
                clonedLayer.setSource(getSource());
1103
                clonedLayer.setVisible(isVisible());
1104
                clonedLayer.setISpatialIndex(getISpatialIndex());
1105
                clonedLayer.setName(getName());
1106
                clonedLayer.setCoordTrans(getCoordTrans());
1107

    
1108
                clonedLayer.setLegend((VectorialLegend)getLegend());
1109

    
1110
                clonedLayer.setIsLabeled(isLabeled());
1111
                clonedLayer.setLabelingStrategy(getLabelingStrategy());
1112

    
1113
                return clonedLayer;
1114
        }
1115

    
1116
        /*
1117
         * jaume. Stuff from ILabeled.
1118
         */
1119
        private boolean isLabeled;
1120
        private ILabelingStrategy strategy;
1121

    
1122
        public boolean isLabeled() {
1123
                return isLabeled;
1124
        }
1125

    
1126
        public void setIsLabeled(boolean isLabeled) {
1127
                this.isLabeled = isLabeled;
1128
        }
1129

    
1130
        public ILabelingStrategy getLabelingStrategy() {
1131
                return strategy;
1132
        }
1133

    
1134
        public void setLabelingStrategy(ILabelingStrategy strategy) {
1135
                this.strategy = strategy;
1136
        }
1137

    
1138
        public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale) throws ReadDriverException {
1139
                if (isWithinScale(scale)) {
1140
                        strategy.draw(image, g, viewPort, cancel);
1141
                }
1142
        }
1143

    
1144
}