Statistics
| Revision:

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

History | View | Annotate | Download (44.7 KB)

1
package com.iver.cit.gvsig.fmap.edition;
2

    
3
import java.io.IOException;
4
import java.util.ArrayList;
5
import java.util.Collection;
6
import java.util.HashMap;
7
import java.util.Iterator;
8
import java.util.TreeMap;
9

    
10
import com.hardcode.driverManager.Driver;
11
import com.hardcode.driverManager.DriverLoadException;
12
import com.hardcode.gdbms.engine.data.DataSourceFactory;
13
import com.hardcode.gdbms.engine.data.NoSuchTableException;
14
import com.hardcode.gdbms.engine.data.driver.DriverException;
15
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
16
import com.hardcode.gdbms.engine.data.edition.DataWare;
17
import com.hardcode.gdbms.engine.values.Value;
18
import com.iver.cit.gvsig.fmap.core.DefaultRow;
19
import com.iver.cit.gvsig.fmap.core.IRow;
20
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
21
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
22
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
23
import com.iver.cit.gvsig.fmap.drivers.TableDefinition;
24
import com.iver.cit.gvsig.fmap.edition.commands.AddFieldCommand;
25
import com.iver.cit.gvsig.fmap.edition.commands.AddRowCommand;
26
import com.iver.cit.gvsig.fmap.edition.commands.Command;
27
import com.iver.cit.gvsig.fmap.edition.commands.CommandCollection;
28
import com.iver.cit.gvsig.fmap.edition.commands.CommandRecord;
29
import com.iver.cit.gvsig.fmap.edition.commands.MemoryCommandRecord;
30
import com.iver.cit.gvsig.fmap.edition.commands.ModifyRowCommand;
31
import com.iver.cit.gvsig.fmap.edition.commands.RemoveFieldCommand;
32
import com.iver.cit.gvsig.fmap.edition.commands.RemoveRowCommand;
33
import com.iver.cit.gvsig.fmap.edition.commands.RenameFieldCommand;
34
import com.iver.cit.gvsig.fmap.edition.fieldmanagers.AbstractFieldManager;
35
import com.iver.cit.gvsig.fmap.edition.rules.IRule;
36
import com.iver.cit.gvsig.fmap.layers.FBitSet;
37
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
38
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
39
import com.iver.cit.gvsig.fmap.operations.Cancel;
40

    
41
/**
42
 * DOCUMENT ME!
43
 * 
44
 * @author Vicente Caballero Navarro
45
 */
46
public class EditableAdapter implements IEditableSource, IWriteable {
47
        protected boolean isEditing = false;
48

    
49
        private SelectableDataSource ds = null;
50

    
51
        protected FBitSet delRows = new FBitSet();
52

    
53
        private CommandRecord cr;
54

    
55
        protected IWriter writer;
56

    
57
        /**
58
         * Flag que indica que hay que tomar las siguientes operaciones como una
59
         * operaci?n at?mica
60
         */
61
        private boolean complex = false;
62

    
63
        private CommandCollection commands = null;
64

    
65
        protected ArrayList listFields = new ArrayList();
66

    
67
        protected ArrayList listInternalFields = new ArrayList();
68
        
69
        protected boolean bFieldsHasBeenChanged = false;
70

    
71
        /**
72
         * La clave ser? el fieldId. Para buscar si un value de una row ha de ser
73
         * rellenado con defaultValue o con lo que venga del expansion file,
74
         * miraremos si existe en este hash. Si existe, usamos el value del
75
         * expansion file. Si no existe, usamos el defaultValue del campo busc?ndolo
76
         * en la lista internalFields. Por cierto, en listInternalFields NO se
77
         * borran campos. Solo se van a?adiendo nuevos actualFields.
78
         */
79
        protected TreeMap actualFields; // la clave ser? el fieldId.
80
        
81
        protected ArrayList fastAccessFields = new ArrayList();
82

    
83
        protected class MyFieldManager extends AbstractFieldManager {
84

    
85
                public boolean alterTable() throws EditionException {
86
                        return getFieldManager().alterTable();
87
                }
88

    
89
                public void addField(FieldDescription fieldDesc) {
90
                        super.addField(fieldDesc);
91
                }
92

    
93
                public FieldDescription removeField(String fieldName) {
94
                        // TODO Auto-generated method stub
95
                        return super.removeField(fieldName);
96
                }
97

    
98
                public void renameField(String antName, String newName) {
99
                        // TODO Auto-generated method stub
100
                        super.renameField(antName, newName);
101
                }
102

    
103
        }
104

    
105
        /*
106
         * Establece una relaci?n entre los ?ndices de las geometr?as en el
107
         * EditableFeatureSource y los ?ndices en el fichero de expansi?n FJP:
108
         * CAMBIO: NECESITAMOS TRABAJAR CON FEATURE Y FEATUREITERATOR PARA IR
109
         * PREPARANDO EL CAMINO, GUARDAMOS EL FEATUREID (STRING) COMO CLAVE, Y COMO
110
         * VALOR, EL INDICE DENTRO DEL FICHERO DE EXPANSION (Integer). Lo de que
111
         * FeatureId sea un String es por compatibilidad con OGC. Seg?n OGC, una
112
         * Feature tiene que tener un Id string En el caso de los randomaccess,
113
         * ser?n el id de registro En los casos de base de datos espaciales, supongo
114
         * que siempre ser? num?rico tambi?n, pero lo tendremos que convertir a
115
         * string. Lo que est? claro es que NO se puede confiar nunca en que sea
116
         * algo correlativo (1, 2, 3, 4, 5, ... => FALSO!!)
117
         */
118
        protected HashMap relations = new HashMap();
119

    
120
        /*
121
         * Fichero en el que se guardan las nuevas geometr?as, producto de adiciones
122
         * o de modificaciones
123
         */
124
        protected ExpansionFile expansionFile;
125

    
126
        protected int numAdd = 0;
127

    
128
        private ObjectDriver editingDriver = new myObjectDriver();
129

    
130
        private SelectableDataSource ods;
131

    
132
        private ArrayList editionListeners = new ArrayList();
133

    
134
        private ArrayList rules = new ArrayList();
135

    
136
        protected int actualIndexFields;
137

    
138
        /**
139
         * Crea un nuevo EditableAdapter.
140
         */
141
        public EditableAdapter() {
142
                expansionFile = new MemoryExpansionFile(this);
143
                cr = new MemoryCommandRecord();
144
        }
145

    
146
        /**
147
         * DOCUMENT ME!
148
         * 
149
         * @param ds
150
         *            DOCUMENT ME!
151
         * @throws DriverException 
152
         */
153
        public void setOriginalDataSource(SelectableDataSource ds) throws DriverException {
154
                this.ods = ds;
155
                initalizeFields(ds);
156
                
157
        }
158

    
159
        /**
160
         * @param ds
161
         * @throws DriverException
162
         */
163
        private void initalizeFields(SelectableDataSource ds) throws DriverException {
164
                FieldDescription[] fields = ds.getFieldsDescription();
165
                listInternalFields.clear();
166
                actualIndexFields = 0;
167
                actualFields = new TreeMap();
168
//                fastAccessFields = new ArrayList();
169
                for (int i=0; i < fields.length; i++)
170
                {
171
                        InternalField field = new InternalField(fields[i], InternalField.ORIGINAL, new Integer(i));
172
                        listFields.add(field);
173
                        // field.setFieldIndex(i);
174
                        actualFields.put(field.getFieldId(), field);
175
//                        fastAccessFields.add(fields[i]);
176
                        System.out.println("INITIALIZEFIELDS: FIELD " + field.getFieldDesc().getFieldAlias());
177
                }
178
                try {
179
                        fieldsChanged();
180
                        bFieldsHasBeenChanged = false;
181
                } catch (EditionException e) {
182
                        e.printStackTrace();
183
                        throw new DriverException(e);
184
                }
185
        }
186

    
187
        private void fieldsChanged() throws EditionException {
188
                fastAccessFields= new ArrayList();
189
                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
190
                        InternalField fld = (InternalField) iter.next();
191
                        fastAccessFields.add(fld.getFieldDesc());
192
                }
193

    
194
                listInternalFields.add(actualFields.clone());
195
                actualIndexFields = listInternalFields.size()-1;
196
                try {
197
                        ds = null;
198
                        getRecordset().mapExternalFields();
199
                        bFieldsHasBeenChanged = true;
200
                } catch (DriverLoadException e) {
201
                        e.printStackTrace();
202
                        throw new EditionException(e);
203
                } catch (DriverException e) {
204
                        e.printStackTrace();
205
                        throw new EditionException(e);
206
                }
207
        }
