Statistics
| Revision:

svn-gvsig-desktop / tags / v10_RC2c / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / EditableAdapter.java @ 8745

History | View | Annotate | Download (45 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
        protected boolean isFullExtentDirty = false;
139

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

    
148
        /**
149
         * DOCUMENT ME!
150
         *
151
         * @param ds
152
         *            DOCUMENT ME!
153
         * @throws DriverException
154
         */
155
        public void setOriginalDataSource(SelectableDataSource ds) throws DriverException {
156
                this.ods = ds;
157
                initalizeFields(ds);
158
                Driver drv = ods.getDriver();
159
                if (drv instanceof IWriteable) {
160
                        setWriter(((IWriteable) drv).getWriter());
161
                }
162

    
163

    
164
        }
165

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

    
194
        private TreeMap deepCloneInternalFields(TreeMap col)
195
        {
196
                TreeMap clonedFields = new TreeMap();
197
                for (Iterator iter = col.values().iterator(); iter.hasNext();) {
198
                        InternalField fld = (InternalField) iter.next();
199
                        InternalField clonedField = fld.cloneInternalField();
200
                        clonedFields.put(clonedField.getFieldId(), clonedField);
201
                }
202

    
203
                return clonedFields;
204
        }
205
        private void fieldsChanged() throws EditionException {
206
                fastAccessFields= new ArrayList();
207
                int index = 0;
208
                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
209
                        InternalField fld = (InternalField) iter.next();
210
                        fastAccessFields.add(fld.getFieldDesc());
211
                        fld.setFieldIndex(index++);
212
                }
213

    
214
                listInternalFields.add(deepCloneInternalFields(actualFields));
215
                actualIndexFields = listInternalFields.size()-1;
216
                try {
217
                        ds = null;
218
                        getRecordset().mapExternalFields();
219
                        bFieldsHasBeenChanged = true;
220
                } catch (DriverLoadException e) {
221
                        e.printStackTrace();
222
                        throw new EditionException(e);
223
                } catch (DriverException e) {
224
                        e.printStackTrace();
225
                        throw new EditionException(e);
226
                }
227
        }
228

    
229
        /**
230
         * DOCUMENT ME!
231
         *
232
         * @throws EditionException
233
         *             DOCUMENT ME!
234
         */
235
        public void startEdition(int sourceType) throws EditionException {
236
                isEditing = true;
237

    
238
                fireStartEditionEvent(sourceType);
239
        }
240

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

    
263
        public void saveEdits(IWriter writer, int sourceType)
264
                        throws EditionException {
265

    
266
                // TODO: ARREGLAR ESTO PARA QUE CUANDO HA HABIDO CAMBIOS
267
                // EN LOS CAMPOS, PODAMOS CAMBIAR LO QUE TOQUE (A SER POSIBLE
268
                // SIN TENER QUE REESCRIBIR TODA LA TABLA CON POSTGIS)
269
                if (bFieldsHasBeenChanged)
270
                {
271
                        // Para cada campo de los originales, miramos si no est? en
272
                        // los actuales. Si no est?, le decimos al fieldManager
273
                        // que lo borre. Si est?, pero le hemos cambiado el nombre
274
                        // le pedimos al fieldManager que le cambie el nombre.
275
                        // Luego recorremos los campos actuales para ver cuales
276
                        // son nuevos, y los a?adimos.
277

    
278
                        TreeMap ancientFields = (TreeMap) listInternalFields
279
                                        .get(0);
280
                        Collection aux = ancientFields.values();
281
                        Iterator it = aux.iterator();
282
                        while (it.hasNext()) {
283
                                InternalField fld = (InternalField) it.next();
284
                                // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
285
                                if (actualFields.containsKey(fld.getFieldId())) {
286
                                        // Es un original
287
                                        String f1 = fld.getFieldDesc().getFieldName();
288
                                        String f2 = fld.getFieldDesc().getFieldAlias();
289
                                        if (f1.compareTo(f2) != 0)
290
                                        {
291
                                                getFieldManager().renameField(f1, f2);
292
                                        }
293
                                }
294
                                else
295
                                {        // No est?, hay que borrarlo
296
                                        getFieldManager().removeField(fld.getFieldDesc().getFieldAlias());
297
                                }
298
                        }
299
                        Collection aux2= actualFields.values();
300
                        Iterator it2 = aux2.iterator();
301
                        while (it2.hasNext()) {
302
                                InternalField fld = (InternalField) it2.next();
303
                                // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
304
                                if (!ancientFields.containsKey(fld.getFieldId())) {
305
                                        // Es uno a?adido
306
                                        getFieldManager().addField(fld.getFieldDesc());
307
                                }
308
                        }
309
                        // getFieldManager().alterTable(); // Se llama dentro del preprocess()
310
                }
311

    
312
                writer.preProcess();
313

    
314
                try {
315

    
316
                        // Procesamos primero los borrados.
317
                        // Cuando se genere un tema nuevo, no se les debe hacer caso
318
                        // a estos registros
319

    
320
                        for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
321
                                        .nextSetBit(i + 1)) {
322
                                int calculatedIndex = i;
323
                                Integer integer = new Integer(calculatedIndex);
324
                                // Si no est? en el fichero de expansi?n, es de los originales
325
                                // y hay que borrarlo
326
                                DefaultRowEdited edRow = null;
327
                                if (!relations.containsKey(integer)) {
328
                                        edRow = new DefaultRowEdited(new DefaultRow(ods
329
                                                        .getRow(calculatedIndex)),
330
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
331
                                        writer.process(edRow);
332
                                } else {
333
                                        int num = ((Integer) relations.get(integer)).intValue();
334

    
335
                                        // return expansionFile.getRow(num);
336
                                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
337
                                        // ?Habr?a que hacer aqu? setID(index + "")?
338
                                        edRow = new DefaultRowEdited(rowFromExpansion
339
                                                        .getLinkedRow().cloneRow(),
340
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
341
                                        writer.process(edRow);
342
                                }
343

    
344
                        }
345

    
346
                        int rowCount = getRowCount();
347
                        for (int i = 0; i < rowCount; i++) {
348
                                IRowEdited rowEdited = getRow(i);
349

    
350
                                if (rowEdited != null) {
351
                                        writer.process(rowEdited);
352
                                }
353
                        }
354
                        writer.postProcess();
355

    
356
                        // Hacemos que el escritor se entere de los nuevos campos
357
                        // que tiene. El escritor debe guardar una referencia
358
                        // a los campos con los que trabaja el drier, de forma
359
                        // que al recargar la capa (por ejemplo en el caso de
360
                        // PostGIS, se haga un setData con los campos que se hayan
361
                        // a?adido, borrado o renombrado).
362
                        writer.getTableDefinition().setFieldsDesc(getRecordset().getFieldsDescription());
363

    
364
                        ods.reload();
365
                        ds = null;
366
                        clean();
367

    
368
                } catch (DriverIOException e) {
369
                        e.printStackTrace();
370
                        throw new EditionException(e);
371
                } catch (IOException e) {
372
                        e.printStackTrace();
373
                        throw new EditionException(e);
374
                } catch (DriverException e) {
375
                        e.printStackTrace();
376
                        throw new EditionException(e);
377
                }
378

    
379
        }
380

    
381
        /**
382
         * DOCUMENT ME!
383
         *
384
         * @throws IOException
385
         *             DOCUMENT ME!
386
         */
387
        public void cancelEdition(int sourceType) throws IOException {
388
                isEditing = false;
389
                try {
390
                        ds= null;
391
                        clean();
392
                        cr.clearAll();
393
                } catch (DriverException e) {
394
                        e.printStackTrace();
395
                        throw new IOException("Error: " + e.getMessage());
396
                }
397
                fireCancelEditionEvent(sourceType);
398
        }
399

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

    
430
                        // return expansionFile.getRow(num);
431
                        // ExpansionFile ya entrega el registro formateado como debe
432
                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
433
                        // ?Habr?a que hacer aqu? setID(index + "")?
434
                        edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
435
                                        .cloneRow(), rowFromExpansion.getStatus(), index);
