Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / VectorialEditableDBAdapter.java @ 12099

History | View | Annotate | Download (16.2 KB)

1
/**
2
 *
3
 */
4
package com.iver.cit.gvsig.fmap.edition;
5

    
6
import java.awt.geom.Rectangle2D;
7
import java.util.ArrayList;
8
import java.util.Hashtable;
9
import java.util.List;
10

    
11
import org.cresques.cts.IProjection;
12

    
13
import com.hardcode.driverManager.Driver;
14
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
15
import com.iver.cit.gvsig.exceptions.commands.EditionCommandException;
16
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
17
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileWriteException;
18
import com.iver.cit.gvsig.exceptions.expansionfile.OpenExpansionFileException;
19
import com.iver.cit.gvsig.exceptions.layers.CancelEditingLayerException;
20
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
21
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
22
import com.iver.cit.gvsig.fmap.core.IFeature;
23
import com.iver.cit.gvsig.fmap.core.IRow;
24
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
25
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
26
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
27
import com.iver.cit.gvsig.fmap.drivers.IVectorialDatabaseDriver;
28
import com.iver.cit.gvsig.fmap.drivers.featureiterators.AttrQueryFeatureIterator;
29
import com.iver.cit.gvsig.fmap.drivers.featureiterators.DefaultFeatureIterator;
30
import com.iver.cit.gvsig.fmap.drivers.featureiterators.IndexedSptQueryFeatureIterator;
31
import com.iver.cit.gvsig.fmap.drivers.featureiterators.SpatialQueryFeatureIterator;
32
import com.iver.cit.gvsig.fmap.layers.ISpatialDB;
33
import com.iver.cit.gvsig.fmap.layers.VectorialDBAdapter;
34
import com.vividsolutions.jts.geom.Envelope;
35
import com.vividsolutions.jts.index.quadtree.Quadtree;
36

    
37
/**
38
 * @author fjp
39
 *
40
 */
