Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / VectorialEditableAdapter.java @ 40328

History | View | Annotate | Download (34.4 KB)

1
/*
2
 * Created on 12-ene-2006 by fjp
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
 *
46
 * $Id: VectorialEditableAdapter.java 40328 2013-04-16 18:29:23Z fpuga $
47
 * $Log$
48
 * Revision 1.76  2007-09-19 16:25:04  jaume
49
 * ReadExpansionFileException removed from this context
50
 *
51
 * Revision 1.75  2007/07/25 06:52:08  caballero
52
 * reproject
53
 *
54
 * Revision 1.74  2007/06/22 10:52:30  caballero
55
 * start y stop
56
 *
57
 * Revision 1.73  2007/05/29 19:09:07  azabala
58
 * using of spatial index in spatial iteration now depends of the query area (to avoid using index in full scan queries)
59
 *
60
 * Revision 1.72  2007/05/07 09:02:47  caballero
61
 * editing memory
62
 *
63
 * Revision 1.71  2007/04/25 14:42:24  caballero
64
 * BoundShape
65
 *
66
 * Revision 1.70  2007/04/19 17:28:24  azabala
67
 * changes in ReadableVectorial interface (new iteration modes)
68
 *
69
 * Revision 1.69  2007/03/06 17:08:55  caballero
70
 * Exceptions
71
 *
72
 * Revision 1.68  2007/02/19 12:36:22  caballero
73
 * *** empty log message ***
74
 *
75
 * Revision 1.67  2007/02/13 11:31:08  caballero
76
 * optimizo cuando el cambio es alfanum?rico
77
 *
78
 * Revision 1.66  2007/02/12 08:53:37  caballero
79
 * FieldExpresion
80
 *
81
 * Revision 1.65  2007/02/08 12:03:07  caballero
82
 * comentar println
83
 *
84
 * Revision 1.64  2006/09/21 17:32:11  azabala
85
 * *** empty log message ***
86
 *
87
 * Revision 1.62  2006/08/10 08:20:31  caballero
88
 * flatness
89
 *
90
 * Revision 1.61  2006/07/20 13:03:07  fjp
91
 * nuevos campos
92
 *
93
 * Revision 1.60  2006/07/12 11:48:41  fjp
94
 * Draft to add, remove and delete fields
95
 *
96
 * Revision 1.59  2006/07/12 10:34:52  fjp
97
 * Draft to add, remove and delete fields
98
 *
99
 * Revision 1.58  2006/07/06 08:31:29  fjp
100
 * Draft to add, remove and delete fields
101
 *
102
 * Revision 1.57  2006/06/22 11:38:12  caballero
103
 * soluci?n error al borrar geometr?as
104
 *
105
 * Revision 1.56  2006/06/16 10:44:01  fjp
106
 * Por mandato de Vicente
107
 *
108
 * Revision 1.54  2006/06/01 16:15:16  fjp
109
 * Escritura que permite crear drivers de manera m?s sencilla.
110
 *
111
 * Revision 1.53  2006/05/30 13:03:41  fjp
112
 * setFlatness solo se debe aplicar a bases de datos espaciales.
113
 *
114
 * Revision 1.52  2006/05/24 09:29:30  caballero
115
 * a?adir flatness
116
 *
117
 * Revision 1.51  2006/05/16 16:07:19  fjp
118
 * snapping. Revisar
119
 *
120
 * Revision 1.50  2006/05/16 07:07:46  caballero
121
 * Modificar la geometr?a desde fuera
122
 *
123
 * Revision 1.49  2006/05/15 10:52:23  caballero
124
 * Saber si se realiza una operaci?n desde la vista o desde la tabla.
125
 *
126
 * Revision 1.48  2006/05/09 15:58:37  caballero
127
 * Para el IGN
128
 *
129
 * Revision 1.47  2006/05/09 10:28:28  caballero
130
 * faltaba controlar undo y redo
131
 *
132
 * Revision 1.46  2006/04/27 06:44:56  caballero
133
 * Soluci?n undo y redo de anotaciones
134
 *
135
 * Revision 1.45  2006/04/18 06:56:55  caballero
136
 * Cambiar VectorialAdapter por ReadableVectorial
137
 *
138
 * Revision 1.44  2006/04/12 17:13:39  fjp
139
 * *** empty log message ***
140
 *
141
 * Revision 1.43  2006/04/11 12:12:29  fjp
142
 * Con edici?n en PostGIS y guardando pseudo-arcos en los shapes.
143
 *
144
 * Revision 1.42  2006/04/11 06:53:20  fjp
145
 * Preparando el driver de escritura PostGIS
146
 *
147
 * Revision 1.41  2006/04/04 11:27:16  fjp
148
 * Consola escuchando bien y selecci?n en tabla sincronizada cuando hay edici?n
149
 *
150
 * Revision 1.40  2006/04/03 11:04:48  caballero
151
 * Posibilidad de a?adir una anotaci?n
152
 *
153
 * Revision 1.39  2006/03/29 06:26:37  caballero
154
 * acelerar con una imagen las herramientas
155
 *
156
 * Revision 1.38  2006/03/23 16:20:52  fjp
157
 * Un fallo un tanto inverosimil con el mapOverview
158
 *
159
 * Revision 1.37  2006/03/23 10:08:11  caballero
160
 * calculo del fullExtent recorriendo todas las geometr?as
161
 *
162
 * Revision 1.36  2006/03/22 11:46:29  caballero
163
 * Editar capa de anotaciones
164
 *
165
 * Revision 1.35  2006/02/28 18:15:22  fjp
166
 * Consola de CAD
167
 *
168
 * Revision 1.34  2006/02/24 11:30:32  fjp
169
 * FUNCIONA!!! (Creo)
170
 *
171
 * Revision 1.33  2006/02/24 07:57:58  fjp
172
 * FUNCIONA!!! (Creo)
173
 *
174
 * Revision 1.32  2006/02/23 17:55:45  fjp
175
 * Preparando para poder editar con el EditionManager
176
 *
177
 * Revision 1.31  2006/02/21 16:44:08  fjp
178
 * Preparando para poder editar con el EditionManager
179
 *
180
 * Revision 1.30  2006/02/20 18:14:59  fjp
181
 * Preparando para poder editar con el EditionManager
182
 *
183
 * Revision 1.29  2006/02/20 10:32:54  fjp
184
 * Preparando para poder editar con el EditionManager
185
 *
186
 * Revision 1.28  2006/02/17 13:40:03  fjp
187
 * Preparando para poder editar con el EditionManager
188
 *
189
 * Revision 1.27  2006/02/17 10:41:14  fjp
190
 * Evento de edici?n lanzado cuando una capa se pone en edici?n
191
 *
192
 * Revision 1.26  2006/02/17 08:21:19  fjp
193
 * *** empty log message ***
194
 *
195
 * Revision 1.25  2006/02/16 09:38:10  fjp
196
 * Preparando compatibilidad para bases de datos (y de paso, acelerando :-)
197
 *
198
 * Revision 1.24  2006/02/16 09:06:28  caballero
199
 * commandStack
200
 *
201
 * Revision 1.23  2006/02/15 18:16:02  fjp
202
 * POR TERMINAR
203
 *
204
 * Revision 1.22  2006/02/13 18:18:31  fjp
205
 * POR TERMINAR
206
 *
207
 * Revision 1.21  2006/02/10 13:28:23  caballero
208
 * poder cambiar la selecci?n
209
 *
210
 * Revision 1.20  2006/02/09 13:11:54  caballero
211
 * *** empty log message ***
212
 *
213
 * Revision 1.19  2006/02/08 16:45:29  caballero
214
 * elimnar c?dio no usado
215
 *
216
 * Revision 1.18  2006/02/08 15:18:45  caballero
217
 * control de las rows eliminadas
218
 *
219
 * Revision 1.17  2006/02/07 10:18:44  caballero
220
 * Con BoundedShape
221
 *
222
 * Revision 1.16  2006/02/06 12:01:41  caballero
223
 * driver del ova
224
 *
225
 * Revision 1.15  2006/02/03 14:09:32  fjp
226
 * Preparando edici?n
227
 *
228
 * Revision 1.14  2006/02/03 12:16:33  fjp
229
 * Preparando edici?n
230
 *
231
 * Revision 1.13  2006/02/03 11:54:12  caballero
232
 * tablas con vectorialEditableAdapter en edici?n
233
 *
234
 * Revision 1.11  2006/01/31 08:10:05  caballero
235
 * cambio de feature a row
236
 *
237
 * Revision 1.10  2006/01/30 08:18:14  caballero
238
 * m?todos para deshacer y rehacer
239
 *
240
 * Revision 1.9  2006/01/23 17:30:28  caballero
241
 * coger los datos del ova
242
 *
243
 * Revision 1.8  2006/01/23 16:16:16  caballero
244
 * getRowIndex
245
 *
246
 * Revision 1.7  2006/01/20 08:37:10  fjp
247
 * Preparando la edici?n
248
 *
249
 * Revision 1.6  2006/01/19 12:48:20  caballero
250
 * poder modificar su vectorial Adapter
251
 *
252
 * Revision 1.5  2006/01/19 09:28:11  fjp
253
 * Preparando la edici?n
254
 *
255
 * Revision 1.4  2006/01/17 10:24:02  fjp
256
 * Preparando edici?n
257
 *
258
 * Revision 1.3  2006/01/16 12:47:38  fjp
259
 * Preparando edici?n
260
 *
261
 * Revision 1.2  2006/01/16 11:23:00  fjp
262
 * Preparando edici?n
263
 *
264
 * Revision 1.1  2006/01/12 13:39:14  fjp
265
 * preaparar edicion
266
 *
267
 *
268
 */