436
                        return edRow;
437
                }
438

    
439

    
440

    
441
        }
442

    
443
        /**
444
         * DOCUMENT ME!
445
         *
446
         * @return DOCUMENT ME!
447
         *
448
         * @throws DriverIOException
449
         *             DOCUMENT ME!
450
         * @throws IOException
451
         *             DOCUMENT ME!
452
         */
453
        public int getRowCount() throws DriverIOException, IOException {
454
                try {
455
                        return (int) (ods.getRowCount() + numAdd) - delRows.cardinality();// -
456
                        // expansionFile.getInvalidRows().cardinality();
457
                } catch (DriverException e) {
458
                        throw new DriverIOException(e);
459
                }
460

    
461
        }
462

    
463
        /*
464
         * (non-Javadoc)
465
         *
466
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
467
         *      java.lang.String)
468
         */
469
        public int addRow(IRow row, String descrip, int sourceType)
470
                        throws DriverIOException, IOException {
471

    
472
                try {
473
                        validateRow(row);
474
                } catch (EditionException e) {
475
                        e.printStackTrace();
476
                        throw new IOException(e.getMessage());
477
                }
478

    
479
                int calculatedIndex = doAddRow(row, sourceType);
480
                Command command = new AddRowCommand(this, row, calculatedIndex,
481
                                sourceType);
482
                command.setDescription(descrip);
483
                if (complex) {
484
                        commands.add(command);
485
                } else {
486
                        cr.pushCommand(command);
487
                }
488

    
489
                return calculatedIndex;
490
        }
491

    
492
        /**
493
         * DOCUMENT ME!
494
         *
495
         * @throws DriverIOException
496
         *             DOCUMENT ME!
497
         * @throws IOException
498
         *             DOCUMENT ME!
499
         */
500
        public void undo() throws DriverIOException, IOException {
501
                // seleccion.clear();
502
                if (cr.moreUndoCommands()) {
503
                        cr.undoCommand();
504
                }
505
        }
506

    
507
        /**
508
         * DOCUMENT ME!
509
         *
510
         * @throws DriverIOException
511
         *             DOCUMENT ME!
512
         * @throws IOException
513
         *             DOCUMENT ME!
514
         */
515
        public void redo() throws DriverIOException, IOException {
516
                // seleccion.clear();
517
                if (cr.moreRedoCommands()) {
518
                        cr.redoCommand();
519
                }
520
        }
521

    
522
        /*
523
         * (non-Javadoc)
524
         *
525
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
526
         */
527
        public void removeRow(int index, String descrip, int sourceType)