208

    
209
        /**
210
         * DOCUMENT ME!
211
         * 
212
         * @throws EditionException
213
         *             DOCUMENT ME!
214
         */
215
        public void startEdition(int sourceType) throws EditionException {
216
                isEditing = true;
217
                // Obtenemos el driver y vemos si implementa IWriter.
218
                /*
219
                 * DataWare dataWare =
220
                 * ods.getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
221
                 * dataWare.get
222
                 */
223
                Driver drv = ods.getDriver();
224
                if (drv instanceof IWriteable) {
225
                        setWriter(((IWriteable) drv).getWriter());
226
                }
227

    
228
                fireStartEditionEvent(sourceType);
229
        }
230

    
231
        /**
232
         * Se ejecuta preProcess() del IWriter, luego se itera por los registros
233
         * borrados por si el IWriter los quiere borrar (solo ser? necesario cuando
234
         * escribimos sobre la misma tabla) y luego se itera por los nuevos
235
         * registros llamando a process con el registro correcto. (A?adidos,
236
         * modificados). Para finalizar, se ejecuta PostProcess
237
         * 
238
         * @param writer
239
         *            IWriter que recibir? las llamadas.
240
         * 
241
         * @throws EditionException
242
         *             DOCUMENT ME!
243
         */
244
        public void stopEdition(IWriter writer, int sourceType)
245
                        throws EditionException {
246
                saveEdits(writer, sourceType);
247
                isEditing = false;
248
                cr.clearAll();
249
                fireStopEditionEvent(sourceType);
250
        }
251

    
252
        public void saveEdits(IWriter writer, int sourceType)