269
package com.iver.cit.gvsig.fmap.edition;
270

    
271
import java.awt.Image;
272
import java.awt.geom.Rectangle2D;
273
import java.awt.image.BufferedImage;
274
import java.io.IOException;
275
import java.util.List;
276

    
277
import org.cresques.cts.ICoordTrans;
278
import org.cresques.cts.IProjection;
279

    
280
import com.hardcode.driverManager.Driver;
281
import com.hardcode.gdbms.driver.exceptions.InitializeDriverException;
282
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
283
import com.hardcode.gdbms.engine.data.DataSource;
284
import com.hardcode.gdbms.engine.data.driver.DriverException;
285
import com.hardcode.gdbms.engine.values.Value;
286
import com.iver.cit.gvsig.exceptions.commands.EditionCommandException;
287
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
288
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileWriteException;
289
import com.iver.cit.gvsig.exceptions.layers.CancelEditingLayerException;
290
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
291
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
292
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
293
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
294
import com.iver.cit.gvsig.fmap.core.FNullGeometry;
295
import com.iver.cit.gvsig.fmap.core.IFeature;
296
import com.iver.cit.gvsig.fmap.core.IGeometry;
297
import com.iver.cit.gvsig.fmap.core.IRow;
298
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
299
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
300
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
301
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
302
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
303
import com.iver.cit.gvsig.fmap.drivers.featureiterators.AttrQueryFeatureIterator;
304
import com.iver.cit.gvsig.fmap.drivers.featureiterators.AttrQuerySelectionFeatureIterator;
305
import com.iver.cit.gvsig.fmap.drivers.featureiterators.DefaultFeatureIterator;
306
import com.iver.cit.gvsig.fmap.drivers.featureiterators.SpatialQueryFeatureIterator;
307
import com.iver.cit.gvsig.fmap.layers.FBitSet;
308
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
309
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
310
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
311

    
312
/**
313
 * @author fjp
314
 *
315
 */