528
                        throws IOException, DriverIOException {
529

    
530
                int calculatedIndex = getCalculatedIndex(index);
531
                Command command = new RemoveRowCommand(this, calculatedIndex,
532
                                sourceType);
533
                command.setDescription(descrip);
534
                if (complex) {
535
                        commands.add(command);
536
                } else {
537
                        cr.pushCommand(command);
538
                }
539
                doRemoveRow(calculatedIndex, sourceType);
540

    
541
        }
542

    
543
        /*
544
         * (non-Javadoc)
545
         *
546
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#modifyRow(int,
547
         *      com.iver.cit.gvsig.fmap.core.IRow)
548
         */
549
        public int modifyRow(int index, IRow row, String descrip, int sourceType)
550
                        throws IOException, DriverIOException {
551

    
552
                try {
553
                        validateRow(row);
554
                } catch (EditionException e) {
555
                        e.printStackTrace();
556
                        throw new IOException(e.getMessage());
557
                }
558

    
559
                int calculatedIndex = getCalculatedIndex(index);
560
                int pos = doModifyRow(calculatedIndex, row, sourceType);
561
                Command command = new ModifyRowCommand(this, calculatedIndex, pos, row,
562
                                sourceType);
563
                command.setDescription(descrip);
564
                if (complex) {
565
                        commands.add(command);
566
                } else {
567
                        cr.pushCommand(command);
568
                }
569

    
570
                return pos;
571
        }
572

    
573
        /**
574
         * DOCUMENT ME!
575
         */
576
        public void compact() {
577
                expansionFile.compact(relations);
578
        }
579

    
580
        /**
581
         * DOCUMENT ME!
582
         */
583
        public void startComplexRow() {
584
                complex = true;
585
                commands = new CommandCollection();
586
        }
587

    
588
        /**
589
         * DOCUMENT ME!
590
         *
591
         * @throws IOException
592
         *             DOCUMENT ME!
593
         * @throws DriverIOException
594
         *             DOCUMENT ME!
595
         */
596
        public void endComplexRow(String description) throws IOException,
597
                        DriverIOException {
598
                commands.setDescription(description);
599
                cr.pushCommand(commands);
600
                complex = false;
601
        }
602

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

    
625
                if (previousExpansionFileIndex == -1) {
626
                        DefaultRowEdited edRow = null;
627
                        try {
628
                                edRow = new DefaultRowEdited(new DefaultRow(ods
629
                                                .getRow(geometryIndex)),
630
                                                DefaultRowEdited.STATUS_ORIGINAL, geometryIndex);
631
                        } catch (DriverException e) {
632
                                e.printStackTrace();
633
                        }
634
                        boolean cancel = fireBeforeModifyRow(edRow, geometryIndex,
635
                                        sourceType);
636
                        if (cancel)
637
                                return;
638
                        // Se elimina de las relaciones y del fichero de expansi?n
639
                        relations.remove(new Integer(geometryIndex));
640
                        expansionFile.deleteLastRow();
641
                } else {
642
                        boolean cancel = fireBeforeModifyRow(expansionFile
643
                                        .getRow(previousExpansionFileIndex), geometryIndex,
644
                                        sourceType);
645
                        if (cancel)
646
                                return;
647
                        // Se actualiza la relaci?n de ?ndices
648
                        relations.put(new Integer(geometryIndex), new Integer(
649
                                        previousExpansionFileIndex));
650
                }
651
                fireAfterModifyRow(geometryIndex, sourceType);
652
        }
653

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

    
681
        /**
682
         * Si se intenta modificar una geometr?a original de la capa en edici?n se
683
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
684
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
685
         * fichero de expansi?n (por ser nueva o original pero modificada) se invoca
686
         * el m?todo modifyGeometry y se actualiza el ?ndice de la geometria en el
687
         * fichero.
688
         *
689
         * @param index
690
         *            DOCUMENT ME!
691
         * @param feat
692
         *            DOCUMENT ME!
693
         *
694
         * @return DOCUMENT ME!
695
         *
696
         * @throws IOException
697
         * @throws DriverIOException
698
         */
699
        public int doModifyRow(int index, IRow feat, int sourceType)
700
                        throws IOException, DriverIOException {
701
                boolean cancel = fireBeforeModifyRow(feat, index, sourceType);
702
                if (cancel)
703
                        return -1;
704

    
705
                int pos = -1;
706
                Integer integer = new Integer(index);
707
                System.err.println("Modifica una Row en la posici?n: " + index);
708
                // Si la geometr?a no ha sido modificada
709
                if (!relations.containsKey(integer)) {
710
                        int expansionIndex = expansionFile.addRow(feat,
711
                                        IRowEdited.STATUS_MODIFIED, actualIndexFields);
712
                        relations.put(integer, new Integer(expansionIndex));
713
                } else {
714
                        // Obtenemos el ?ndice en el fichero de expansi?n
715
                        int num = ((Integer) relations.get(integer)).intValue();
716
                        pos = num;
717

    
718
                        /*
719
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
720
                         * fichero de expansi?n en el que se encuentra la geometr?a
721
                         * modificada
722
                         */
723
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
724

    
725
                        /*
726
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
727
                         * fichero de expansi?n.
728
                         */
729
                        relations.put(integer, new Integer(num));
730
                }
731
                isFullExtentDirty = true;
732
                fireAfterModifyRow(index, sourceType);
733
                return pos;
734
        }
735

    
736
        /**
737
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
738
         * en la tabla relations.
739
         *
740
         * @param feat
741
         *            geometr?a a guardar.
742
         *
743
         * @return calculatedIndex
744
         *
745
         * @throws DriverIOException
746
         * @throws IOException
747
         */