253
                        throws EditionException {
254
                
255
                // TODO: ARREGLAR ESTO PARA QUE CUANDO HA HABIDO CAMBIOS
256
                // EN LOS CAMPOS, PODAMOS CAMBIAR LO QUE TOQUE (A SER POSIBLE
257
                // SIN TENER QUE REESCRIBIR TODA LA TABLA CON POSTGIS)
258
                if (bFieldsHasBeenChanged)
259
                {
260
                        // Para cada campo de los originales, miramos si no est? en 
261
                        // los actuales. Si no est?, le decimos al fieldManager
262
                        // que lo borre. Si est?, pero le hemos cambiado el nombre
263
                        // le pedimos al fieldManager que le cambie el nombre.
264
                        // Luego recorremos los campos actuales para ver cuales
265
                        // son nuevos, y los a?adimos.
266
 
267
                        TreeMap ancientFields = (TreeMap) listInternalFields
268
                                        .get(0);
269
                        Collection aux = ancientFields.values();
270
                        Iterator it = aux.iterator();
271
                        while (it.hasNext()) {
272
                                InternalField fld = (InternalField) it.next();
273
                                // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
274
                                if (actualFields.containsKey(fld.getFieldId())) {
275
                                        // Es un original
276
                                        String f1 = fld.getFieldDesc().getFieldName();
277
                                        String f2 = fld.getFieldDesc().getFieldAlias();
278
                                        if (f1.compareTo(f2) != 0)
279
                                        {
280
                                                getFieldManager().renameField(f1, f2);
281
                                        }        
282
                                }
283
                                else
284
                                {        // No est?, hay que borrarlo
285
                                        getFieldManager().removeField(fld.getFieldDesc().getFieldAlias());
286
                                }
287
                        }
288
                        Collection aux2= actualFields.values();
289
                        Iterator it2 = aux2.iterator();
290
                        while (it2.hasNext()) {
291
                                InternalField fld = (InternalField) it2.next();
292
                                // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
293
                                if (!ancientFields.containsKey(fld.getFieldId())) {
294
                                        // Es uno a?adido
295
                                        getFieldManager().addField(fld.getFieldDesc());
296
                                }
297
                        }
298
                        // getFieldManager().alterTable(); // Se llama dentro del preprocess()
299
                }
300
                
301
                writer.preProcess();
302

    
303
                try {
304

    
305
                        // Procesamos primero los borrados.
306
                        // Cuando se genere un tema nuevo, no se les debe hacer caso
307
                        // a estos registros
308

    
309
                        for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
310
                                        .nextSetBit(i + 1)) {
311
                                int calculatedIndex = i;
312
                                Integer integer = new Integer(calculatedIndex);
313
                                // Si no est? en el fichero de expansi?n, es de los originales
314
                                // y hay que borrarlo
315
                                DefaultRowEdited edRow = null;
316
                                if (!relations.containsKey(integer)) {
317
                                        edRow = new DefaultRowEdited(new DefaultRow(ods
318
                                                        .getRow(calculatedIndex)),
319
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
320
                                        writer.process(edRow);
321
                                } else {
322
                                        int num = ((Integer) relations.get(integer)).intValue();
323

    
324
                                        // return expansionFile.getRow(num);
325
                                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
326
                                        // ?Habr?a que hacer aqu? setID(index + "")?
327
                                        edRow = new DefaultRowEdited(rowFromExpansion
328
                                                        .getLinkedRow().cloneRow(),
329
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
330
                                        writer.process(edRow);
331
                                }
332

    
333
                        }
334

    
335
                        int rowCount = getRowCount();
336
                        for (int i = 0; i < rowCount; i++) {
337
                                IRowEdited rowEdited = getRow(i);
338

    
339
                                if (rowEdited != null) {
340
                                        writer.process(rowEdited);
341
                                }
342
                        }
343
                        writer.postProcess();
344

    
345
                        // Hacemos que el escritor se entere de los nuevos campos
346
                        // que tiene. El escritor debe guardar una referencia
347
                        // a los campos con los que trabaja el drier, de forma
348
                        // que al recargar la capa (por ejemplo en el caso de
349
                        // PostGIS, se haga un setData con los campos que se hayan
350
                        // a?adido, borrado o renombrado).
351
                        writer.getTableDefinition().setFieldsDesc(getRecordset().getFieldsDescription());
352

    
353
                        ods.reload();
354
                        ds = null;
355
                        clean();
356
                        
357
                } catch (DriverIOException e) {
358
                        e.printStackTrace();
359
                        throw new EditionException(e);
360
                } catch (IOException e) {
361
                        e.printStackTrace();
362
                        throw new EditionException(e);
363
                } catch (DriverException e) {
364
                        e.printStackTrace();
365
                        throw new EditionException(e);
366
                }
367

    
368
        }
369

    
370
        /**
371
         * DOCUMENT ME!
372
         * 
373
         * @throws IOException
374
         *             DOCUMENT ME!
375
         */
376
        public void cancelEdition(int sourceType) throws IOException {
377
                isEditing = false;
378
                try {
379
                        ds= null;
380
                        clean();
381
                        cr.clearAll();
382
                } catch (DriverException e) {
383
                        e.printStackTrace();
384
                        throw new IOException("Error: " + e.getMessage());
385
                }
386
                fireCancelEditionEvent(sourceType);
387
        }
388

    
389
        /*
390
         * (non-Javadoc)
391
         * 
392
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getRow(int)
393
         */
394
        public IRowEdited getRow(int index) throws DriverIOException, IOException {
395
                int calculatedIndex = getCalculatedIndex(index);
396
                Integer integer = new Integer(calculatedIndex);
397
                DefaultRowEdited edRow = null;
398
                // Si no est? en el fichero de expansi?n
399
                if (!relations.containsKey(integer)) {
400
                        try {
401
                                /*
402
                                 * edRow = new DefaultRowEdited(new
403
                                 * DefaultRow(ods.getRow(calculatedIndex), "" + index),
404
                                 * DefaultRowEdited.STATUS_ORIGINAL, index);
405
                                 */
406
                                DefaultRow auxR = new DefaultRow(ods.getRow(calculatedIndex));
407
                                edRow = new DefaultRowEdited(auxR,
408
                                                DefaultRowEdited.STATUS_ORIGINAL, index);
409
                                return createExternalRow(edRow, 0);
410
//                                edRow = new DefaultRowEdited(new DefaultRow(ods
411
//                                                .getRow(calculatedIndex)),
412
//                                                DefaultRowEdited.STATUS_ORIGINAL, index);
413
                        } catch (DriverException e) {
414
                                throw new DriverIOException(e);
415
                        }
416
                } else {
417
                        int num = ((Integer) relations.get(integer)).intValue();
418

    
419
                        // return expansionFile.getRow(num);
420
                        // ExpansionFile ya entrega el registro formateado como debe
421
                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
422
                        // ?Habr?a que hacer aqu? setID(index + "")?
423
                        edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
424
                                        .cloneRow(), rowFromExpansion.getStatus(), index);
425
                        return edRow;
426
                }
427
                
428
                
429

    
430
        }
431

    
432
        /**
433
         * DOCUMENT ME!
434
         * 
435
         * @return DOCUMENT ME!
436
         * 
437
         * @throws DriverIOException
438
         *             DOCUMENT ME!
439
         * @throws IOException
440
         *             DOCUMENT ME!
441
         */
442
        public int getRowCount() throws DriverIOException, IOException {
443
                try {
444
                        return (int) (ods.getRowCount() + numAdd) - delRows.cardinality();// -
445
                        // expansionFile.getInvalidRows().cardinality();
446
                } catch (DriverException e) {
447
                        throw new DriverIOException(e);
448
                }
449

    
450
        }
451

    
452
        /*
453
         * (non-Javadoc)
454
         * 
455
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
456
         *      java.lang.String)
457
         */
458
        public int addRow(IRow row, String descrip, int sourceType)
459
                        throws DriverIOException, IOException {
460

    
461
                try {
462
                        validateRow(row);
463
                } catch (EditionException e) {
464
                        e.printStackTrace();
465
                        throw new IOException(e.getMessage());
466
                }
467

    
468
                int calculatedIndex = doAddRow(row, sourceType);
469
                Command command = new AddRowCommand(this, row, calculatedIndex,
470
                                sourceType);
471
                command.setDescription(descrip);
472
                if (complex) {
473
                        commands.add(command);
474
                } else {
475
                        cr.pushCommand(command);
476
                }
477

    
478
                return calculatedIndex;
479
        }
480

    
481
        /**
482
         * DOCUMENT ME!
483
         * 
484
         * @throws DriverIOException
485
         *             DOCUMENT ME!
486
         * @throws IOException
487
         *             DOCUMENT ME!
488
         */
489
        public void undo() throws DriverIOException, IOException {
490
                // seleccion.clear();
491
                if (cr.moreUndoCommands()) {
492
                        cr.undoCommand();
493
                }
494
        }
495

    
496
        /**
497
         * DOCUMENT ME!
498
         * 
499
         * @throws DriverIOException
500
         *             DOCUMENT ME!
501
         * @throws IOException
502
         *             DOCUMENT ME!
503
         */
504
        public void redo() throws DriverIOException, IOException {
505
                // seleccion.clear();
506
                if (cr.moreRedoCommands()) {
507
                        cr.redoCommand();
508
                }
509
        }
510

    
511
        /*
512
         * (non-Javadoc)
513
         * 
514
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
515
         */
516
        public void removeRow(int index, String descrip, int sourceType)
517
                        throws IOException, DriverIOException {
518

    
519
                int calculatedIndex = getCalculatedIndex(index);
520
                Command command = new RemoveRowCommand(this, calculatedIndex,
521
                                sourceType);
522
                command.setDescription(descrip);
523
                if (complex) {
524
                        commands.add(command);
525
                } else {
526
                        cr.pushCommand(command);
527
                }
528
                doRemoveRow(calculatedIndex, sourceType);
529

    
530
        }
531

    
532
        /*
533
         * (non-Javadoc)
534
         * 
535
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#modifyRow(int,
536
         *      com.iver.cit.gvsig.fmap.core.IRow)
537
         */
538
        public int modifyRow(int index, IRow row, String descrip, int sourceType)