316
public class VectorialEditableAdapter extends EditableAdapter implements
317
                ReadableVectorial, BoundedShapes {
318
        protected ReadableVectorial ova;
319

    
320
        protected ISpatialIndex fmapSpatialIndex;
321

    
322
        protected Rectangle2D fullExtent;
323

    
324
        protected Image selectionImage;
325

    
326
        protected BufferedImage handlersImage;
327

    
328

    
329
        /*
330
         * azo; ReadableVectorial implementations need a reference to
331
         * IProjection (of the layer) and to ISpatialIndex (of the layer)
332
         * to allow iteration with different criteria
333
         * */
334
        protected IProjection projection;
335
//        protected ISpatialIndex fmapSpatialIndex;
336
        private ICoordTrans ct;
337

    
338
        //private double flatness=0.8;
339
        /*
340
         * private class MyFeatureIterator implements IFeatureIterator { int numReg =
341
         * 0; Rectangle2D rect; String epsg; IFeatureIterator origFeatIt; boolean
342
         * bHasNext = true;
343
         *
344
         * public MyFeatureIterator(Rectangle2D r, String strEPSG) throws
345
         * DriverException { rect = r; epsg = strEPSG; origFeatIt =
346
         * ova.getFeatureIterator(r, epsg); } public boolean hasNext() throws
347
         * DriverException { return bHasNext; }
348
         *
349
         * public IFeature next() throws DriverException { IFeature aux =
350
         * origFeatIt.next(); return null; }
351
         *
352
         * public void closeIterator() throws DriverException {
353
         *  }
354
         *  }
355
         */
356

    
357

    
358

    
359
        public VectorialEditableAdapter() {
360
                super();
361
        }
362

    
363
        public void setOriginalVectorialAdapter(ReadableVectorial rv) throws ReadDriverException {
364
                ova = rv;
365
                setOriginalDataSource(rv.getRecordset());
366
        }
367

    
368
        /*
369
         * (non-Javadoc)
370
         *
371
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#start()
372
         */
373
        public void start() throws ReadDriverException, InitializeDriverException {
374
                ova.start();
375
        }
376

    
377
        public IWriter getWriter() {
378
                if (ova.getDriver() instanceof IWriteable)
379
                {
380
                        IWriter writer = ((IWriteable) ova.getDriver()).getWriter();
381
                        if (writer instanceof ISpatialWriter)
382
                                return writer;
383
                }
384
                return null;
385
        }
386

    
387
        /*
388
         * (non-Javadoc)
389
         *
390
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#stop()
391
         */
392
        public void stop() throws ReadDriverException {
393
                ova.stop();
394
        }
395

    
396
        /*
397
         * (non-Javadoc)
398
         *
399
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getShape(int)
400
         */
401
        public IGeometry getShape(int rowIndex) throws ReadDriverException, ExpansionFileReadException {
402
                // Si no est? en el fichero de expansi?n
403
                int calculatedIndex = getCalculatedIndex(rowIndex);
404
                Integer integer = new Integer(calculatedIndex);
405
                if (!relations.containsKey(integer)) {
406
                        // Si ha sido eliminada
407
                        /*
408
                         * if (delRows.get(integer.intValue())) { return null; } else {
409
                         */
410
                        return ova.getShape(calculatedIndex);
411
                        // }
412
                }
413
                int num = ((Integer) relations.get(integer)).intValue();
414
                DefaultRowEdited feat;
415
                feat = (DefaultRowEdited) expansionFile.getRow(num);
416
                IGeometry geom=((IFeature) feat.getLinkedRow()).getGeometry();
417
                if (geom!=null)
418
                        return geom.cloneGeometry();
419
                return geom;
420
        }
421

    
422
        /*
423
         * (non-Javadoc)
424
         *
425
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getShapeType()
426
         */
427
        public int getShapeType() throws ReadDriverException {
428
                return ova.getShapeType();
429
        }
430

    
431
        public ReadableVectorial getOriginalAdapter() {
432
                return ova;
433
        }
434

    
435
        public VectorialDriver getDriver() {
436
                return ova.getDriver();
437
        }
438

    
439
        public void setDriver(VectorialDriver driver) {
440
                this.ova.setDriver(driver);
441
        }
442

    
443
        public DriverAttributes getDriverAttributes() {
444
                return ova.getDriverAttributes();
445
        }
446

    
447
        /**
448
         * DOCUMENT ME!
449
         * @throws StartEditionLayerException
450
         * @throws StartWriterVisitorException
451
         *
452
         * @throws EditionException
453
         *             DOCUMENT ME!
454
         */
455
        public void startEdition(int sourceType) throws StartWriterVisitorException {
456
                super.startEdition(sourceType);
457
                Driver drv = ova.getDriver();
458
                if (drv instanceof IWriteable)
459
                {
460
                        setWriter(((IWriteable) drv).getWriter());
461
                }
462

    
463

    
464
                try {
465
                        expansionFile.open();
466
                        if (fmapSpatialIndex == null) {
467
                                // TODO: Si la capa dispone de un ?ndice espacial, hacer
468
                                // algo aqu? para que se use ese ?ndice espacial.
469
//                                index = new Quadtree();
470
                                fmapSpatialIndex = new QuadtreeJts();
471

    
472
                                for (int i = 0; i < ova.getShapeCount(); i++) {
473
                                        Rectangle2D r=null;
474
                                        if (ova.getDriver() instanceof BoundedShapes) {
475
                                                r = ((BoundedShapes) ova.getDriver()).getShapeBounds(i);
476
                                        } else {
477
                                                IGeometry g = null;
478
                                                g = ((DefaultFeature) ova.getFeature(i))
479
                                                                        .getGeometry();
480
                                                if (g == null) {
481
                                                        continue;
482
                                                }
483

    
484
                                                r = g.getBounds2D();
485
                                        }
486
                                        if (ct != null) {
487
                                                r = ct.convert(r);
488
                                        }
489
//                                        Envelope e = new Envelope(r.getX(),
490
//                                                        r.getX() + r.getWidth(), r.getY(), r.getY()
491
//                                                                        + r.getHeight());
492
                                        fmapSpatialIndex.insert(r, new Integer(i));
493
                                        if (fullExtent == null) {
494
                                                fullExtent = r;
495
                                        } else {
496
                                                fullExtent = fullExtent.createUnion(r);
497
                                        }
498
                                }
499
                        }
500
                } catch (ReadDriverException e) {
501
                        throw new StartWriterVisitorException(writer.getName(),e);
502
                }
503

    
504
//                System.err.println("Se han metido en el ?ndice "
505
//                                + index.queryAll().size() + " geometr?as");
506
        }
507

    
508
        /*
509
         * (non-Javadoc)
510
         *
511
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getRow(int)
512
         */
513
        public IRowEdited getRow(int index) throws ReadDriverException, ExpansionFileReadException {
514
                // FJP: Demasiados start - stop hacen que se abra miles de veces el fichero y salte un error. Es mejor
515
                // no abrir al leer una fila, y si se abre, que se haga en procesos de lectura y escritura en batch.
516
                // otra posibilidad es abrir y no cerrar. (De todas formas a los 5 segundos lo cierrra el AutomaticDataSource
517
                // Por cierto, al quitar esto tambi?n se gana velocidad.
518
//                start(); 
519
                int calculatedIndex = getCalculatedIndex(index);
520
                Integer integer = new Integer(calculatedIndex);
521
                // Si no est? en el fichero de expansi?n
522
                DefaultRowEdited edRow = null;
523
                if (!relations.containsKey(integer)) {
524
                        edRow = new DefaultRowEdited(ova.getFeature(calculatedIndex),
525
                                        IRowEdited.STATUS_ORIGINAL, index);
526
//                        stop();
527
                        return createExternalRow(edRow, 0);
528
                }
529
                int num = ((Integer) relations.get(integer)).intValue();
530
                IRowEdited aux = expansionFile.getRow(num);
531
                edRow = new DefaultRowEdited(aux.getLinkedRow().cloneRow(), aux
532
                                .getStatus(), index);
533
//                stop();
534
                return edRow;
535
        }
536

    
537
        /**
538
         * Elimina una geometria. Si es una geometr?a original de la capa en edici?n
539
         * se marca como eliminada (haya sido modificada o no). Si es una geometr?a
540
         * a?adida posteriormente se invalida en el fichero de expansi?n, para que
541
         * una futura compactaci?n termine con ella.
542
         *
543
         * @param index
544
         *            ?ndice de la geometr?a.
545
         * @throws ReadDriverException
546
         * @throws ExpansionFileReadException
547
         *
548
         * @throws DriverIOException
549
         * @throws IOException
550
         */
551
        public IRow doRemoveRow(int index, int sourceType) throws ReadDriverException, ExpansionFileReadException{
552
                boolean cancel = fireBeforeRemoveRow(index, sourceType);
553
                if (cancel)
554
                        return null;
555
                // Llega el calculatedIndex
556
                Integer integer = new Integer(index);
557

    
558
                IFeature feat = null;
559
                delRows.set(index, true);
560
                // Si la geometr?a no ha sido modificada
561
                if (!relations.containsKey(integer)) {
562
                        feat = (DefaultFeature) (ova.getFeature(index));
563
                } else {
564
                        int num = ((Integer) relations.get(integer)).intValue();
565
                        feat = (IFeature) expansionFile.getRow(num).getLinkedRow();
566
                }
567
                // Se actualiza el ?ndice
568
                if (feat != null) {
569
                    IGeometry geom = feat.getGeometry();
570
                    if (geom != null) {
571
                        Rectangle2D r = geom.getBounds2D();
572
                        this.fmapSpatialIndex.delete(r, new Integer(index));
573
                        isFullExtentDirty = true;
574
                    }
575
                }
576
                setSelection(new FBitSet());
577
                fireAfterRemoveRow(index, sourceType);
578
                return feat;
579
        }
580

    
581
        /**
582
         * Si se intenta modificar una geometr?a original de la capa en edici?n se
583
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
584
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
585
         * fichero de expansi?n (por ser nueva o original pero modificada) se invoca
586
         * el m?todo modifyGeometry y se actualiza el ?ndice de la geometria en el
587
         * fichero.
588
         *
589
         * @param calculatedIndex
590
         *            DOCUMENT ME!
591
         * @param feat
592
         *            DOCUMENT ME!
593
         *
594
         * @return position inside ExpansionFile
595
         * @throws ReadDriverException
596
         * @throws ExpansionFileWriteException
597
         * @throws ExpansionFileReadException
598
         *
599
         * @throws IOException
600
         * @throws DriverIOException
601
         */
602
        public int doModifyRow(int calculatedIndex, IRow feat, int sourceType) throws ReadDriverException, ExpansionFileWriteException, ExpansionFileReadException {
603
                boolean cancel = fireBeforeModifyRow(feat, calculatedIndex, sourceType);
604
                if (cancel)
605
                        return -1;
606
                int posAnteriorInExpansionFile = -1;
607
                Integer integer = new Integer(calculatedIndex);
608

    
609
                IFeature featAnt = null;
610
//                System.err.println("Modifica una Row en la posici?n: "
611
//                                + calculatedIndex);
612
                // Si la geometr?a no ha sido modificada
613
                if (!relations.containsKey(integer)) {
614
                        int newPosition = expansionFile.addRow(feat,
615
                                        IRowEdited.STATUS_MODIFIED, actualIndexFields);
616
                        relations.put(integer, new Integer(newPosition));
617

    
618
                        if (sourceType == EditionEvent.GRAPHIC) {
619
                                // Se actualiza el ?ndice espacial
620
                                featAnt = (DefaultFeature) (ova.getFeature(calculatedIndex));
621
                                IGeometry g = featAnt.getGeometry();
622
                                Rectangle2D rAnt = g.getBounds2D();
623
                                Rectangle2D r = ((IFeature) feat).getGeometry().getBounds2D();
624
                                this.fmapSpatialIndex.delete(rAnt, new Integer(calculatedIndex));
625
                                this.fmapSpatialIndex.insert(r, new Integer(calculatedIndex));
626
                        }
627
                } else {
628
                        // Obtenemos el ?ndice en el fichero de expansi?n
629
                        int num = ((Integer) relations.get(integer)).intValue();
630
                        posAnteriorInExpansionFile=num;
631

    
632
                        // Obtenemos la geometr?a para actualiza el ?ndice
633
                        // espacialposteriormente
634
                        featAnt = (IFeature) expansionFile.getRow(num).getLinkedRow();
635

    
636
                        /*
637
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
638
                         * fichero de expansi?n en el que se encuentra la geometr?a
639
                         * modificada
640
                         */
641
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
642

    
643
                        /*
644
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
645
                         * fichero de expansi?n.
646
                         */
647
                        relations.put(integer, new Integer(num));
648
                        if (sourceType == EditionEvent.GRAPHIC) {
649
                                // Se modifica el ?ndice espacial
650
                                Rectangle2D rAnt = featAnt.getGeometry().getBounds2D();
651
                                Rectangle2D r = ((IFeature) feat).getGeometry().getBounds2D();
652
                                this.fmapSpatialIndex.delete(rAnt, new Integer(calculatedIndex));
653
                                this.fmapSpatialIndex.insert(r, new Integer(calculatedIndex));
654
                        }
655

    
656
                }
657
                isFullExtentDirty = true;
658
                fireAfterModifyRow(calculatedIndex, sourceType);
659
                return posAnteriorInExpansionFile;
660
        }
661

    
662
        /**
663
         * Actualiza en el mapa de ?ndices, la posici?n en la que estaba la
664
         * geometr?a antes de ser modificada. Se marca como v?lida, en caso de que
665
         * fuera una modificaci?n de una geometr?a que estuviese en el fichero de
666
         * expansi?n antes de ser modificada y se pone el puntero de escritura del
667
         * expansion file a justo despues de la penultima geometr?a
668
         *
669
         * @param calculatedIndex
670
         *            ?ndice de la geometr?a que se quiere deshacer su modificaci?n
671
         * @param previousExpansionFileIndex
672
         *            ?ndice que ten?a antes la geometr?a en el expansionFile. Si
673
         *            vale -1 quiere decir que es una modificaci?n de una geometr?a
674
         *            original y por tanto no hay que actualizar el mapa de indices
675
         *            sino eliminar su entrada.
676
         * @throws IOException
677
         * @throws DriverIOException
678
         */
679
        public int undoModifyRow(int calculatedIndex,
680
                        int previousExpansionFileIndex, int sourceType) throws EditionCommandException{
681
                try {
682
                        // Llega el CalculatedIndex
683
                        /*
684
                         * Si la acci?n de modificar se realiz? sobre una geometr?a original
685
                         */
686
                        if (previousExpansionFileIndex == -1) {
687

    
688
                                // Se obtiene la geometr?a para actualizar el ?ndice
689
                                // IGeometry g = ((DefaultFeature)
690
                                // getRow(calculatedIndex).getLinkedRow()).getGeometry();
691
                                int inverse = getInversedIndex(calculatedIndex);
692
                                DefaultFeature df;
693

    
694
                                df = (DefaultFeature) getRow(inverse).getLinkedRow();
695

    
696
                                boolean cancel = fireBeforeModifyRow(df, calculatedIndex,
697
                                                sourceType);
698
                                if (cancel)
699
                                        return -1;
700
                                IGeometry g = df.getGeometry();
701
                                // IGeometry g = ova.getShape(calculatedIndex);
702
                                Rectangle2D r = g.getBounds2D();
703

    
704
                                // Se elimina de las relaciones y del fichero de expansi?n
705
                                relations.remove(new Integer(calculatedIndex));
706
                                expansionFile.deleteLastRow();
707
                                if (sourceType == EditionEvent.GRAPHIC) {
708
                                        // Se actualizan los ?ndices
709
                                        IGeometry gAnt = ova.getShape(calculatedIndex);
710
                                        /*
711
                                         * IGeometry gAnt = ((DefaultFeature) getRow(calculatedIndex)
712
                                         * .getLinkedRow()).getGeometry();
713
                                         */
714
                                        Rectangle2D rAnt = gAnt.getBounds2D();
715
                                        this.fmapSpatialIndex.delete(r, new Integer(calculatedIndex));
716
                                        this.fmapSpatialIndex.insert(rAnt, new Integer(calculatedIndex));
717
                                }
718
                        } else {
719
                                // Se obtiene la geometr?a para actualizar el ?ndice
720
                                IGeometry g = null;
721
                                int inverse = getInversedIndex(calculatedIndex);
722
                                DefaultFeature df = (DefaultFeature) getRow(inverse).getLinkedRow();
723
                                boolean cancel = fireBeforeModifyRow(df, calculatedIndex,
724
                                                sourceType);
725
                                if (cancel)
726
                                        return -1;
727
                                if (sourceType == EditionEvent.GRAPHIC) {
728
                                        g = df.getGeometry();
729
                                        System.out.println("Actual: " + g.toString());
730

    
731
                                        Rectangle2D r = g.getBounds2D();
732
                                        this.fmapSpatialIndex.delete(r, new Integer(calculatedIndex));
733

    
734
                                        // Se recupera la geometr?a
735
                                        // expansionFile.validateRow(previousExpansionFileIndex);
736

    
737
                                        // Se actualizan los ?ndices
738
                                         g = ((IFeature)
739
                                         (expansionFile.getRow(previousExpansionFileIndex).getLinkedRow())).getGeometry();
740
                                        // System.out.println("Anterior a la que volvemos : " +
741
                                        // g.toString());
742
//                                        g = ((DefaultFeature) getRow(inverse).getLinkedRow())
743
//                                        .getGeometry();
744
                                        r = g.getBounds2D();
745
                                        this.fmapSpatialIndex.insert(r, new Integer(calculatedIndex));
746
                                }
747
                                // Se actualiza la relaci?n de ?ndices
748
                                // Integer integer = new Integer(geometryIndex);
749
                                int numAnt=((Integer)relations.get(new Integer(calculatedIndex))).intValue();
750
                                relations.put(new Integer(calculatedIndex), new Integer(
751
                                                previousExpansionFileIndex));
752
                                return numAnt;
753

    
754
                        }
755
                } catch (ReadDriverException e) {
756
                        throw new EditionCommandException(writer.getName(),e);
757
                }
758
                //fireAfterModifyRow(calculatedIndex, sourceType);
759
                return -1;
760
        }
761

    
762
        /**
763
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
764
         * en la tabla relations.
765
         *
766
         * @param feat
767
         *            geometr?a a guardar.
768
         *
769
         * @return calculatedIndex
770
         * @throws ExpansionFileWriteException
771
         * @throws DriverIOException
772
         * @throws IOException
773
         */
774
        public int doAddRow(IRow feat, int sourceType) throws ReadDriverException, ExpansionFileWriteException{
775
                int calculatedIndex = super.doAddRow(feat, sourceType);
776
                // Actualiza el ?ndice espacial
777
                IGeometry g = ((IFeature) feat).getGeometry();
778
                Rectangle2D r = g.getBounds2D();
779
                fmapSpatialIndex.insert(r, new Integer(calculatedIndex));
780
                isFullExtentDirty = true;
781
                return calculatedIndex;
782
        }
783

    
784
        /**
785
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
786
         * en el fichero original
787
         *
788
         * @param index
789
         *            DOCUMENT ME!
790
         * @throws IOException
791
         * @throws DriverIOException
792
         */
793
        public void undoRemoveRow(int index, int sourceType) throws EditionCommandException  {
794
                super.undoRemoveRow(index, sourceType);
795

    
796
                IGeometry g = null;
797
                try {
798
                        g = ((IFeature) getRow(getInversedIndex(index)).getLinkedRow()).getGeometry();
799
                } catch (ReadDriverException e) {
800
                        throw new EditionCommandException(writer.getName(),e);
801
                }
802

    
803
                Rectangle2D r = g.getBounds2D();
804
                this.fmapSpatialIndex.insert(r, new Integer(index));
805
        }
806

    
807
        /**
808
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
809
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
810
         * relaci?n del mapa de relaciones
811
         *
812
         * @param fmapSpatialIndex
813
         *            ?ndice de la geometr?a que se a?adi?
814
         * @throws EditionCommandException
815
         * @throws DriverIOException
816
         * @throws IOException
817
         */
818
        public void undoAddRow(int calculatedIndex, int sourceType) throws EditionCommandException{
819
                int inverse = getInversedIndex(calculatedIndex);
820
                IGeometry g;
821
                try {
822
                        g = ((IFeature) getRow(inverse).getLinkedRow()).getGeometry();
823
                        Rectangle2D r = g.getBounds2D();
824
                        this.fmapSpatialIndex.delete(r, new Integer(calculatedIndex));
825

    
826
                        super.undoAddRow(calculatedIndex, sourceType);
827
                        setSelection(new FBitSet());
828
                } catch (ReadDriverException e) {
829
                        throw new EditionCommandException(writer.getName(),e);
830
                }
831
        }
832

    
833
        /**
834
         * Obtiene las geometr?as que se encuentran en el rect?ngulo que se pasa
835
         * como par?metro haciendo uso del ?ndice espacial
836
         *
837
         * @param r
838
         *            Rect?ngulo indicando la porci?n del espacio para el cual se
839
         *            quiere saber los ?ndices de las geometr?as que se encuentran
840
         *            dentro de ?l
841
         *
842
         * @return Array de ?ndices para su uso con getGeometry, removeGeometry, ...
843
         */
844
        /*
845
         * public int[] getRowsIndexes_OL(Rectangle2D r) { Envelope e = new
846
         * Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(), r.getY() +
847
         * r.getHeight()); List l = index.query(e); int[] indexes = new
848
         * int[l.size()];
849
         *
850
         * for (int index = 0; index < l.size(); index++) { Integer i = (Integer)
851
         * l.get(index); indexes[index] = getInversedIndex(i.intValue()); }
852
         *
853
         * return indexes; }
854
         */
855
        /**
856
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getShapeCount()
857
         */
858
        public int getShapeCount() throws ReadDriverException {
859
                return getRowCount();
860
        }
861

    
862
        /**
863
         * @throws ExpansionFileReadException
864
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getFullExtent()
865
         */
866
        public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
867
                if (fullExtent == null) {
868
                        fullExtent = ova.getFullExtent();
869
                }
870

    
871
                if (isFullExtentDirty) {
872
                        fullExtent = reCalculateFullExtent();
873
                        isFullExtentDirty = false;
874
                }
875
                return fullExtent;
876
        }