748
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
749
                        IOException {
750
                boolean cancel = fireBeforeRowAdded(sourceType);
751
                if (cancel)
752
                        return -1;
753
                // A?ade la geometr?a
754
                // int virtualIndex = 0;
755
                int calculatedIndex = -1;
756

    
757
                try {
758
                        calculatedIndex = (int) ods.getRowCount() + numAdd;
759
                        // int externalIndex = getRowCount();
760
                        // calculatedIndex = getCalculatedIndex(externalIndex);
761
                } catch (DriverException e) {
762
                        throw new DriverIOException(e);
763
                }
764

    
765
                int pos = expansionFile.addRow(feat, IRowEdited.STATUS_ADDED, actualIndexFields);
766
                relations.put(new Integer(calculatedIndex), new Integer(pos));
767
                numAdd++;
768
                System.err.println("A?ade una Row en la posici?n: " + calculatedIndex);
769
                isFullExtentDirty  = true;
770
                fireAfterRowAdded(calculatedIndex, sourceType);
771
                return calculatedIndex;
772
        }
773

    
774
        /**
775
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
776
         * en el fichero original
777
         *
778
         * @param index
779
         *            DOCUMENT ME!
780
         *
781
         * @throws IOException
782
         * @throws DriverIOException
783
         */
784
        public void undoRemoveRow(int index, int sourceType) throws IOException,
785
                        DriverIOException {
786
                boolean cancel = fireBeforeRowAdded(sourceType);
787
                if (cancel)
788
                        return;
789
                delRows.set(index, false);
790
                fireAfterRowAdded(index, sourceType);
791
        }
792

    
793
        /**
794
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
795
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
796
         * relaci?n del mapa de relaciones
797
         *
798
         * @param index
799
         *            ?ndice de la geometr?a que se a?adi?
800
         *
801
         * @throws DriverIOException
802
         * @throws IOException
803
         */
804
        public void undoAddRow(int calculatedIndex, int sourceType)
805
                        throws DriverIOException, IOException {
806
                boolean cancel = fireBeforeRemoveRow(calculatedIndex, sourceType);
807
                if (cancel)
808
                        return;
809
                expansionFile.deleteLastRow();
810
                relations.remove(new Integer(calculatedIndex));
811
                numAdd--;
812
                fireAfterRemoveRow(calculatedIndex, sourceType);
813
        }
814

    
815
        /*
816
         * (non-Javadoc)
817
         *
818
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
819
         */
820
        public SelectableDataSource getRecordset() throws DriverLoadException {
821
                if (isEditing) {
822
                        if (ds == null) {
823
                                String name = LayerFactory.getDataSourceFactory()
824
                                                .addDataSource((ObjectDriver) editingDriver);
825

    
826
                                try {
827

    
828
                                        ds = new SelectableDataSource(LayerFactory
829
                                                        .getDataSourceFactory().createRandomDataSource(
830
                                                                        name, DataSourceFactory.MANUAL_OPENING));
831
                                        ds.start();
832
                                        ds.setSelectionSupport(ods.getSelectionSupport());
833

    
834
                                } catch (NoSuchTableException e) {
835
                                        throw new RuntimeException(e);
836
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
837
                                        throw new RuntimeException(e);
838
                                }
839
                        }
840

    
841
                        return ds;
842
                } else {
843
                        return ods;
844
                }
845
        }
846

    
847

    
848
        /**
849
         * DOCUMENT ME!
850
         *
851
         * @return
852
         */
853
        public FBitSet getSelection() {
854
                /*
855
                 * try { return getRecordset().getSelection(); } catch
856
                 * (DriverLoadException e) { // TODO Auto-generated catch block
857
                 * e.printStackTrace(); } return null;
858
                 */
859
                return getRecordset().getSelection();
860
        }
861

    
862
        public void setSelection(FBitSet selection) {
863
                /*
864
                 * try { getRecordset().setSelection(selection); } catch
865
                 * (DriverLoadException e) { // TODO Auto-generated catch block
866
                 * e.printStackTrace(); }
867
                 */
868
                getRecordset().setSelection(selection);
869
        }
870

    
871
        /**
872
         * DOCUMENT ME!
873
         *
874
         * @return DOCUMENT ME!
875
         */
876
        public boolean isEditing() {
877
                return isEditing;
878
        }
879

    
880
        public int getInversedIndex(long rowIndex) {
881
                int intervalNotDeleted = 0;
882
                int antDeleted = -1;
883
                int idPedido = (int) rowIndex;
884
                int numNotDeleted = 0;
885
                int numBorradosAnt = 0;
886

    
887
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
888
                                .nextSetBit(i + 1)) {
889
                        intervalNotDeleted = i - antDeleted - 1;
890
                        numNotDeleted += intervalNotDeleted;
891
                        if (i > idPedido) {
892
                                numNotDeleted = numNotDeleted + (i - idPedido);
893
                                break;
894
                        }
895
                        numBorradosAnt++;
896
                        antDeleted = i;
897
                }
898
                numNotDeleted = idPedido - numBorradosAnt;
899
                // System.out.println("Piden Viejo : "+ rowIndex + " y devuelvo como
900
                // nuevo " + (numNotDeleted));
901
                return numNotDeleted;
902
        }
903

    
904
        /**
905
         * DOCUMENT ME!
906
         *
907
         * @param rowIndex
908
         *            DOCUMENT ME!
909
         *
910
         * @return DOCUMENT ME!
911
         */