41
public class VectorialEditableDBAdapter extends VectorialEditableAdapter
42
                implements ISpatialDB {
43
        private int maxIndex=0;
44
        private class MyIterator implements IFeatureIterator {
45
                private Rectangle2D extent = null;
46

    
47
                private VectorialDBAdapter orig;
48

    
49
                private IFeature feat;
50

    
51
                private IFeatureIterator featIt;
52

    
53
                private String epsg;
54

    
55
                private IVectorialDatabaseDriver dbDriver;
56

    
57
                Hashtable alreadyDone = new Hashtable();
58

    
59
                private int idFromExpansion = 0;
60

    
61
                private List listFromExpansion;
62

    
63
                private boolean bOriginalCursorOpened = true;
64

    
65
                public MyIterator(Rectangle2D r, String strEPSG) throws ReadDriverException {
66
                        extent = r;
67
                        epsg = strEPSG;
68
                        orig = (VectorialDBAdapter) ova;
69
                        featIt = orig.getFeatureIterator(extent, epsg);
70
                        dbDriver = (IVectorialDatabaseDriver) getOriginalDriver();
71
                        getFeaturesFromExpansionFile();
72
                }
73

    
74

    
75
                /*
76
                 * azo: these new constructors must be tested
77
                 * */
78

    
79
                public MyIterator(String[] fields, IProjection newProjection) throws ReadDriverException{
80
                        epsg = newProjection.getAbrev();
81
                        orig = (VectorialDBAdapter) ova;
82
                        featIt = orig.getFeatureIterator(fields, newProjection);
83
                        dbDriver = (IVectorialDatabaseDriver) getOriginalDriver();
84
                        getFeaturesFromExpansionFile();
85
                }
86

    
87
                public MyIterator(String sql, IProjection newProjection) throws ReadDriverException{
88
                        epsg = newProjection.getAbrev();
89
                        orig = (VectorialDBAdapter) ova;
90
                        featIt = orig.getFeatureIterator(sql, newProjection);
91
                        dbDriver = (IVectorialDatabaseDriver) getOriginalDriver();
92
                        getFeaturesFromExpansionFile();
93
                }
94

    
95
                public MyIterator(Rectangle2D rect, String[] fields, IProjection newProjection) throws ReadDriverException{
96
                        extent = rect;
97
                        epsg = newProjection.getAbrev();
98
                        orig = (VectorialDBAdapter) ova;
99
                        featIt = orig.getFeatureIterator(extent, fields, newProjection, true);
100
                        dbDriver = (IVectorialDatabaseDriver) getOriginalDriver();
101
                        getFeaturesFromExpansionFile();
102
                }
103

    
104

    
105

    
106
                public boolean hasNext() throws ReadDriverException, ExpansionFileReadException {
107
                        feat = null;
108
                        int calculatedIndex = -1;
109
                        if (bOriginalCursorOpened) // Si hay originales (Es porque si se ha
110
                                                                                // llegado al final, se cierra el
111
                                                                                // iterador y salta un fallo
112
                        {
113
                                bOriginalCursorOpened = featIt.hasNext();
114
                                if (bOriginalCursorOpened) {
115
                                        feat = featIt.next();
116
                                        int originalIndex = dbDriver.getRowIndexByFID(feat);
117

    
118
                                        // Iteramos hasta que encontremos alguno no borrado.
119
                                        // Aqu? suponemos que el orden es el original. Si no, no funcionar?.
120
                                        if (delRows.get(originalIndex)) // Si est? borrado
121
                                        {
122
                                                feat = null;
123
                                                boolean bFound = false;
124
                                                while (featIt.hasNext())
125
                                                {
126
                                                        feat = featIt.next();
127
                                                        originalIndex = dbDriver.getRowIndexByFID(feat);
128
                                                        // calculatedIndex = getCalculatedIndex(originalIndex);
129
                                                        if (delRows.get(originalIndex) == false) // Si NO est? borrado
130
                                                        {
131
                                                                bFound = true;
132
                                                                break;
133
                                                        }
134
                                                }
135
                                                if (bFound == false) // Todos los ?ltimos est?n borrados.
136
                                                {
137
                                                        bOriginalCursorOpened = false; // para que busque en el fichero de expansi?n
138
                                                        feat = null;
139
                                                }
140
                                        } // if delRows
141
                                        if (bOriginalCursorOpened) // Si todav?a quedan features por leer, y no est?n borradas
142
                                        {
143
                                                calculatedIndex = originalIndex; //getCalculatedIndex(originalIndex);
144
                                                Integer integer = new Integer(calculatedIndex);
145
                                                if (!relations.containsKey(integer)) { // Si no est? en el
146
                                                                                                                                // fichero de
147
                                                                                                                                // expansi?n
148
                                                        alreadyDone.put(integer, feat);
149
                                                } else { // Si est? en el fichero de expansi?n
150
                                                        int num = ((Integer) relations.get(integer)).intValue();
151
                                                        IRowEdited auxR;
152
                                                        auxR = expansionFile.getRow(num);
153
                                                        feat = (IFeature) auxR.getLinkedRow().cloneRow();
154
                                                        // feat = (IFeature) auxR.getLinkedRow();
155
                                                        alreadyDone.put(integer, feat);
156
                                                } // else
157
                                        } // if tercer bOriginalCursorOpened
158
                                } // if segundo bOriginalCursorOpened
159
                        } // if primer bOriginalCursorOpened
160
                        if (!bOriginalCursorOpened) {
161
                                // Si ya no hay m?s de las originales, todav?a tenemos
162
                                // que revisar las a?adidas que hay en el fichero
163
                                // de expansi?n
164
                                        while ((idFromExpansion < expansionFile.getSize()) && (feat == null))
165
                                        {
166
                                                IRowEdited rowEd = expansionFile.getRow(idFromExpansion);
167
                                                IFeature aux = (IFeature) rowEd.getLinkedRow();
168
                                                Integer calculated = (Integer) mapFID2index.get(aux.getID());
169
                                                calculatedIndex = calculated.intValue();
170
                                                System.out.println("El elemento idFromExpansion = " + idFromExpansion + " es " + aux.getID());
171

    
172
                                                // Revisamos los borrados
173
                                                if (delRows.get(calculatedIndex) == true)
174
                                                {
175
                                                        boolean bFound = false;
176
                                                        while ((!bFound) && (idFromExpansion < expansionFile.getSize()-1))
177
                                                        {
178
                                                                // calculatedIndex++;
179
                                                                idFromExpansion++;
180
                                                                rowEd = expansionFile.getRow(idFromExpansion);
181
                                                                aux = (IFeature) rowEd.getLinkedRow();
182

    
183

    
184

    
185
                                                                Integer auxCalculated = (Integer) mapFID2index.get(aux.getID());
186
                                                                calculatedIndex = auxCalculated.intValue();
187
                                                                // Si no est? borrado y es una entidad v?lida, que est? siendo usada (no es algo que est? en el expansionFile sin usarse)
188
                                                                if ((delRows.get(calculatedIndex) == false) && (relations.containsKey(auxCalculated)))
189
                                                                {
190
                                                                        bFound = true;
191
                                                                        calculated = auxCalculated;
192
                                                                        break;
193
                                                                }
194
                                                                else
195
                                                                {
196
                                                                        System.out.println("El elemento idFromExpansion = " + idFromExpansion + " est? borrado");
197
                                                                }
198
                                                        }
199
                                                        if (bFound)
200
                                                        {
201
                                                                calculated = new Integer(calculatedIndex);
202
                                                                rowEd = expansionFile.getRow(idFromExpansion);
203
                                                                aux = (IFeature) rowEd.getLinkedRow();
204
                                                        }
205
                                                        else
206
                                                        {
207
                                                                return false; // El resto est?n borrados
208
                                                        }
209
                                                } // if primer borrado
210
                                                if (relations.containsKey(calculated))
211
                                                {
212
                                                        Integer realExpansionIndex = (Integer) relations.get(calculated);
213
                                                        if (realExpansionIndex.intValue() == idFromExpansion)
214
                                                        {
215
                                                                feat = (IFeature) aux.cloneRow();
216
                                                        }
217
                                                }
218
                                                idFromExpansion++;
219
                                        }
220
                        }
221

    
222
                        if (calculatedIndex == -1)
223
                                return false;
224
                        else {
225
                                if (feat == null)
226
                                {
227
                                        if (idFromExpansion == expansionFile.getSize())
228
                                                return false;
229
                                        else
230
                                                System.err.println("ERROR DE ENTREGA DE FEATURE EN hasNext del Iterador");
231
                                }
232
                                /* if (delRows.get(calculatedIndex))
233
                                        feat = null; */
234
                                return true;
235
                        }
236

    
237
                }
238

    
239
                public IFeature next() {
240
                        return feat;
241
                }
242

    
243
                public void closeIterator() throws ReadDriverException {
244
                        // TODO Auto-generated method stub
245

    
246
                }
247

    
248
                private void getFeaturesFromExpansionFile() {
249
                        Envelope e = FConverter.convertRectangle2DtoEnvelope(extent);
250
                        listFromExpansion = index.query(e);
251
                }
252
        }
253

    
254

    
255
        private Hashtable mapFID2index = new Hashtable();
256
        private Hashtable mapIndex2FID = new Hashtable();
257
        /**
258
         *
259
         */
260
        public VectorialEditableDBAdapter() {
261
                super();
262
        }
263

    
264
        /*
265
         * (non-Javadoc)
266
         *
267
         * @see com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter#getFeatures(java.awt.geom.Rectangle2D,
268
         *      java.lang.String)
269
         */
270
        public IRowEdited[] getFeatures(Rectangle2D r, String strEPSG) throws ReadDriverException, ExpansionFileReadException {
271
                ArrayList aux = new ArrayList();
272
                IFeatureIterator featIt = getFeatureIterator(r, strEPSG, null);
273
                int numEntities = 0;
274
                while (featIt.hasNext()) {
275
                        IFeature feat = featIt.next();
276
                        // TODO:
277
                        assert(feat !=null);
278
                        int index = getRowIndexByFID(feat);
279
                        IRowEdited edRow = new DefaultRowEdited(feat, IRowEdited.STATUS_ORIGINAL, index);
280
                        aux.add(edRow);
281
                        numEntities++;
282
                }
283

    
284
                return (IRowEdited[]) aux.toArray(new IRowEdited[0]);
285
                // return (IFeature[]) aux.toArray(new IFeature[0]);
286

    
287
        }
288

    
289
        /*
290
         * (non-Javadoc)
291
         *
292
         * @see com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter#startEdition()
293
         */
294
        public void startEdition(int sourceType) throws StartWriterVisitorException {
295
                isEditing = true;
296
                Driver drv = ova.getDriver();
297
                if (drv instanceof IWriteable)
298
                {
299
                        setWriter(((IWriteable) drv).getWriter());
300
                }
301

    
302
                try {
303
                        expansionFile.open();
304

    
305
                        // TODO: Si la capa dispone de un ?ndice espacial, hacer
306
                        // algo aqu? para que se use ese ?ndice espacial.
307
                        index = new Quadtree();
308
                        // No metemos ninguna entidad de las originales dentro
309
                        // de la base de datos porque esa consulta ya la
310
                        // hace getFeatures sin tener en cuenta el ?ndice local.
311
                         for (int i = 0; i < ova.getShapeCount(); i++)
312
                         {
313
                                 IFeature feat = ova.getFeature(i);
314
                                 Integer calculatedIndex = new Integer(i);
315
                                 mapFID2index.put(feat.getID(), calculatedIndex);
316
                                 int featInt=Integer.parseInt(feat.getID());
317
                                 if (maxIndex<featInt){
318
                                         maxIndex=featInt;
319
                                 }
320
                                 mapIndex2FID.put(calculatedIndex, feat.getID());
321
                         }
322

    
323
                        /*
324
                         * for (int i = 0; i < ova.getShapeCount(); i++) { IGeometry g=null;
325
                         * try { g = ((DefaultFeature) ova.getFeature(i)).getGeometry(); }
326
                         * catch (DriverException e1) { // TODO Auto-generated catch block
327
                         * e1.printStackTrace(); }
328
                         *
329
                         * if (g == null) { continue; }
330
                         *
331
                         * Rectangle2D r = g.getBounds2D(); Envelope e = new
332
                         * Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(), r.getY() +
333
                         * r.getHeight()); index.insert(e, new Integer(i)); } } catch
334
                         * (DriverIOException e) { throw new EditionException(e);
335
                         */
336
                } catch (ReadDriverException e) {
337
                        throw new StartWriterVisitorException(writer.getName(),e);
338
                } catch (ExpansionFileReadException e) {
339
                        throw new StartWriterVisitorException(writer.getName(),e);
340
                } catch (OpenExpansionFileException e) {
341
                        throw new StartWriterVisitorException(writer.getName(),e);
342
                }
343

    
344
                System.err.println("Se han metido en el ?ndice "
345
                                + index.queryAll().size() + " geometr?as");
346

    
347
        }
348

    
349
        public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG)