877

    
878
        /**
879
         * Use it BEFORE writing to a file.
880
         *
881
         * @return real full extent.
882
         * @throws ExpansionFileReadException
883
         * @throws ReadDriverException
884
         * @throws DriverIOException
885
         */
886
        public Rectangle2D reCalculateFullExtent() throws ReadDriverException, ExpansionFileReadException  {
887
                int i=0;
888
                int count=getShapeCount();
889
                while (i<count && getShape(i) == null){
890
                        i++;
891
                }
892
                if (i < count){
893
                        fullExtent = getShape(i).getBounds2D();
894
                        for (int j = i; j < count; j++) {
895
                                IGeometry geom=getShape(i);
896
                                if (geom==null)
897
                                        continue;
898
                                if (fullExtent==null) {
899
                                        fullExtent=geom.getBounds2D();
900
                                        continue;
901
                                }
902
                                if (!(geom instanceof FNullGeometry)) {
903
                                        fullExtent.add(geom.getBounds2D());
904
                                }
905
                        }
906
                } else {
907
                        fullExtent = ova.getFullExtent();
908
                }
909
                return fullExtent;
910
        }
911

    
912
        /**
913
         * En la implementaci?n por defecto podemos hacer que cada feature tenga ID =
914
         * numero de registro. En el DBAdapter podr?amos "overrride" este m?todo y
915
         * poner como ID de la Feature el campo ?nico escogido en la base de datos.
916
         *
917
         * @param numReg
918
         * @return
919
         * @throws ExpansionFileReadException
920
         */