539
                        throws IOException, DriverIOException {
540

    
541
                try {
542
                        validateRow(row);
543
                } catch (EditionException e) {
544
                        e.printStackTrace();
545
                        throw new IOException(e.getMessage());
546
                }
547

    
548
                int calculatedIndex = getCalculatedIndex(index);
549
                int pos = doModifyRow(calculatedIndex, row, sourceType);
550
                Command command = new ModifyRowCommand(this, calculatedIndex, pos, row,
551
                                sourceType);
552
                command.setDescription(descrip);
553
                if (complex) {
554
                        commands.add(command);
555
                } else {
556
                        cr.pushCommand(command);
557
                }
558

    
559
                return pos;
560
        }
561

    
562
        /**
563
         * DOCUMENT ME!
564
         */
565
        public void compact() {
566
                expansionFile.compact(relations);
567
        }
568

    
569
        /**
570
         * DOCUMENT ME!
571
         */
572
        public void startComplexRow() {
573
                complex = true;
574
                commands = new CommandCollection();
575
        }
576

    
577
        /**
578
         * DOCUMENT ME!
579
         * 
580
         * @throws IOException
581
         *             DOCUMENT ME!
582
         * @throws DriverIOException
583
         *             DOCUMENT ME!
584
         */
585
        public void endComplexRow(String description) throws IOException,
586
                        DriverIOException {
587
                commands.setDescription(description);
588
                cr.pushCommand(commands);
589
                complex = false;
590
        }
591

    
592
        /**
593
         * Actualiza en el mapa de ?ndices, la posici?n en la que estaba la
594
         * geometr?a antes de ser modificada. Se marca como v?lida, en caso de que
595
         * fuera una modificaci?n de una geometr?a que estuviese en el fichero de
596
         * expansi?n antes de ser modificada y se pone el puntero de escritura del
597
         * expansion file a justo despues de la penultima geometr?a
598
         * 
599
         * @param geometryIndex
600
         *            ?ndice de la geometr?a que se quiere deshacer su modificaci?n
601
         * @param previousExpansionFileIndex
602
         *            ?ndice que ten?a antes la geometr?a en el expansionFile. Si
603
         *            vale -1 quiere decir que es una modificaci?n de una geometr?a
604
         *            original y por tanto no hay que actualizar el mapa de indices
605
         *            sino eliminar su entrada.
606
         * 
607
         * @throws IOException
608
         * @throws DriverIOException
609
         */
610
        public void undoModifyRow(int geometryIndex,
611
                        int previousExpansionFileIndex, int sourceType) throws IOException,
612
                        DriverIOException {
613

    
614
                if (previousExpansionFileIndex == -1) {
615
                        DefaultRowEdited edRow = null;
616
                        try {
617
                                edRow = new DefaultRowEdited(new DefaultRow(ods
618
                                                .getRow(geometryIndex)),
619
                                                DefaultRowEdited.STATUS_ORIGINAL, geometryIndex);
620
                        } catch (DriverException e) {
621
                                e.printStackTrace();
622
                        }
623
                        boolean cancel = fireBeforeModifyRow(edRow, geometryIndex,
624
                                        sourceType);
625
                        if (cancel)
626
                                return;
627
                        // Se elimina de las relaciones y del fichero de expansi?n
628
                        relations.remove(new Integer(geometryIndex));
629
                        expansionFile.deleteLastRow();
630
                } else {
631
                        boolean cancel = fireBeforeModifyRow(expansionFile
632
                                        .getRow(previousExpansionFileIndex), geometryIndex,
633
                                        sourceType);
634
                        if (cancel)
635
                                return;
636
                        // Se actualiza la relaci?n de ?ndices
637
                        relations.put(new Integer(geometryIndex), new Integer(
638
                                        previousExpansionFileIndex));
639
                }
640
                fireAfterModifyRow(geometryIndex, sourceType);
641
        }
642

    
643
        /**
644
         * Elimina una geometria. Si es una geometr?a original de la capa en edici?n
645
         * se marca como eliminada (haya sido modificada o no). Si es una geometr?a
646
         * a?adida posteriormente se invalida en el fichero de expansi?n, para que
647
         * una futura compactaci?n termine con ella.
648
         * 
649
         * @param index
650
         *            ?ndice de la geometr?a.
651
         * 
652
         * @throws DriverIOException
653
         * @throws IOException
654
         */
655
        public IRow doRemoveRow(int index, int sourceType)
656
                        throws DriverIOException, IOException {
657
                boolean cancel = fireBeforeRemoveRow(index, sourceType);
658
                if (cancel)
659
                        return null;
660
                // Llega un calculatedIndex
661
                delRows.set(index, true);
662
                System.err.println("Elimina una Row en la posici?n: " + index);
663
                // TODO: Con tablas no es necesario devolver la anterior feature. Por
664
                // ahora.
665
                fireAfterRemoveRow(index, sourceType);
666
                return null;
667
        }
668

    
669
        /**
670
         * Si se intenta modificar una geometr?a original de la capa en edici?n se
671
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
672
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
673
         * fichero de expansi?n (por ser nueva o original pero modificada) se invoca
674
         * el m?todo modifyGeometry y se actualiza el ?ndice de la geometria en el
675
         * fichero.
676
         * 
677
         * @param index
678
         *            DOCUMENT ME!
679
         * @param feat
680
         *            DOCUMENT ME!
681
         * 
682
         * @return DOCUMENT ME!
683
         * 
684
         * @throws IOException
685
         * @throws DriverIOException
686
         */
687
        public int doModifyRow(int index, IRow feat, int sourceType)
688
                        throws IOException, DriverIOException {
689
                boolean cancel = fireBeforeModifyRow(feat, index, sourceType);
690
                if (cancel)
691
                        return -1;
692

    
693
                int pos = -1;
694
                Integer integer = new Integer(index);
695
                System.err.println("Modifica una Row en la posici?n: " + index);
696
                // Si la geometr?a no ha sido modificada
697
                if (!relations.containsKey(integer)) {
698
                        int expansionIndex = expansionFile.addRow(feat,
699
                                        IRowEdited.STATUS_MODIFIED, actualIndexFields);
700
                        relations.put(integer, new Integer(expansionIndex));
701
                } else {
702
                        // Obtenemos el ?ndice en el fichero de expansi?n
703
                        int num = ((Integer) relations.get(integer)).intValue();
704
                        pos = num;
705

    
706
                        /*
707
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
708
                         * fichero de expansi?n en el que se encuentra la geometr?a
709
                         * modificada
710
                         */
711
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
712

    
713
                        /*
714
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
715
                         * fichero de expansi?n.
716
                         */
717
                        relations.put(integer, new Integer(num));
718
                }
719
                fireAfterModifyRow(index, sourceType);
720
                return pos;
721
        }
722

    
723
        /**
724
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
725
         * en la tabla relations.
726
         * 
727
         * @param feat
728
         *            geometr?a a guardar.
729
         * 
730
         * @return calculatedIndex
731
         * 
732
         * @throws DriverIOException
733
         * @throws IOException
734
         */