350
                        throws ReadDriverException {
351
                return new MyIterator(r, strEPSG);
352
        }
353

    
354
        public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG,
355
                        String[] alphaNumericFieldsNeeded) throws ReadDriverException {
356
                return new MyIterator(r, strEPSG);
357
        }
358

    
359
        public IFeatureIterator getFeatureIterator(String[] fields, IProjection newProjection)
360
        throws ReadDriverException{
361
                //TODO make tests with these (unit test of vectorialeditableadapter)
362
                return new MyIterator(fields, newProjection);
363
//                return new DefaultFeatureIterator(this, projection, newProjection, fields);
364
        }
365

    
366
        //TODO test this (azo)
367
        public IFeatureIterator getFeatureIterator(Rectangle2D rect, String[] fields,
368
                        IProjection newProjection,
369
                        boolean fastIteration) throws ReadDriverException{
370
                return getFeatureIterator(rect, newProjection.getAbrev(), fields);
371
        }
372

    
373
        /**
374
        * Return a feature iterator from a given sql statement.
375
        * <br>
376
        * In this case, the statement will have the "projection" operator
377
        * (select campo1, campo2, ...etc) and the "selection" operator (where ....)
378
        * @param sql statement which define a filter
379
        * @return feature iterator
380
        * */
381
        public IFeatureIterator getFeatureIterator(String sql,
382
                                                                IProjection newProjection) throws ReadDriverException{
383

    
384
                return new AttrQueryFeatureIterator(this, projection, newProjection, sql);
385
        }