921
        public IFeature getFeature(int numReg) throws ReadDriverException, ExpansionFileReadException {
922
                IGeometry geom;
923
                IFeature feat = null;
924
                        geom = getShape(numReg);
925
                        DataSource rs = getRecordset();
926
                        Value[] regAtt = new Value[rs.getFieldCount()];
927
                        for (int fieldId = 0; fieldId < rs.getFieldCount(); fieldId++) {
928
                                regAtt[fieldId] = rs.getFieldValue(numReg, fieldId);
929
                        }
930
                        feat = new DefaultFeature(geom, regAtt, numReg + "");
931
                return feat;
932
        }
933

    
934
        public void stopEdition(IWriter writer, int sourceType) throws StopWriterVisitorException {
935
//                ISpatialWriter spatialWriter = (ISpatialWriter) writer;
936
//                spatialWriter.setFlatness(FConverter.flatness);
937
                super.stopEdition(writer, sourceType);
938
//                try {
939
//                        ova.getDriver().reload();
940
//                } catch (ReloadDriverException e) {
941
//                        throw new StopWriterVisitorException(writer.getName(),e);
942
//                }
943
//                fmapSpatialIndex=null;
944
                writer=null;
945
        }
946

    
947
        public Rectangle2D getShapeBounds(int index) throws ReadDriverException, ExpansionFileReadException {
948
                // Solo se utiliza cuando el driver es BoundedShapes
949
                // Si no est? en el fichero de expansi?n
950
                Integer integer = new Integer(index);
951
                if (!relations.containsKey(integer)) {
952
                        if (ova.getDriver() instanceof BoundedShapes) {
953
                                BoundedShapes bs = (BoundedShapes) ova.getDriver();
954
                                return bs.getShapeBounds(index);
955
                        }
956
                        return ova.getDriver().getShape(index).getBounds2D();
957

    
958
                }
959
                int num = ((Integer) relations.get(integer)).intValue();
960
                DefaultRowEdited feat;
961
                feat = (DefaultRowEdited) expansionFile.getRow(num);
962
                if (feat.getStatus() == IRowEdited.STATUS_DELETED)
963
                        return null;
964
                IGeometry geom = ((IFeature) feat.getLinkedRow()).getGeometry();
965
                return geom.getBounds2D();// getGeometry();
966

    
967
        }