912
        public int getCalculatedIndex(long rowIndex) {
913
                int numNotDeleted = 0;
914
                int intervalNotDeleted = 0;
915
                int antDeleted = -1;
916
                int calculatedIndex;
917
                int idPedido = (int) rowIndex;
918
                int numBorradosAnt = 0;
919

    
920
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
921
                                .nextSetBit(i + 1)) {
922
                        intervalNotDeleted = i - antDeleted - 1;
923
                        numNotDeleted += intervalNotDeleted;
924
                        if (numNotDeleted > idPedido) {
925
                                break;
926
                        }
927
                        numBorradosAnt++;
928
                        antDeleted = i;
929
                }
930
                calculatedIndex = numBorradosAnt + idPedido;
931
                // System.out.println("Piden Registro : "+ rowIndex + " y devuelvo el "
932
                // + (calculatedIndex));
933
                return calculatedIndex;
934
        }
935

    
936
        /**
937
         * DOCUMENT ME!
938
         *
939
         * @author Vicente Caballero Navarro
940
         */
941
        private class myObjectDriver implements ObjectDriver {
942
                /*
943
                 * (non-Javadoc)
944
                 *
945
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
946
                 */
947
                public int[] getPrimaryKeys() throws DriverException {
948
                        return ods.getPrimaryKeys();
949
                        // int[] pk=new int[1];
950
                        /*
951
                         * for (int i=0;i<getRowCount();i++){ pk[i]=i; }
952
                         */
953
                        // pk[0]=1;
954
                        // return pk;
955
                }
956

    
957
                /*
958
                 * (non-Javadoc)
959
                 *
960
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
961
                 */
962
                public void write(DataWare dataWare) throws DriverException {
963
                        DataWare dataWareOrig = ods
964
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
965
                        dataWareOrig.commitTrans();
966
                }
967

    
968
                /*
969
                 * (non-Javadoc)
970
                 *
971
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
972
                 */
973
                public void setDataSourceFactory(DataSourceFactory dsf) {
974
                        ods.setDataSourceFactory(dsf);
975
                }
976

    
977
                /*
978
                 * (non-Javadoc)
979
                 *
980
                 * @see com.hardcode.driverManager.Driver#getName()
981
                 */
982
                public String getName() {
983
                        return ods.getName();
984
                }
985

    
986
                /*
987
                 * (non-Javadoc)
988
                 *
989
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
990
                 *      int)
991
                 */
992
                public Value getFieldValue(long rowIndex, int fieldId)
993
                                throws DriverException {
994
                        // Si no est? en el fichero de expansi?n
995
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
996

    
997

    
998
                        try {
999
                                IRow row = getRow((int)rowIndex);
1000
                                return row.getAttribute(fieldId);
1001
//                                if (!relations.containsKey(integer)) {
1002
//                                        return ods.getFieldValue(rowIndex, fieldId);
1003
//                                } else {
1004
//                                        int num = ((Integer) relations.get(integer)).intValue();
1005
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
1006
//                                                        .getRow(num);
1007
//
1008
//                                        if (feat == null) {
1009
//                                                return null;
1010
//                                        }
1011
//
1012
//                                        return feat.getAttribute(fieldId);
1013
//                                }
1014
//                        } catch (DriverException e) {
1015
//                                e.printStackTrace();
1016
//                                throw new DriverException(e);
1017
                        } catch (IOException e) {
1018
                                e.printStackTrace();
1019
                                throw new DriverException(e);
1020
                        } catch (DriverIOException e) {
1021
                                e.printStackTrace();
1022
                                throw new DriverException(e);
1023
                        }
1024

    
1025
                        /**
1026
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
1027
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
1028
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
1029
                         * num = ((Integer) relations.get(integer)).intValue();
1030
                         * DefaultRowEdited feat = (DefaultRowEdited)
1031
                         * expansionFile.getRow(num); if (feat==null)return null; return
1032
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
1033
                         * e.printStackTrace(); throw new DriverException(e); } catch
1034
                         * (IOException e) { e.printStackTrace(); throw new
1035
                         * DriverException(e); }
1036
                         */
1037
                }
1038

    
1039
                /*
1040
                 * (non-Javadoc)
1041
                 *
1042
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1043
                 */
1044
                public int getFieldCount() throws DriverException {
1045
                        return fastAccessFields.size();
1046
                }
1047

    
1048
                /*
1049
                 * (non-Javadoc)
1050
                 *
1051
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
1052
                 */
1053
                public String getFieldName(int fieldId) throws DriverException {
1054
//                        int i=0;
1055
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1056
//                                InternalField fld = (InternalField) iter.next();
1057
//                                if (i == fieldId)
1058
//                                        return fld.getFieldDesc().getFieldAlias();
1059
//                                i++;
1060
//
1061
//                        }
1062
//                        throw new DriverException("FieldId " + fieldId + " not found ");
1063
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1064
                        return aux.getFieldAlias();
1065
                        // return null;
1066
                        // return ods.getFieldName(fieldId);
1067
                }
1068

    
1069
                /*
1070
                 * (non-Javadoc)
1071
                 *
1072
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1073
                 */
1074
                public long getRowCount() {
1075
                        try {
1076
                                return (int) (ods.getRowCount() + numAdd)
1077
                                                - delRows.cardinality();// -
1078
                                // expansionFile.getInvalidRows().cardinality();
1079
                        } catch (DriverException e) {
1080
                                // TODO Auto-generated catch block
1081
                                e.printStackTrace();
1082
                        }
1083

    
1084
                        return 0;
1085
                }
1086

    
1087
                /*
1088
                 * (non-Javadoc)
1089
                 *
1090
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1091
                 */
1092
                public int getFieldType(int fieldId) throws DriverException {
1093
//                        int i=0;
1094
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1095
//                                InternalField fld = (InternalField) iter.next();
1096
//                                if (i == fieldId)
1097
//                                        return fld.getFieldDesc().getFieldType();
1098
//                                i++;
1099
//
1100
//                        }
1101
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1102
                        return aux.getFieldType();
1103

    
1104
//                        return ods.getFieldType(i);
1105
                }
1106

    
1107
                public int getFieldWidth(int fieldId) throws DriverException {
1108
//                        int i=0;
1109
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1110
//                                InternalField fld = (InternalField) iter.next();
1111
////                                if (fld.getFieldIndex() == i)
1112
////                                        return fld.getFieldDesc().getFieldLength();
1113
//                                if (i == fieldId)
1114
//                                        return fld.getFieldDesc().getFieldLength();
1115
//                                i++;
1116
//
1117
//                        }
1118
//
1119
//                        return ods.getFieldWidth(i);
1120
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1121
                        return aux.getFieldLength();
1122

    
1123
                }
1124

    
1125
                public void reload() throws IOException, DriverException {
1126
                        ods.reload();
1127

    
1128
                }
1129
        }