386

    
387
        public DBLayerDefinition getLyrDef() {
388
                VectorialDBAdapter orig = (VectorialDBAdapter) ova;
389
                return orig.getLyrDef();
390
        }
391

    
392
        public int getRowIndexByFID(IFeature feat) {
393
                Integer calculatedIndex = (Integer) mapFID2index.get(feat.getID());
394
                return getInversedIndex(calculatedIndex.intValue());
395
        }
396

    
397
        /* (non-Javadoc)
398
         * @see com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter#doAddRow(com.iver.cit.gvsig.fmap.core.IRow)
399
         */
400
        public int doAddRow(IRow feat, int sourceType) throws ReadDriverException, ExpansionFileWriteException {
401
                int calculatedIndex = super.doAddRow(feat, sourceType);
402
                // Integer posInExpansionFile = (Integer) relations.get(new Integer(calculatedIndex));
403
                Integer virtual = new Integer(calculatedIndex); // calculatedIndex es igual al numero de shapes originales + el numero de entidades a?adidas.
404
                                        // es decir, virtual es el calculatedIndex (no tiene en cuenta los borrados)
405
                                        // calculatedIndex = indiceExterno + borrados hasta ese punto.
406
                mapFID2index.put(feat.getID(), virtual);
407
                mapIndex2FID.put(virtual, feat.getID());
408
                return calculatedIndex;
409

    
410
        }