968

    
969
        public int getShapeType(int index) throws ReadDriverException {
970
                return ova.getShapeType();
971
        }
972

    
973
        /**
974
         * Usar solo cuando est?s seguro de que puedes gastar memoria. Nosotros lo
975
         * usamos para las b?squedas por ?ndice espacial con el handle. La idea es
976
         * usarlo una vez, guardar las geometr?as que necesitas en ese extent y
977
         * trabajar con ellas hasta el siguiente cambio de extent.
978
         *
979
         * @param r
980
         * @param strEPSG
981
         * @return
982
         * @throws ExpansionFileReadException
983
         * @throws ReadDriverException
984
         * @throws DriverException
985
         */
986
        public IRowEdited[] getFeatures(Rectangle2D r, String strEPSG) throws ReadDriverException, ExpansionFileReadException{
987
                // En esta clase suponemos random access.
988
                // Luego tendremos otra clase que sea VectorialEditableDBAdapter
989
                // que reescribir? este m?todo.
990
//                Envelope e = FConverter.convertRectangle2DtoEnvelope(r);
991
                long t1 = System.currentTimeMillis();
992
                List l = fmapSpatialIndex.query(r);
993
                long t2 = System.currentTimeMillis();
994
                IRowEdited[] feats = new IRowEdited[l.size()];
995
                for (int index = 0; index < l.size(); index++) {
996
                        Integer i = (Integer) l.get(index);
997
                        int inverse = getInversedIndex(i.intValue());
998
                        feats[index] = getRow(inverse);
999
                }
1000
                long t3 = System.currentTimeMillis();
1001
                System.out.println("VectorialEditableAdapter.getFeatures: tSpatialIndex = " + (t2-t1) + " tFor=" + (t3-t2));
1002
                return feats;
1003
        }