1130

    
1131
        public CommandRecord getCommandRecord() {
1132
                return cr;
1133
        }
1134

    
1135
        protected void fireAfterRemoveRow(int index, int sourceType) {
1136
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1137
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1138
                for (int i = 0; i < editionListeners.size(); i++) {
1139
                        IEditionListener listener = (IEditionListener) editionListeners
1140
                                        .get(i);
1141
                        listener.afterRowEditEvent(null, event);
1142
                }
1143

    
1144
        }
1145

    
1146
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1147
                Cancel cancel = new Cancel();
1148
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1149
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1150
                for (int i = 0; i < editionListeners.size(); i++) {
1151
                        IEditionListener listener = (IEditionListener) editionListeners
1152
                                        .get(i);
1153
                        listener.beforeRowEditEvent(null, event);
1154
                        if (cancel.isCanceled())
1155
                                return true;
1156
                }
1157
                return false;
1158
        }
1159

    
1160
        protected void fireAfterRowAdded(int calculatedIndex, int sourceType) {
1161
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1162
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1163
                for (int i = 0; i < editionListeners.size(); i++) {
1164
                        IEditionListener listener = (IEditionListener) editionListeners
1165
                                        .get(i);
1166
                        listener.afterRowEditEvent(null, event);
1167
                }
1168
        }
1169

    
1170
        protected void fireAfterFieldAdded(FieldDescription field) {
1171
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1172
                                EditionEvent.CHANGE_TYPE_ADD);
1173
                for (int i = 0; i < editionListeners.size(); i++) {
1174
                        IEditionListener listener = (IEditionListener) editionListeners
1175
                                        .get(i);
1176
                        listener.afterFieldEditEvent(event);
1177
                }
1178
        }
1179

    
1180
        protected void fireAfterFieldRemoved(FieldDescription field) {
1181
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1182
                                EditionEvent.CHANGE_TYPE_DELETE);
1183
                for (int i = 0; i < editionListeners.size(); i++) {
1184
                        IEditionListener listener = (IEditionListener) editionListeners
1185
                                        .get(i);
1186
                        listener.afterFieldEditEvent(event);
1187
                }
1188
        }
1189

    
1190
        protected void fireAfterFieldModified(FieldDescription field) {
1191
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1192
                                EditionEvent.CHANGE_TYPE_MODIFY);
1193
                for (int i = 0; i < editionListeners.size(); i++) {
1194
                        IEditionListener listener = (IEditionListener) editionListeners
1195
                                        .get(i);
1196
                        listener.afterFieldEditEvent(event);
1197
                }
1198
        }
1199

    
1200

    
1201
        protected boolean fireBeforeRowAdded(int sourceType)
1202
                        throws DriverIOException, IOException {
1203
                Cancel cancel = new Cancel();
1204
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, getRowCount(),
1205
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1206
                for (int i = 0; i < editionListeners.size(); i++) {
1207
                        IEditionListener listener = (IEditionListener) editionListeners
1208
                                        .get(i);
1209
                        listener.beforeRowEditEvent(null, event);
1210
                        if (cancel.isCanceled())
1211
                                return true;
1212
                }
1213
                return false;
1214
        }
1215

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

    
1231
        protected boolean fireBeforeRemoveField(FieldDescription field)
1232
        throws EditionException {
1233
                Cancel cancel = new Cancel();
1234
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1235
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1236
                for (int i = 0; i < editionListeners.size(); i++) {
1237
                        IEditionListener listener = (IEditionListener) editionListeners
1238
                        .get(i);
1239
                        listener.beforeFieldEditEvent(event);
1240
                        if (cancel.isCanceled())
1241
                                return true;
1242
                }
1243
                return false;
1244
        }
1245

    
1246

    
1247
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1248
                Cancel cancel = new Cancel();