411

    
412
        /* (non-Javadoc)
413
         * @see com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter#doModifyRow(int, com.iver.cit.gvsig.fmap.core.IRow)
414
         */
415
        public int doModifyRow(int calculatedIndex, IRow feat,int sourceType) throws ReadDriverException, ExpansionFileWriteException, ExpansionFileReadException{
416
                int posAnteriorInExpansionFile = super.doModifyRow(calculatedIndex, feat, sourceType); // devolver? -1 si es original
417
                // No hacemos nada con las modificaciones sobre los ?ndices.
418
                // Suponiendo que feat tenga la misma ID que la que hab?a antes.
419
                Integer virtual = new Integer(calculatedIndex);
420
                String theIDoriginal = (String) mapIndex2FID.get(virtual);
421
                if (!theIDoriginal.equals(feat.getID()))
422
                {
423
                        AssertionError err = new AssertionError("Fallo al modificar la fila. ID viejo=" + theIDoriginal + " ID nuevo = " + feat.getID());
424
                        err.printStackTrace();
425
                }
426
                // hashFIDtoExpansionFile.put(feat.getID(), new Integer(posInExpansionFile));
427
                mapFID2index.put(feat.getID(), virtual);
428
                mapIndex2FID.put(virtual, feat.getID());
429
                return posAnteriorInExpansionFile;
430
        }
431

    
432
        /* (non-Javadoc)
433
         * @see com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter#doRemoveRow(int)
434
         */
435
        public IRow doRemoveRow(int index,int sourceType) throws ReadDriverException, ExpansionFileReadException {
436
                // Le entra un calculatedIndex, as? que delRows tiene guardados
437
                // los ?ndices internos, no los externos.
438
                IFeature deletedFeat = (IFeature) super.doRemoveRow(index, sourceType);
439
                // Lo borramos de hashFIDtoExpansionFile
440
                // hashFIDtoExpansionFile.remove(deletedFeat.getID());
441
                return deletedFeat;
442
        }
443

    
444
        /* (non-Javadoc)
445
         * @see com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter#undoAddRow(int)
446
         */
447
        public void undoAddRow(int calculatedIndex, int sourceType) throws EditionCommandException {
448
                // TODO Auto-generated method stub
449
                super.undoAddRow(calculatedIndex,sourceType);
450
                Integer calculated = new Integer(calculatedIndex);
451
                String theID = (String) mapIndex2FID.get(calculated);
452
                mapFID2index.remove(calculated);
453
                mapIndex2FID.remove(theID);
454

    
455
        }
456
        public void cancelEdition(int sourceType) throws CancelEditingLayerException {
457
                super.cancelEdition(sourceType);
458
                mapFID2index.clear();
459
                mapIndex2FID.clear();
460
        }
461

    
462
        public void stopEdition(IWriter writer, int sourceType) throws StopWriterVisitorException{
463
                super.stopEdition(writer, sourceType);
464
                mapFID2index.clear();
465
                mapIndex2FID.clear();
466
        }
467
        public int getNewIndex(){
468
                int index = maxIndex+1;
469
                while(mapFID2index.containsKey(String.valueOf(index))){
470
                        index++;
471
                }
472
                return index;
473
        }
474

    
475
}