1004

    
1005
//        public void setSpatialIndex(SpatialIndex spatialIndex) {
1006
//                index = (Quadtree) spatialIndex;
1007
//                QuadtreeJts fmapidx = new QuadtreeJts(index);
1008
//                setSpatialIndex(fmapidx);
1009
//
1010
//        }
1011

    
1012
        public void setFullExtent(Rectangle2D fullExtent2) {
1013
                fullExtent = fullExtent2;
1014
        }
1015

    
1016
        /**
1017
         * DOCUMENT ME!
1018
         *
1019
         * @return DOCUMENT ME!
1020
         */
1021
        public Image getSelectionImage() {
1022
                return selectionImage;
1023
        }
1024

    
1025
        public Image getHandlersImage() {
1026
                return handlersImage;
1027
        }
1028

    
1029
        /**
1030
         * DOCUMENT ME!
1031
         *
1032
         * @param i
1033
         *            DOCUMENT ME!
1034
         */
1035
        public void setSelectionImage(Image i) {
1036
                selectionImage = i;
1037
        }
1038

    
1039
        public void setHandlersImage(BufferedImage handlersImage) {
1040
                this.handlersImage = handlersImage;
1041
        }
1042

    
1043
        public IFeatureIterator getFeatureIterator() throws ReadDriverException {
1044
                return new DefaultFeatureIterator(this, projection, null, null);
1045
        }