735
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
736
                        IOException {
737
                boolean cancel = fireBeforeRowAdded(sourceType);
738
                if (cancel)
739
                        return -1;
740
                // A?ade la geometr?a
741
                // int virtualIndex = 0;
742
                int calculatedIndex = -1;
743

    
744
                try {
745
                        calculatedIndex = (int) ods.getRowCount() + numAdd;
746
                        // int externalIndex = getRowCount();
747
                        // calculatedIndex = getCalculatedIndex(externalIndex);
748
                } catch (DriverException e) {
749
                        throw new DriverIOException(e);
750
                }
751

    
752
                int pos = expansionFile.addRow(feat, IRowEdited.STATUS_ADDED, actualIndexFields);
753
                relations.put(new Integer(calculatedIndex), new Integer(pos));
754
                numAdd++;
755
                System.err.println("A?ade una Row en la posici?n: " + calculatedIndex);
756
                fireAfterRowAdded(calculatedIndex, sourceType);
757
                return calculatedIndex;
758
        }
759

    
760
        /**
761
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
762
         * en el fichero original
763
         * 
764
         * @param index
765
         *            DOCUMENT ME!
766
         * 
767
         * @throws IOException
768
         * @throws DriverIOException
769
         */
770
        public void undoRemoveRow(int index, int sourceType) throws IOException,
771
                        DriverIOException {
772
                boolean cancel = fireBeforeRowAdded(sourceType);
773
                if (cancel)
774
                        return;
775
                delRows.set(index, false);
776
                fireAfterRowAdded(index, sourceType);
777
        }
778

    
779
        /**
780
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
781
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
782
         * relaci?n del mapa de relaciones
783
         * 
784
         * @param index
785
         *            ?ndice de la geometr?a que se a?adi?
786
         * 
787
         * @throws DriverIOException
788
         * @throws IOException
789
         */
790
        public void undoAddRow(int calculatedIndex, int sourceType)
791
                        throws DriverIOException, IOException {
792
                boolean cancel = fireBeforeRemoveRow(calculatedIndex, sourceType);
793
                if (cancel)
794
                        return;
795
                expansionFile.deleteLastRow();
796
                relations.remove(new Integer(calculatedIndex));
797
                numAdd--;
798
                fireAfterRemoveRow(calculatedIndex, sourceType);
799
        }
800

    
801
        /*
802
         * (non-Javadoc)
803
         * 
804
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
805
         */
806
        public SelectableDataSource getRecordset() throws DriverLoadException {
807
                if (isEditing) {
808
                        if (ds == null) {
809
                                String name = LayerFactory.getDataSourceFactory()
810
                                                .addDataSource((ObjectDriver) editingDriver);
811

    
812
                                try {
813
                                        
814
                                        ds = new SelectableDataSource(LayerFactory
815
                                                        .getDataSourceFactory().createRandomDataSource(
816
                                                                        name, DataSourceFactory.MANUAL_OPENING));
817
                                        ds.start();
818
                                        ds.setSelectionSupport(ods.getSelectionSupport());
819

    
820
                                } catch (NoSuchTableException e) {
821
                                        throw new RuntimeException(e);
822
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
823
                                        throw new RuntimeException(e);
824
                                }
825
                        }
826

    
827
                        return ds;
828
                } else {
829
                        return ods;
830
                }
831
        }
832

    
833

    
834
        /**
835
         * DOCUMENT ME!
836
         * 
837
         * @return
838
         */
839
        public FBitSet getSelection() {
840
                /*
841
                 * try { return getRecordset().getSelection(); } catch
842
                 * (DriverLoadException e) { // TODO Auto-generated catch block
843
                 * e.printStackTrace(); } return null;
844
                 */
845
                return getRecordset().getSelection();
846
        }
847

    
848
        public void setSelection(FBitSet selection) {
849
                /*
850
                 * try { getRecordset().setSelection(selection); } catch
851
                 * (DriverLoadException e) { // TODO Auto-generated catch block
852
                 * e.printStackTrace(); }
853
                 */
854
                getRecordset().setSelection(selection);
855
        }
856

    
857
        /**
858
         * DOCUMENT ME!
859
         * 
860
         * @return DOCUMENT ME!
861
         */
862
        public boolean isEditing() {
863
                return isEditing;
864
        }
865

    
866
        public int getInversedIndex(long rowIndex) {
867
                int intervalNotDeleted = 0;
868
                int antDeleted = -1;
869
                int idPedido = (int) rowIndex;
870
                int numNotDeleted = 0;
871
                int numBorradosAnt = 0;
872

    
873
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
874
                                .nextSetBit(i + 1)) {
875
                        intervalNotDeleted = i - antDeleted - 1;
876
                        numNotDeleted += intervalNotDeleted;
877
                        if (i > idPedido) {
878
                                numNotDeleted = numNotDeleted + (i - idPedido);
879
                                break;
880
                        }
881
                        numBorradosAnt++;
882
                        antDeleted = i;
883
                }
884
                numNotDeleted = idPedido - numBorradosAnt;
885
                // System.out.println("Piden Viejo : "+ rowIndex + " y devuelvo como
886
                // nuevo " + (numNotDeleted));
887
                return numNotDeleted;
888
        }
889

    
890
        /**
891
         * DOCUMENT ME!
892
         * 
893
         * @param rowIndex
894
         *            DOCUMENT ME!
895
         * 
896
         * @return DOCUMENT ME!
897
         */
898
        public int getCalculatedIndex(long rowIndex) {
899
                int numNotDeleted = 0;
900
                int intervalNotDeleted = 0;
901
                int antDeleted = -1;
902
                int calculatedIndex;
903
                int idPedido = (int) rowIndex;
904
                int numBorradosAnt = 0;
905

    
906
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
907
                                .nextSetBit(i + 1)) {
908
                        intervalNotDeleted = i - antDeleted - 1;
909
                        numNotDeleted += intervalNotDeleted;
910
                        if (numNotDeleted > idPedido) {
911
                                break;
912
                        }
913
                        numBorradosAnt++;
914
                        antDeleted = i;
915
                }
916
                calculatedIndex = numBorradosAnt + idPedido;
917
                // System.out.println("Piden Registro : "+ rowIndex + " y devuelvo el "
918
                // + (calculatedIndex));
919
                return calculatedIndex;
920
        }
921

    
922
        /**
923
         * DOCUMENT ME!
924
         * 
925
         * @author Vicente Caballero Navarro
926
         */