1249
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1250
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1251
                for (int i = 0; i < editionListeners.size(); i++) {
1252
                        IEditionListener listener = (IEditionListener) editionListeners
1253
                                        .get(i);
1254
                        listener.beforeRowEditEvent(feat, event);
1255
                        if (cancel.isCanceled())
1256
                                return true;
1257
                }
1258
                return false;
1259
        }
1260

    
1261
        protected void fireAfterModifyRow(int index, int sourceType) {
1262
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1263
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1264
                for (int i = 0; i < editionListeners.size(); i++) {
1265
                        IEditionListener listener = (IEditionListener) editionListeners
1266
                                        .get(i);
1267
                        listener.afterRowEditEvent(null, event);
1268
                }
1269

    
1270
        }
1271

    
1272
        protected void fireStartEditionEvent(int sourceType) {
1273
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1274
                                sourceType);
1275
                for (int i = 0; i < editionListeners.size(); i++) {
1276
                        IEditionListener listener = (IEditionListener) editionListeners
1277
                                        .get(i);
1278
                        listener.processEvent(ev);
1279
                }
1280

    
1281
        }
1282

    
1283
        protected void fireStopEditionEvent(int sourceType) {
1284
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1285
                                sourceType);
1286
                for (int i = 0; i < editionListeners.size(); i++) {
1287
                        IEditionListener listener = (IEditionListener) editionListeners
1288
                                        .get(i);
1289
                        listener.processEvent(ev);
1290
                }
1291

    
1292
        }
1293

    
1294
        protected void fireCancelEditionEvent(int sourceType) {
1295
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1296
                                sourceType);
1297
                for (int i = 0; i < editionListeners.size(); i++) {
1298
                        IEditionListener listener = (IEditionListener) editionListeners
1299
                                        .get(i);
1300
                        listener.processEvent(ev);
1301
                }
1302

    
1303
        }
1304

    
1305
        public void addEditionListener(IEditionListener listener) {
1306
                if (!editionListeners.contains(listener))
1307
                        editionListeners.add(listener);
1308
        }
1309

    
1310
        public void removeEditionListener(IEditionListener listener) {
1311
                editionListeners.remove(listener);
1312
        }
1313

    
1314
        public IWriter getWriter() {
1315
                return writer;
1316
        }
1317

    
1318
        protected void setWriter(IWriter writer) {
1319
                this.writer = writer;
1320

    
1321
        }
1322

    
1323
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1324
                        DriverException {
1325
                TableDefinition tableDef = new TableDefinition();
1326
                tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1327
                tableDef.setName(getRecordset().getSourceInfo().name);
1328
                return tableDef;
1329
        }
1330

    
1331
        public void validateRow(IRow row) throws EditionException {
1332
                for (int i = 0; i < rules.size(); i++) {
1333
                        IRule rule = (IRule) rules.get(i);
1334
                        boolean bAux = rule.validate(row);
1335
                        if (bAux == false) {
1336
                                EditionException ex = new EditionException(
1337
                                                "NOT follow the rule: " + rule.getDescription());
1338
                                // TODO: Lanzar una RuleException con datos como el registro
1339
                                // que no cumple, la regla que no lo ha cumplido, etc.
1340
                                throw ex;
1341
                        }
1342
                }
1343
        }
1344

    
1345
        public ArrayList getRules() {
1346
                return rules;
1347
        }
1348

    
1349
        public void setRules(ArrayList rules) {
1350
                this.rules = rules;
1351
        }
1352

    
1353
        private void clean() throws IOException, DriverException {
1354
                expansionFile.close();
1355
                relations.clear();
1356
                numAdd = 0;
1357
                delRows.clear();
1358
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1359
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1360
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1361
                // reload completo.
1362
                initalizeFields(ods);
1363

    
1364
//                listInternalFields.clear();
1365
//                listInternalFields.add(actualFields);
1366
        }
1367

    
1368
        /*
1369
         * (non-Javadoc)
1370
         *
1371
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1372
         */
1373
        public IFieldManager getFieldManager() {
1374
                if (ods.getDriver() instanceof IWriteable)
1375
                {
1376
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1377
                        if ((writer != null) && (writer instanceof IFieldManager))
1378
                        {
1379
                                IFieldManager fldManager = (IFieldManager) writer;
1380
                                return fldManager;
1381
                        }
1382
                }
1383
                return null;
1384
        }
1385

    
1386
        /**
1387
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1388
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1389
         *
1390
         * @param edRow
1391
         * @param indexInternalFields
1392
         * @return
1393
         */
1394
        public IRowEdited createExternalRow(IRowEdited edRow,
1395
                        int indexInternalFields) {
1396

    
1397
                // para acelerar
1398
                if (bFieldsHasBeenChanged == false)
1399
                        return edRow;
1400

    
1401
                Value[] att = edRow.getAttributes();
1402
                TreeMap ancientFields = (TreeMap) listInternalFields
1403
                                .get(indexInternalFields);
1404
                Value[] newAtt = new Value[actualFields.size()];
1405
                Collection aux = actualFields.values();
1406
                Iterator it = aux.iterator();
1407
                int i = 0;
1408
                Value val = null;
1409
                while (it.hasNext()) {
1410
                        // Para cada campo de los actuales, miramos si ya estaba cuando
1411
                        // el registro estaba guardado.
1412
                        // Si estaba, cogemos el valor de ese campo en el registro
1413
                        // guardado. Si no estaba, ha sido a?adido despu?s y ponemos
1414
                        // su valor por defecto.
1415
                        // Nota importante: fieldIndex es el ?ndice del campo cuando
1416
                        // se guard?. NO es el ?ndice actual dentro de actualFields.
1417
                        // Se usa SOLO para recuperar el valor de los atributos
1418
                        // antiguos. Por eso no nos preocupamos de mantener actuallizados
1419
                        // el resto de campos cuando se borra o a?ade un nuevo campo.
1420
                        InternalField fld = (InternalField) it.next();
1421
                        // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
1422
                        if (ancientFields.containsKey(fld.getFieldId())) {
1423
                                InternalField ancientField = (InternalField) ancientFields
1424
                                                .get(fld.getFieldId());
1425
                                val = att[ancientField.getFieldIndex()];
1426
                                // val = att[ancientField.getFieldId().intValue()];
1427
                                // System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + " val" + val);
1428
                        } else
1429
                                val = fld.getFieldDesc().getDefaultValue();
1430
                        newAtt[i++] = val;
1431
                }
1432
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1433
                newRow.setAttributes(newAtt);
1434
                return newRow;
1435
        }