1046

    
1047

    
1048
        public IFeatureIterator getFeatureIterator(String[] fields, IProjection newProjection)
1049
        throws ReadDriverException{
1050
                return new DefaultFeatureIterator(this, projection, newProjection, fields);
1051
        }
1052

    
1053
        /**
1054
        * Return a feature iterator from a given sql statement.
1055
        * <br>
1056
        * In this case, the statement will have the "projection" operator
1057
        * (select campo1, campo2, ...etc) and the "selection" operator (where ....)
1058
        * @param sql statement which define a filter
1059
        * @return feature iterator
1060
        * */
1061
        public IFeatureIterator getFeatureIterator(String sql,
1062
                                                                IProjection newProjection) throws ReadDriverException{
1063

    
1064
                return new AttrQueryFeatureIterator(this, projection, newProjection, sql);
1065
        }
1066

    
1067

    
1068
        /**
1069
        * Makes an spatial query returning a feature iterator over the features which intersects
1070
        * or are contained in the rectangle query. Applies a restriction to the alphanumeric fields
1071
        * returned by the iterator.
1072
        * @param rect
1073
        * @param fields
1074
        * @return
1075
         * @throws ReadDriverException
1076
        */
1077
        public IFeatureIterator getFeatureIterator(Rectangle2D rect, String[] fields,
1078
                                                                        IProjection newProjection, boolean fastIteration) throws ReadDriverException{
1079
//                if(index == null){
1080
                        return new SpatialQueryFeatureIterator(this, projection, newProjection, fields, rect, fastIteration);
1081
//                }else{
1082
//                        return new IndexedSptQueryFeatureIterator(this, projection, newProjection, fields, rect, fmapSpatialIndex, fastIteration);
1083
//                }
1084
        }
1085

    
1086
        public ISpatialIndex getSpatialIndex() {
1087
                return fmapSpatialIndex;
1088
        }
1089

    
1090
        public void setSpatialIndex(ISpatialIndex spatialIndex) {
1091
//                this.fmapSpatialIndex = spatialIndex;
1092
        }
1093

    
1094
        public void setProjection(IProjection projection) {
1095
                this.projection = projection;
1096
        }
1097

    
1098
        public IProjection getProjection() {
1099
                return projection;
1100
        }
1101

    
1102
        public void cancelEdition(int sourceType) throws CancelEditingLayerException {
1103
                super.cancelEdition(sourceType);
1104
                fmapSpatialIndex=null;
1105
                setWriter(null);
1106
                System.gc();
1107
        }
1108

    
1109
        /**
1110
         * Inserta las coordenadas de transformaci?n.
1111
         *
1112
         * @param ct Coordenadas de transformaci?n.
1113
         */
1114
        public void setCoordTrans(ICoordTrans ct) {
1115
                this.ct=ct;
1116
        }
1117

    
1118
        public IFeatureIterator getFeatureIterator(String sql, IProjection newProjection, boolean withSelection) throws ReadDriverException {
1119
                if (withSelection)
1120
                        return new AttrQuerySelectionFeatureIterator(this, projection, newProjection, sql);
1121
                else
1122
                        return getFeatureIterator(sql,newProjection);
1123
        }
1124

    
1125
}