927
        private class myObjectDriver implements ObjectDriver {
928
                /*
929
                 * (non-Javadoc)
930
                 * 
931
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
932
                 */
933
                public int[] getPrimaryKeys() throws DriverException {
934
                        return ods.getPrimaryKeys();
935
                        // int[] pk=new int[1];
936
                        /*
937
                         * for (int i=0;i<getRowCount();i++){ pk[i]=i; }
938
                         */
939
                        // pk[0]=1;
940
                        // return pk;
941
                }
942

    
943
                /*
944
                 * (non-Javadoc)
945
                 * 
946
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
947
                 */
948
                public void write(DataWare dataWare) throws DriverException {
949
                        DataWare dataWareOrig = ods
950
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
951
                        dataWareOrig.commitTrans();
952
                }
953

    
954
                /*
955
                 * (non-Javadoc)
956
                 * 
957
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
958
                 */
959
                public void setDataSourceFactory(DataSourceFactory dsf) {
960
                        ods.setDataSourceFactory(dsf);
961
                }
962

    
963
                /*
964
                 * (non-Javadoc)
965
                 * 
966
                 * @see com.hardcode.driverManager.Driver#getName()
967
                 */
968
                public String getName() {
969
                        return ods.getName();
970
                }
971

    
972
                /*
973
                 * (non-Javadoc)
974
                 * 
975
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
976
                 *      int)
977
                 */
978
                public Value getFieldValue(long rowIndex, int fieldId)
979
                                throws DriverException {
980
                        // Si no est? en el fichero de expansi?n
981
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
982

    
983

    
984
                        try {
985
                                IRow row = getRow((int)rowIndex);
986
                                return row.getAttribute(fieldId);
987
//                                if (!relations.containsKey(integer)) {
988
//                                        return ods.getFieldValue(rowIndex, fieldId);
989
//                                } else {
990
//                                        int num = ((Integer) relations.get(integer)).intValue();
991
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
992
//                                                        .getRow(num);
993
//
994
//                                        if (feat == null) {
995
//                                                return null;
996
//                                        }
997
//
998
//                                        return feat.getAttribute(fieldId);
999
//                                }
1000
//                        } catch (DriverException e) {
1001
//                                e.printStackTrace();
1002
//                                throw new DriverException(e);
1003
                        } catch (IOException e) {
1004
                                e.printStackTrace();
1005
                                throw new DriverException(e);
1006
                        } catch (DriverIOException e) {
1007
                                e.printStackTrace();
1008
                                throw new DriverException(e);
1009
                        }
1010

    
1011
                        /**
1012
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
1013
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
1014
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
1015
                         * num = ((Integer) relations.get(integer)).intValue();
1016
                         * DefaultRowEdited feat = (DefaultRowEdited)
1017
                         * expansionFile.getRow(num); if (feat==null)return null; return
1018
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
1019
                         * e.printStackTrace(); throw new DriverException(e); } catch
1020
                         * (IOException e) { e.printStackTrace(); throw new
1021
                         * DriverException(e); }
1022
                         */
1023
                }
1024

    
1025
                /*
1026
                 * (non-Javadoc)
1027
                 * 
1028
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1029
                 */
1030
                public int getFieldCount() throws DriverException {
1031
                        return fastAccessFields.size();
1032
                }
1033

    
1034
                /*
1035
                 * (non-Javadoc)
1036
                 * 
1037
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
1038
                 */
1039
                public String getFieldName(int fieldId) throws DriverException {
1040
//                        int i=0;
1041
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1042
//                                InternalField fld = (InternalField) iter.next();
1043
//                                if (i == fieldId)
1044
//                                        return fld.getFieldDesc().getFieldAlias();
1045
//                                i++;
1046
//                                
1047
//                        }
1048
//                        throw new DriverException("FieldId " + fieldId + " not found ");
1049
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1050
                        return aux.getFieldAlias();
1051
                        // return null;
1052
                        // return ods.getFieldName(fieldId);
1053
                }
1054

    
1055
                /*
1056
                 * (non-Javadoc)
1057
                 * 
1058
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1059
                 */
1060
                public long getRowCount() {
1061
                        try {
1062
                                return (int) (ods.getRowCount() + numAdd)
1063
                                                - delRows.cardinality();// -
1064
                                // expansionFile.getInvalidRows().cardinality();
1065
                        } catch (DriverException e) {
1066
                                // TODO Auto-generated catch block
1067
                                e.printStackTrace();
1068
                        }
1069

    
1070
                        return 0;
1071
                }
1072

    
1073
                /*
1074
                 * (non-Javadoc)
1075
                 * 
1076
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1077
                 */
1078
                public int getFieldType(int fieldId) throws DriverException {
1079
//                        int i=0;
1080
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1081
//                                InternalField fld = (InternalField) iter.next();
1082
//                                if (i == fieldId)
1083
//                                        return fld.getFieldDesc().getFieldType();
1084
//                                i++;
1085
//                                
1086
//                        }
1087
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1088
                        return aux.getFieldType();
1089
                        
1090
//                        return ods.getFieldType(i);
1091
                }
1092

    
1093
                public int getFieldWidth(int fieldId) throws DriverException {
1094
//                        int i=0;
1095
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {                                
1096
//                                InternalField fld = (InternalField) iter.next();
1097
////                                if (fld.getFieldIndex() == i)
1098
////                                        return fld.getFieldDesc().getFieldLength();
1099
//                                if (i == fieldId)
1100
//                                        return fld.getFieldDesc().getFieldLength();
1101
//                                i++;
1102
//                                
1103
//                        }
1104
//
1105
//                        return ods.getFieldWidth(i);
1106
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1107
                        return aux.getFieldLength();
1108

    
1109
                }
1110

    
1111
                public void reload() throws IOException, DriverException {
1112
                        ods.reload();
1113
                        
1114
                }
1115
        }
1116

    
1117
        public CommandRecord getCommandRecord() {
1118
                return cr;
1119
        }
1120

    
1121
        protected void fireAfterRemoveRow(int index, int sourceType) {
1122
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1123
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1124
                for (int i = 0; i < editionListeners.size(); i++) {
1125
                        IEditionListener listener = (IEditionListener) editionListeners
1126
                                        .get(i);
1127
                        listener.afterRowEditEvent(null, event);
1128
                }
1129

    
1130
        }
1131

    
1132
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1133
                Cancel cancel = new Cancel();
1134
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1135
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1136
                for (int i = 0; i < editionListeners.size(); i++) {
1137
                        IEditionListener listener = (IEditionListener) editionListeners
1138
                                        .get(i);
1139
                        listener.beforeRowEditEvent(null, event);
1140
                        if (cancel.isCanceled())
1141
                                return true;
1142
                }
1143
                return false;
1144
        }
1145

    
1146
        protected void fireAfterRowAdded(int calculatedIndex, int sourceType) {
1147
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1148
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1149
                for (int i = 0; i < editionListeners.size(); i++) {
1150
                        IEditionListener listener = (IEditionListener) editionListeners
1151
                                        .get(i);
1152
                        listener.afterRowEditEvent(null, event);
1153
                }
1154
        }
1155

    
1156
        protected void fireAfterFieldAdded(FieldDescription field) {
1157
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1158
                                EditionEvent.CHANGE_TYPE_ADD);