1436

    
1437
        public void removeField(String fieldName) throws EditionException {
1438

    
1439
                InternalField fld = findFieldByName(fieldName);
1440
                if (fld == null)
1441
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1442
                Command command = new RemoveFieldCommand(this, fld);
1443
                if (complex) {
1444
                        commands.add(command);
1445
                } else {
1446
                        cr.pushCommand(command);
1447
                }
1448
                doRemoveField(fld);
1449

    
1450
        }
1451

    
1452
        private InternalField findFieldByName(String fieldName) {
1453
                Collection aux = actualFields.values();
1454
                Iterator it = aux.iterator();
1455
                while (it.hasNext()) {
1456
                        InternalField fld = (InternalField) it.next();
1457
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1458
                                return fld;
1459
                }
1460

    
1461
                return null;
1462
        }
1463

    
1464
        public void undoRemoveField(InternalField field) throws EditionException {
1465
                // field.setDeleted(false);
1466
//                field.setFieldIndex(actualFields.size());
1467
                actualFields.put(field.getFieldId(), field);
1468
                fieldsChanged();
1469
                fireAfterFieldAdded(field.getFieldDesc());
1470
        }
1471

    
1472
        public void doRemoveField(InternalField field) throws EditionException {
1473
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1474
                if (cancel) return;
1475
                actualFields.remove(field.getFieldId());
1476
                fieldsChanged();
1477
                fireAfterFieldRemoved(field.getFieldDesc());
1478
        }
1479

    
1480
        public void renameField(String antName, String newName) throws EditionException {
1481

    
1482
                InternalField fld = findFieldByName(antName);
1483
                Command command = new RenameFieldCommand(this, fld, newName);
1484
                if (complex) {
1485
                        commands.add(command);
1486
                } else {
1487
                        cr.pushCommand(command);
1488
                }
1489
                doRenameField(fld, newName);
1490

    
1491
        }
1492

    
1493
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1494
                field.getFieldDesc().setFieldAlias(antName);
1495
                fieldsChanged();
1496
                fireAfterFieldModified(field.getFieldDesc());
1497

    
1498
        }
1499

    
1500
        public void doRenameField(InternalField field, String newName) throws EditionException  {
1501
                field.getFieldDesc().setFieldAlias(newName);
1502
                fieldsChanged();
1503
                fireAfterFieldModified(field.getFieldDesc());
1504

    
1505
        }
1506

    
1507

    
1508
        public void addField(FieldDescription field) throws EditionException {
1509

    
1510
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1511
                Command command = new AddFieldCommand(this, fld);
1512
                if (complex) {
1513
                        commands.add(command);
1514
                } else {
1515
                        cr.pushCommand(command);
1516
                }
1517
                listFields.add(fld);
1518
                doAddField(fld);
1519

    
1520
        }
1521

    
1522
        public void undoAddField(InternalField field) throws EditionException {
1523
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1524
                if (cancel)
1525
                        return;
1526

    
1527
                // field.setDeleted(true);
1528
                actualFields.remove(field.getFieldId());
1529
                fieldsChanged();
1530
                fireAfterFieldRemoved(field.getFieldDesc());
1531

    
1532
        }
1533

    
1534
        public int doAddField(InternalField field) throws EditionException {
1535
                boolean cancel;
1536
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1537
                if (cancel)
1538
                        return -1;
1539

    
1540
                // field.setDeleted(false);
1541
//                field.setFieldIndex(actualFields.size());
1542
                actualFields.put(field.getFieldId(), field);
1543
                fieldsChanged();
1544
                fireAfterFieldAdded(field.getFieldDesc());
1545
//                return field.getFieldIndex();
1546
                return field.getFieldId().intValue();
1547
        }
1548

    
1549
        public Driver getOriginalDriver()
1550
        {
1551
                return ods.getDriver();
1552
        }
1553

    
1554
        /**
1555
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1556
         * to be created next time it is needed
1557
         */
1558
        public void cleanSelectableDatasource() {
1559
                ds = null;
1560
        }
1561

    
1562
        public FieldDescription[] getFieldsDescription() {
1563
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1564
        }
1565

    
1566

    
1567
//        private InternalField getInternalFieldByIndex(int fieldId)
1568
//        {
1569
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1570
//                        InternalField fld = (InternalField) iter.next();
1571
//                        if (fld.getFieldIndex() == fieldId)
1572
//                                return fld;
1573
//                }
1574
//                return null;
1575
//        }
1576

    
1577
}