1159
                for (int i = 0; i < editionListeners.size(); i++) {
1160
                        IEditionListener listener = (IEditionListener) editionListeners
1161
                                        .get(i);
1162
                        listener.afterFieldEditEvent(event);
1163
                }
1164
        }
1165

    
1166
        protected void fireAfterFieldRemoved(FieldDescription field) {
1167
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1168
                                EditionEvent.CHANGE_TYPE_DELETE);
1169
                for (int i = 0; i < editionListeners.size(); i++) {
1170
                        IEditionListener listener = (IEditionListener) editionListeners
1171
                                        .get(i);
1172
                        listener.afterFieldEditEvent(event);
1173
                }
1174
        }
1175

    
1176
        protected void fireAfterFieldModified(FieldDescription field) {
1177
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1178
                                EditionEvent.CHANGE_TYPE_MODIFY);
1179
                for (int i = 0; i < editionListeners.size(); i++) {
1180
                        IEditionListener listener = (IEditionListener) editionListeners
1181
                                        .get(i);
1182
                        listener.afterFieldEditEvent(event);
1183
                }
1184
        }
1185
        
1186
        
1187
        protected boolean fireBeforeRowAdded(int sourceType)
1188
                        throws DriverIOException, IOException {
1189
                Cancel cancel = new Cancel();
1190
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, getRowCount(),
1191
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1192
                for (int i = 0; i < editionListeners.size(); i++) {
1193
                        IEditionListener listener = (IEditionListener) editionListeners
1194
                                        .get(i);
1195
                        listener.beforeRowEditEvent(null, event);
1196
                        if (cancel.isCanceled())
1197
                                return true;
1198
                }
1199
                return false;
1200
        }
1201

    
1202
        protected boolean fireBeforeFieldAdded(FieldDescription field)
1203
        throws EditionException {
1204
                Cancel cancel = new Cancel();
1205
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1206
                EditionEvent.CHANGE_TYPE_ADD, cancel);
1207
                for (int i = 0; i < editionListeners.size(); i++) {
1208
                        IEditionListener listener = (IEditionListener) editionListeners
1209
                        .get(i);
1210
                        listener.beforeFieldEditEvent(event);
1211
                        if (cancel.isCanceled())
1212
                                return true;
1213
                }
1214
                return false;
1215
        }
1216

    
1217
        protected boolean fireBeforeRemoveField(FieldDescription field)
1218
        throws EditionException {
1219
                Cancel cancel = new Cancel();
1220
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1221
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1222
                for (int i = 0; i < editionListeners.size(); i++) {
1223
                        IEditionListener listener = (IEditionListener) editionListeners
1224
                        .get(i);
1225
                        listener.beforeFieldEditEvent(event);
1226
                        if (cancel.isCanceled())
1227
                                return true;
1228
                }
1229
                return false;
1230
        }
1231

    
1232
        
1233
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1234
                Cancel cancel = new Cancel();
1235
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1236
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1237
                for (int i = 0; i < editionListeners.size(); i++) {
1238
                        IEditionListener listener = (IEditionListener) editionListeners
1239
                                        .get(i);
1240
                        listener.beforeRowEditEvent(feat, event);
1241
                        if (cancel.isCanceled())
1242
                                return true;
1243
                }
1244
                return false;
1245
        }
1246

    
1247
        protected void fireAfterModifyRow(int index, int sourceType) {
1248
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1249
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1250
                for (int i = 0; i < editionListeners.size(); i++) {
1251
                        IEditionListener listener = (IEditionListener) editionListeners
1252
                                        .get(i);
1253
                        listener.afterRowEditEvent(null, event);
1254
                }
1255

    
1256
        }
1257

    
1258
        protected void fireStartEditionEvent(int sourceType) {
1259
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1260
                                sourceType);
1261
                for (int i = 0; i < editionListeners.size(); i++) {
1262
                        IEditionListener listener = (IEditionListener) editionListeners
1263
                                        .get(i);
1264
                        listener.processEvent(ev);
1265
                }
1266

    
1267
        }
1268

    
1269
        protected void fireStopEditionEvent(int sourceType) {
1270
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1271
                                sourceType);
1272
                for (int i = 0; i < editionListeners.size(); i++) {
1273
                        IEditionListener listener = (IEditionListener) editionListeners
1274
                                        .get(i);
1275
                        listener.processEvent(ev);
1276
                }
1277

    
1278
        }
1279

    
1280
        protected void fireCancelEditionEvent(int sourceType) {
1281
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1282
                                sourceType);
1283
                for (int i = 0; i < editionListeners.size(); i++) {
1284
                        IEditionListener listener = (IEditionListener) editionListeners
1285
                                        .get(i);
1286
                        listener.processEvent(ev);
1287
                }
1288

    
1289
        }
1290

    
1291
        public void addEditionListener(IEditionListener listener) {
1292
                if (!editionListeners.contains(listener))
1293
                        editionListeners.add(listener);
1294
        }
1295

    
1296
        public void removeEditionListener(IEditionListener listener) {
1297
                editionListeners.remove(listener);
1298
        }
1299

    
1300
        public IWriter getWriter() {
1301
                return writer;
1302
        }
1303

    
1304
        protected void setWriter(IWriter writer) {
1305
                this.writer = writer;
1306

    
1307
        }
1308

    
1309
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1310
                        DriverException {
1311
                TableDefinition tableDef = new TableDefinition();
1312
                tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1313
                tableDef.setName(getRecordset().getSourceInfo().name);
1314
                return tableDef;
1315
        }
1316

    
1317
        public void validateRow(IRow row) throws EditionException {
1318
                for (int i = 0; i < rules.size(); i++) {
1319
                        IRule rule = (IRule) rules.get(i);
1320
                        boolean bAux = rule.validate(row);
1321
                        if (bAux == false) {
1322
                                EditionException ex = new EditionException(
1323
                                                "NOT follow the rule: " + rule.getDescription());
1324
                                // TODO: Lanzar una RuleException con datos como el registro
1325
                                // que no cumple, la regla que no lo ha cumplido, etc.
1326
                                throw ex;
1327
                        }
1328
                }
1329
        }
1330

    
1331
        public ArrayList getRules() {
1332
                return rules;
1333
        }
1334

    
1335
        public void setRules(ArrayList rules) {
1336
                this.rules = rules;
1337
        }
1338

    
1339
        private void clean() throws IOException, DriverException {
1340
                expansionFile.close();
1341
                relations.clear();
1342
                numAdd = 0;
1343
                delRows.clear();
1344
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1345
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1346
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1347
                // reload completo.
1348
                initalizeFields(ods);
1349
                
1350
//                listInternalFields.clear();
1351
//                listInternalFields.add(actualFields);
1352
        }
1353

    
1354
        /*
1355
         * (non-Javadoc)
1356
         * 
1357
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1358
         */
1359
        public IFieldManager getFieldManager() {
1360
                if (ods.getDriver() instanceof IWriteable)
1361
                {
1362
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1363
                        if ((writer != null) && (writer instanceof IFieldManager))
1364
                        {
1365
                                IFieldManager fldManager = (IFieldManager) writer;
1366
                                return fldManager;
1367
                        }
1368
                }
1369
                return null;
1370
        }
1371

    
1372
        /**
1373
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1374
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1375
         * 
1376
         * @param edRow
1377
         * @param indexInternalFields
1378
         * @return
1379
         */
1380
        public IRowEdited createExternalRow(IRowEdited edRow,
1381
                        int indexInternalFields) {
1382
                
1383
                // para acelerar
1384
                if (bFieldsHasBeenChanged == false)
1385
                        return edRow;
1386
                
1387
                Value[] att = edRow.getAttributes();
1388
                TreeMap ancientFields = (TreeMap) listInternalFields
1389
                                .get(indexInternalFields);
1390
                Value[] newAtt = new Value[actualFields.size()];
1391
                Collection aux = actualFields.values();
1392
                Iterator it = aux.iterator();
1393
                int i = 0;
1394
                Value val = null;
1395
                while (it.hasNext()) {
1396
                        // Para cada campo de los actuales, miramos si ya estaba cuando
1397
                        // el registro estaba guardado. 
1398
                        // Si estaba, cogemos el valor de ese campo en el registro
1399
                        // guardado. Si no estaba, ha sido a?adido despu?s y ponemos
1400
                        // su valor por defecto.
1401
                        // Nota importante: fieldIndex es el ?ndice del campo cuando
1402
                        // se guard?. NO es el ?ndice actual dentro de actualFields.
1403
                        // Se usa SOLO para recuperar el valor de los atributos
1404
                        // antiguos. Por eso no nos preocupamos de mantener actuallizados
1405
                        // el resto de campos cuando se borra o a?ade un nuevo campo.
1406
                        InternalField fld = (InternalField) it.next();
1407
                        // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
1408
                        if (ancientFields.containsKey(fld.getFieldId())) {
1409
                                InternalField ancientField = (InternalField) ancientFields
1410
                                                .get(fld.getFieldId());
1411
                                // val = att[ancientField.getFieldIndex()];
1412
                                val = att[ancientField.getFieldId().intValue()];
1413
                                // System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + " val" + val);
1414
                        } else
1415
                                val = fld.getFieldDesc().getDefaultValue();
1416
                        newAtt[i++] = val;
1417
                }
1418
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1419
                newRow.setAttributes(newAtt);
1420
                return newRow;
1421
        }
1422

    
1423
        public void removeField(String fieldName) throws EditionException {
1424

    
1425
                InternalField fld = findFieldByName(fieldName);
1426
                if (fld == null)
1427
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1428
                Command command = new RemoveFieldCommand(this, fld);
1429
                if (complex) {
1430
                        commands.add(command);
1431
                } else {
1432
                        cr.pushCommand(command);
1433
                }
1434
                doRemoveField(fld);
1435

    
1436
        }
1437

    
1438
        private InternalField findFieldByName(String fieldName) {
1439
                Collection aux = actualFields.values();
1440
                Iterator it = aux.iterator();
1441
                while (it.hasNext()) {
1442
                        InternalField fld = (InternalField) it.next();
1443
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1444
                                return fld;
1445
                }
1446
                
1447
                return null;
1448
        }
1449

    
1450
        public void undoRemoveField(InternalField field) throws EditionException {
1451
                // field.setDeleted(false);
1452
//                field.setFieldIndex(actualFields.size());
1453
                actualFields.put(field.getFieldId(), field);
1454
                fieldsChanged();
1455
                fireAfterFieldAdded(field.getFieldDesc());
1456
        }
1457

    
1458
        public void doRemoveField(InternalField field) throws EditionException {
1459
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1460
                if (cancel) return;
1461
                actualFields.remove(field.getFieldId());
1462
                fieldsChanged();
1463
                fireAfterFieldRemoved(field.getFieldDesc());
1464
        }
1465

    
1466
        public void renameField(String antName, String newName) throws EditionException {
1467

    
1468
                InternalField fld = findFieldByName(antName);
1469
                Command command = new RenameFieldCommand(this, fld, newName);
1470
                if (complex) {
1471
                        commands.add(command);
1472
                } else {
1473
                        cr.pushCommand(command);
1474
                }
1475
                doRenameField(fld, newName);
1476

    
1477
        }
1478
        
1479
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1480
                field.getFieldDesc().setFieldAlias(antName);
1481
                fieldsChanged();
1482
                fireAfterFieldModified(field.getFieldDesc());
1483

    
1484
        }
1485

    
1486
        public void doRenameField(InternalField field, String newName) throws EditionException  {
1487
                field.getFieldDesc().setFieldAlias(newName);
1488
                fieldsChanged();
1489
                fireAfterFieldModified(field.getFieldDesc());
1490

    
1491
        }
1492

    
1493

    
1494
        public void addField(FieldDescription field) throws EditionException {
1495

    
1496
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1497
                Command command = new AddFieldCommand(this, fld);
1498
                if (complex) {
1499
                        commands.add(command);
1500
                } else {
1501
                        cr.pushCommand(command);
1502
                }
1503
                listFields.add(fld);
1504
                doAddField(fld);
1505

    
1506
        }
1507

    
1508
        public void undoAddField(InternalField field) throws EditionException {
1509
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1510
                if (cancel)
1511
                        return;
1512

    
1513
                // field.setDeleted(true);
1514
                actualFields.remove(field.getFieldId());
1515
                fieldsChanged();
1516
                fireAfterFieldRemoved(field.getFieldDesc());
1517
                
1518
        }
1519

    
1520
        public int doAddField(InternalField field) throws EditionException {
1521
                boolean cancel;
1522
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1523
                if (cancel)
1524
                        return -1;
1525

    
1526
                // field.setDeleted(false);
1527
//                field.setFieldIndex(actualFields.size());
1528
                actualFields.put(field.getFieldId(), field);
1529
                fieldsChanged();
1530
                fireAfterFieldAdded(field.getFieldDesc());
1531
//                return field.getFieldIndex();
1532
                return field.getFieldId().intValue();
1533
        }
1534
        
1535
        public Driver getOriginalDriver()
1536
        {
1537
                return ods.getDriver();
1538
        }
1539
        
1540
        /**
1541
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1542
         * to be created next time it is needed
1543
         */
1544
        public void cleanSelectableDatasource() {
1545
                ds = null;
1546
        }
1547

    
1548
        public FieldDescription[] getFieldsDescription() {
1549
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1550
        }
1551

    
1552
        
1553
//        private InternalField getInternalFieldByIndex(int fieldId)
1554
//        {
1555
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1556
//                        InternalField fld = (InternalField) iter.next();
1557
//                        if (fld.getFieldIndex() == fieldId)
1558
//                                return fld;
1559
//                }
1560
//                return null;
1561
//        }
1562
        
1563
}