Statistics
| Revision:

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

History | View | Annotate | Download (39.4 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
        /**
70
         * La clave ser? el fieldIndex. Para buscar si un value de una row ha de ser
71
         * rellenado con defaultValue o con lo que venga del expansion file,
72
         * miraremos si existe en este hash. Si existe, usamos el value del
73
         * expansion file. Si no existe, usamos el defaultValue del campo busc?ndolo
74
         * en la lista internalFields. Por cierto, en listInternalFields NO se
75
         * borran campos. Solo se marcan como borrados.
76
         */
77
        protected TreeMap actualFields; // la clave ser? el fieldIndex.
78

    
79
        protected class MyFieldManager extends AbstractFieldManager {
80

    
81
                public boolean alterTable() throws EditionException {
82
                        return getFieldManager().alterTable();
83
                }
84

    
85
                public void addField(FieldDescription fieldDesc) {
86
                        super.addField(fieldDesc);
87
                }
88

    
89
                public FieldDescription removeField(String fieldName) {
90
                        // TODO Auto-generated method stub
91
                        return super.removeField(fieldName);
92
                }
93

    
94
                public void renameField(String antName, String newName) {
95
                        // TODO Auto-generated method stub
96
                        super.renameField(antName, newName);
97
                }
98

    
99
        }
100

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

    
116
        /*
117
         * Fichero en el que se guardan las nuevas geometr?as, producto de adiciones
118
         * o de modificaciones
119
         */
120
        protected ExpansionFile expansionFile;
121

    
122
        protected int numAdd = 0;
123

    
124
        private ObjectDriver editingDriver = new myObjectDriver();
125

    
126
        private SelectableDataSource ods;
127

    
128
        private ArrayList editionListeners = new ArrayList();
129

    
130
        private ArrayList rules = new ArrayList();
131

    
132
        protected int actualIndexFields;
133

    
134
        /**
135
         * Crea un nuevo EditableAdapter.
136
         */
137
        public EditableAdapter() {
138
                expansionFile = new MemoryExpansionFile(this);
139
                cr = new MemoryCommandRecord();
140
        }
141

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

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

    
180
        private void fieldsChanged() throws EditionException {
181
                listInternalFields.add(actualFields.clone());
182
                actualIndexFields = listInternalFields.size()-1;
183
                try {
184
                        getRecordset().mapExternalFields();
185
                } catch (DriverLoadException e) {
186
                        e.printStackTrace();
187
                        throw new EditionException(e);
188
                } catch (DriverException e) {
189
                        e.printStackTrace();
190
                        throw new EditionException(e);
191
                }
192
        }
193

    
194
        /**
195
         * DOCUMENT ME!
196
         * 
197
         * @throws EditionException
198
         *             DOCUMENT ME!
199
         */
200
        public void startEdition(int sourceType) throws EditionException {
201
                isEditing = true;
202
                // Obtenemos el driver y vemos si implementa IWriter.
203
                /*
204
                 * DataWare dataWare =
205
                 * ods.getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
206
                 * dataWare.get
207
                 */
208
                Driver drv = ods.getDriver();
209
                if (drv instanceof IWriteable) {
210
                        setWriter(((IWriteable) drv).getWriter());
211
                }
212

    
213
                fireStartEditionEvent(sourceType);
214
        }
215

    
216
        /**
217
         * Se ejecuta preProcess() del IWriter, luego se itera por los registros
218
         * borrados por si el IWriter los quiere borrar (solo ser? necesario cuando
219
         * escribimos sobre la misma tabla) y luego se itera por los nuevos
220
         * registros llamando a process con el registro correcto. (A?adidos,
221
         * modificados). Para finalizar, se ejecuta PostProcess
222
         * 
223
         * @param writer
224
         *            IWriter que recibir? las llamadas.
225
         * 
226
         * @throws EditionException
227
         *             DOCUMENT ME!
228
         */
229
        public void stopEdition(IWriter writer, int sourceType)
230
                        throws EditionException {
231

    
232
                saveEdits(writer, sourceType);
233
                isEditing = false;
234
                fireStopEditionEvent(sourceType);
235
        }
236

    
237
        public void saveEdits(IWriter writer, int sourceType)
238
                        throws EditionException {
239
                writer.preProcess();
240

    
241
                try {
242

    
243
                        // Procesamos primero los borrados.
244
                        // Cuando se genere un tema nuevo, no se les debe hacer caso
245
                        // a estos registros
246

    
247
                        for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
248
                                        .nextSetBit(i + 1)) {
249
                                int calculatedIndex = i;
250
                                Integer integer = new Integer(calculatedIndex);
251
                                // Si no est? en el fichero de expansi?n, es de los originales
252
                                // y hay que borrarlo
253
                                DefaultRowEdited edRow = null;
254
                                if (!relations.containsKey(integer)) {
255
                                        edRow = new DefaultRowEdited(new DefaultRow(ods
256
                                                        .getRow(calculatedIndex)),
257
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
258
                                        writer.process(edRow);
259
                                } else {
260
                                        int num = ((Integer) relations.get(integer)).intValue();
261

    
262
                                        // return expansionFile.getRow(num);
263
                                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
264
                                        // ?Habr?a que hacer aqu? setID(index + "")?
265
                                        edRow = new DefaultRowEdited(rowFromExpansion
266
                                                        .getLinkedRow().cloneRow(),
267
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
268
                                        writer.process(edRow);
269
                                }
270

    
271
                        }
272

    
273
                        int rowCount = getRowCount();
274
                        for (int i = 0; i < rowCount; i++) {
275
                                IRowEdited rowEdited = getRow(i);
276

    
277
                                if (rowEdited != null) {
278
                                        writer.process(rowEdited);
279
                                }
280
                        }
281
                        writer.postProcess();
282

    
283
                        ods.reload();
284
                        ds = null;
285
                        clean();
286
                        
287
                } catch (DriverIOException e) {
288
                        e.printStackTrace();
289
                        throw new EditionException(e);
290
                } catch (IOException e) {
291
                        e.printStackTrace();
292
                        throw new EditionException(e);
293
                } catch (DriverException e) {
294
                        e.printStackTrace();
295
                        throw new EditionException(e);
296
                }
297

    
298
        }
299

    
300
        /**
301
         * DOCUMENT ME!
302
         * 
303
         * @throws IOException
304
         *             DOCUMENT ME!
305
         */
306
        public void cancelEdition(int sourceType) throws IOException {
307
                isEditing = false;
308
                try {
309
                        ds= null;
310
                        clean();
311
                } catch (DriverException e) {
312
                        e.printStackTrace();
313
                        throw new IOException("Error: " + e.getMessage());
314
                }
315
                fireCancelEditionEvent(sourceType);
316
        }
317

    
318
        /*
319
         * (non-Javadoc)
320
         * 
321
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getRow(int)
322
         */
323
        public IRowEdited getRow(int index) throws DriverIOException, IOException {
324
                int calculatedIndex = getCalculatedIndex(index);
325
                Integer integer = new Integer(calculatedIndex);
326
                DefaultRowEdited edRow = null;
327
                // Si no est? en el fichero de expansi?n
328
                if (!relations.containsKey(integer)) {
329
                        try {
330
                                /*
331
                                 * edRow = new DefaultRowEdited(new
332
                                 * DefaultRow(ods.getRow(calculatedIndex), "" + index),
333
                                 * DefaultRowEdited.STATUS_ORIGINAL, index);
334
                                 */
335
                                DefaultRow auxR = new DefaultRow(ods.getRow(calculatedIndex));
336
                                edRow = new DefaultRowEdited(auxR,
337
                                                DefaultRowEdited.STATUS_ORIGINAL, index);
338
                                return createExternalRow(edRow, 0);
339
//                                edRow = new DefaultRowEdited(new DefaultRow(ods
340
//                                                .getRow(calculatedIndex)),
341
//                                                DefaultRowEdited.STATUS_ORIGINAL, index);
342
                        } catch (DriverException e) {
343
                                throw new DriverIOException(e);
344
                        }
345
                } else {
346
                        int num = ((Integer) relations.get(integer)).intValue();
347

    
348
                        // return expansionFile.getRow(num);
349
                        // ExpansionFile ya entrega el registro formateado como debe
350
                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
351
                        // ?Habr?a que hacer aqu? setID(index + "")?
352
                        edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
353
                                        .cloneRow(), rowFromExpansion.getStatus(), index);
354
                        return edRow;
355
                }
356
                
357
                
358

    
359
        }
360

    
361
        /**
362
         * DOCUMENT ME!
363
         * 
364
         * @return DOCUMENT ME!
365
         * 
366
         * @throws DriverIOException
367
         *             DOCUMENT ME!
368
         * @throws IOException
369
         *             DOCUMENT ME!
370
         */
371
        public int getRowCount() throws DriverIOException, IOException {
372
                try {
373
                        return (int) (ods.getRowCount() + numAdd) - delRows.cardinality();// -
374
                        // expansionFile.getInvalidRows().cardinality();
375
                } catch (DriverException e) {
376
                        throw new DriverIOException(e);
377
                }
378

    
379
        }
380

    
381
        /*
382
         * (non-Javadoc)
383
         * 
384
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
385
         *      java.lang.String)
386
         */
387
        public int addRow(IRow row, String descrip, int sourceType)
388
                        throws DriverIOException, IOException {
389

    
390
                try {
391
                        validateRow(row);
392
                } catch (EditionException e) {
393
                        e.printStackTrace();
394
                        throw new IOException(e.getMessage());
395
                }
396

    
397
                int calculatedIndex = doAddRow(row, sourceType);
398
                Command command = new AddRowCommand(this, row, calculatedIndex,
399
                                sourceType);
400
                command.setDescription(descrip);
401
                if (complex) {
402
                        commands.add(command);
403
                } else {
404
                        cr.pushCommand(command);
405
                }
406

    
407
                return calculatedIndex;
408
        }
409

    
410
        /**
411
         * DOCUMENT ME!
412
         * 
413
         * @throws DriverIOException
414
         *             DOCUMENT ME!
415
         * @throws IOException
416
         *             DOCUMENT ME!
417
         */
418
        public void undo() throws DriverIOException, IOException {
419
                // seleccion.clear();
420
                if (cr.moreUndoCommands()) {
421
                        cr.undoCommand();
422
                }
423
        }
424

    
425
        /**
426
         * DOCUMENT ME!
427
         * 
428
         * @throws DriverIOException
429
         *             DOCUMENT ME!
430
         * @throws IOException
431
         *             DOCUMENT ME!
432
         */
433
        public void redo() throws DriverIOException, IOException {
434
                // seleccion.clear();
435
                if (cr.moreRedoCommands()) {
436
                        cr.redoCommand();
437
                }
438
        }
439

    
440
        /*
441
         * (non-Javadoc)
442
         * 
443
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
444
         */
445
        public void removeRow(int index, String descrip, int sourceType)
446
                        throws IOException, DriverIOException {
447

    
448
                int calculatedIndex = getCalculatedIndex(index);
449
                Command command = new RemoveRowCommand(this, calculatedIndex,
450
                                sourceType);
451
                command.setDescription(descrip);
452
                if (complex) {
453
                        commands.add(command);
454
                } else {
455
                        cr.pushCommand(command);
456
                }
457
                doRemoveRow(calculatedIndex, sourceType);
458

    
459
        }
460

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

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

    
477
                int calculatedIndex = getCalculatedIndex(index);
478
                int pos = doModifyRow(calculatedIndex, row, sourceType);
479
                Command command = new ModifyRowCommand(this, calculatedIndex, pos, row,
480
                                sourceType);
481
                command.setDescription(descrip);
482
                if (complex) {
483
                        commands.add(command);
484
                } else {
485
                        cr.pushCommand(command);
486
                }
487

    
488
                return pos;
489
        }
490

    
491
        /**
492
         * DOCUMENT ME!
493
         */
494
        public void compact() {
495
                expansionFile.compact(relations);
496
        }
497

    
498
        /**
499
         * DOCUMENT ME!
500
         */
501
        public void startComplexRow() {
502
                complex = true;
503
                commands = new CommandCollection();
504
        }
505

    
506
        /**
507
         * DOCUMENT ME!
508
         * 
509
         * @throws IOException
510
         *             DOCUMENT ME!
511
         * @throws DriverIOException
512
         *             DOCUMENT ME!
513
         */
514
        public void endComplexRow(String description) throws IOException,
515
                        DriverIOException {
516
                commands.setDescription(description);
517
                cr.pushCommand(commands);
518
                complex = false;
519
        }
520

    
521
        /**
522
         * Actualiza en el mapa de ?ndices, la posici?n en la que estaba la
523
         * geometr?a antes de ser modificada. Se marca como v?lida, en caso de que
524
         * fuera una modificaci?n de una geometr?a que estuviese en el fichero de
525
         * expansi?n antes de ser modificada y se pone el puntero de escritura del
526
         * expansion file a justo despues de la penultima geometr?a
527
         * 
528
         * @param geometryIndex
529
         *            ?ndice de la geometr?a que se quiere deshacer su modificaci?n
530
         * @param previousExpansionFileIndex
531
         *            ?ndice que ten?a antes la geometr?a en el expansionFile. Si
532
         *            vale -1 quiere decir que es una modificaci?n de una geometr?a
533
         *            original y por tanto no hay que actualizar el mapa de indices
534
         *            sino eliminar su entrada.
535
         * 
536
         * @throws IOException
537
         * @throws DriverIOException
538
         */
539
        public void undoModifyRow(int geometryIndex,
540
                        int previousExpansionFileIndex, int sourceType) throws IOException,
541
                        DriverIOException {
542

    
543
                if (previousExpansionFileIndex == -1) {
544
                        DefaultRowEdited edRow = null;
545
                        try {
546
                                edRow = new DefaultRowEdited(new DefaultRow(ods
547
                                                .getRow(geometryIndex)),
548
                                                DefaultRowEdited.STATUS_ORIGINAL, geometryIndex);
549
                        } catch (DriverException e) {
550
                                e.printStackTrace();
551
                        }
552
                        boolean cancel = fireBeforeModifyRow(edRow, geometryIndex,
553
                                        sourceType);
554
                        if (cancel)
555
                                return;
556
                        // Se elimina de las relaciones y del fichero de expansi?n
557
                        relations.remove(new Integer(geometryIndex));
558
                        expansionFile.deleteLastRow();
559
                } else {
560
                        boolean cancel = fireBeforeModifyRow(expansionFile
561
                                        .getRow(previousExpansionFileIndex), geometryIndex,
562
                                        sourceType);
563
                        if (cancel)
564
                                return;
565
                        // Se actualiza la relaci?n de ?ndices
566
                        relations.put(new Integer(geometryIndex), new Integer(
567
                                        previousExpansionFileIndex));
568
                }
569
                fireAfterModifyRow(geometryIndex, sourceType);
570
        }
571

    
572
        /**
573
         * Elimina una geometria. Si es una geometr?a original de la capa en edici?n
574
         * se marca como eliminada (haya sido modificada o no). Si es una geometr?a
575
         * a?adida posteriormente se invalida en el fichero de expansi?n, para que
576
         * una futura compactaci?n termine con ella.
577
         * 
578
         * @param index
579
         *            ?ndice de la geometr?a.
580
         * 
581
         * @throws DriverIOException
582
         * @throws IOException
583
         */
584
        public IRow doRemoveRow(int index, int sourceType)
585
                        throws DriverIOException, IOException {
586
                boolean cancel = fireBeforeRemoveRow(index, sourceType);
587
                if (cancel)
588
                        return null;
589
                // Llega un calculatedIndex
590
                delRows.set(index, true);
591
                System.err.println("Elimina una Row en la posici?n: " + index);
592
                // TODO: Con tablas no es necesario devolver la anterior feature. Por
593
                // ahora.
594
                fireAfterRemoveRow(index, sourceType);
595
                return null;
596
        }
597

    
598
        /**
599
         * Si se intenta modificar una geometr?a original de la capa en edici?n se
600
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
601
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
602
         * fichero de expansi?n (por ser nueva o original pero modificada) se invoca
603
         * el m?todo modifyGeometry y se actualiza el ?ndice de la geometria en el
604
         * fichero.
605
         * 
606
         * @param index
607
         *            DOCUMENT ME!
608
         * @param feat
609
         *            DOCUMENT ME!
610
         * 
611
         * @return DOCUMENT ME!
612
         * 
613
         * @throws IOException
614
         * @throws DriverIOException
615
         */
616
        public int doModifyRow(int index, IRow feat, int sourceType)
617
                        throws IOException, DriverIOException {
618
                boolean cancel = fireBeforeModifyRow(feat, index, sourceType);
619
                if (cancel)
620
                        return -1;
621

    
622
                int pos = -1;
623
                Integer integer = new Integer(index);
624
                System.err.println("Modifica una Row en la posici?n: " + index);
625
                // Si la geometr?a no ha sido modificada
626
                if (!relations.containsKey(integer)) {
627
                        int expansionIndex = expansionFile.addRow(feat,
628
                                        IRowEdited.STATUS_MODIFIED, actualIndexFields);
629
                        relations.put(integer, new Integer(expansionIndex));
630
                } else {
631
                        // Obtenemos el ?ndice en el fichero de expansi?n
632
                        int num = ((Integer) relations.get(integer)).intValue();
633
                        pos = num;
634

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

    
642
                        /*
643
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
644
                         * fichero de expansi?n.
645
                         */
646
                        relations.put(integer, new Integer(num));
647
                }
648
                fireAfterModifyRow(index, sourceType);
649
                return pos;
650
        }
651

    
652
        /**
653
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
654
         * en la tabla relations.
655
         * 
656
         * @param feat
657
         *            geometr?a a guardar.
658
         * 
659
         * @return calculatedIndex
660
         * 
661
         * @throws DriverIOException
662
         * @throws IOException
663
         */
664
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
665
                        IOException {
666
                boolean cancel = fireBeforeRowAdded(sourceType);
667
                if (cancel)
668
                        return -1;
669
                // A?ade la geometr?a
670
                // int virtualIndex = 0;
671
                int calculatedIndex = -1;
672

    
673
                try {
674
                        calculatedIndex = (int) ods.getRowCount() + numAdd;
675
                        // int externalIndex = getRowCount();
676
                        // calculatedIndex = getCalculatedIndex(externalIndex);
677
                } catch (DriverException e) {
678
                        throw new DriverIOException(e);
679
                }
680

    
681
                int pos = expansionFile.addRow(feat, IRowEdited.STATUS_ADDED, actualIndexFields);
682
                relations.put(new Integer(calculatedIndex), new Integer(pos));
683
                numAdd++;
684
                System.err.println("A?ade una Row en la posici?n: " + calculatedIndex);
685
                fireAfterRowAdded(calculatedIndex, sourceType);
686
                return calculatedIndex;
687
        }
688

    
689
        /**
690
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
691
         * en el fichero original
692
         * 
693
         * @param index
694
         *            DOCUMENT ME!
695
         * 
696
         * @throws IOException
697
         * @throws DriverIOException
698
         */
699
        public void undoRemoveRow(int index, int sourceType) throws IOException,
700
                        DriverIOException {
701
                boolean cancel = fireBeforeRowAdded(sourceType);
702
                if (cancel)
703
                        return;
704
                delRows.set(index, false);
705
                fireAfterRowAdded(index, sourceType);
706
        }
707

    
708
        /**
709
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
710
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
711
         * relaci?n del mapa de relaciones
712
         * 
713
         * @param index
714
         *            ?ndice de la geometr?a que se a?adi?
715
         * 
716
         * @throws DriverIOException
717
         * @throws IOException
718
         */
719
        public void undoAddRow(int calculatedIndex, int sourceType)
720
                        throws DriverIOException, IOException {
721
                boolean cancel = fireBeforeRemoveRow(calculatedIndex, sourceType);
722
                if (cancel)
723
                        return;
724
                expansionFile.deleteLastRow();
725
                relations.remove(new Integer(calculatedIndex));
726
                numAdd--;
727
                fireAfterRemoveRow(calculatedIndex, sourceType);
728
        }
729

    
730
        /*
731
         * (non-Javadoc)
732
         * 
733
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
734
         */
735
        public SelectableDataSource getRecordset() throws DriverLoadException {
736
                if (isEditing) {
737
                        if (ds == null) {
738
                                String name = LayerFactory.getDataSourceFactory()
739
                                                .addDataSource((ObjectDriver) editingDriver);
740

    
741
                                try {
742
                                        ds = new SelectableDataSource(LayerFactory
743
                                                        .getDataSourceFactory().createRandomDataSource(
744
                                                                        name, DataSourceFactory.MANUAL_OPENING));
745
                                        ds.start();
746
                                        ds.setSelectionSupport(ods.getSelectionSupport());
747

    
748
                                } catch (NoSuchTableException e) {
749
                                        throw new RuntimeException(e);
750
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
751
                                        throw new RuntimeException(e);
752
                                }
753
                        }
754

    
755
                        return ds;
756
                } else {
757
                        return ods;
758
                }
759
        }
760

    
761

    
762
        /**
763
         * DOCUMENT ME!
764
         * 
765
         * @return
766
         */
767
        public FBitSet getSelection() {
768
                /*
769
                 * try { return getRecordset().getSelection(); } catch
770
                 * (DriverLoadException e) { // TODO Auto-generated catch block
771
                 * e.printStackTrace(); } return null;
772
                 */
773
                return getRecordset().getSelection();
774
        }
775

    
776
        public void setSelection(FBitSet selection) {
777
                /*
778
                 * try { getRecordset().setSelection(selection); } catch
779
                 * (DriverLoadException e) { // TODO Auto-generated catch block
780
                 * e.printStackTrace(); }
781
                 */
782
                getRecordset().setSelection(selection);
783
        }
784

    
785
        /**
786
         * DOCUMENT ME!
787
         * 
788
         * @return DOCUMENT ME!
789
         */
790
        public boolean isEditing() {
791
                return isEditing;
792
        }
793

    
794
        public int getInversedIndex(long rowIndex) {
795
                int intervalNotDeleted = 0;
796
                int antDeleted = -1;
797
                int idPedido = (int) rowIndex;
798
                int numNotDeleted = 0;
799
                int numBorradosAnt = 0;
800

    
801
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
802
                                .nextSetBit(i + 1)) {
803
                        intervalNotDeleted = i - antDeleted - 1;
804
                        numNotDeleted += intervalNotDeleted;
805
                        if (i > idPedido) {
806
                                numNotDeleted = numNotDeleted + (i - idPedido);
807
                                break;
808
                        }
809
                        numBorradosAnt++;
810
                        antDeleted = i;
811
                }
812
                numNotDeleted = idPedido - numBorradosAnt;
813
                // System.out.println("Piden Viejo : "+ rowIndex + " y devuelvo como
814
                // nuevo " + (numNotDeleted));
815
                return numNotDeleted;
816
        }
817

    
818
        /**
819
         * DOCUMENT ME!
820
         * 
821
         * @param rowIndex
822
         *            DOCUMENT ME!
823
         * 
824
         * @return DOCUMENT ME!
825
         */
826
        public int getCalculatedIndex(long rowIndex) {
827
                int numNotDeleted = 0;
828
                int intervalNotDeleted = 0;
829
                int antDeleted = -1;
830
                int calculatedIndex;
831
                int idPedido = (int) rowIndex;
832
                int numBorradosAnt = 0;
833

    
834
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
835
                                .nextSetBit(i + 1)) {
836
                        intervalNotDeleted = i - antDeleted - 1;
837
                        numNotDeleted += intervalNotDeleted;
838
                        if (numNotDeleted > idPedido) {
839
                                break;
840
                        }
841
                        numBorradosAnt++;
842
                        antDeleted = i;
843
                }
844
                calculatedIndex = numBorradosAnt + idPedido;
845
                // System.out.println("Piden Registro : "+ rowIndex + " y devuelvo el "
846
                // + (calculatedIndex));
847
                return calculatedIndex;
848
        }
849

    
850
        /**
851
         * DOCUMENT ME!
852
         * 
853
         * @author Vicente Caballero Navarro
854
         */
855
        private class myObjectDriver implements ObjectDriver {
856
                /*
857
                 * (non-Javadoc)
858
                 * 
859
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
860
                 */
861
                public int[] getPrimaryKeys() throws DriverException {
862
                        return ods.getPrimaryKeys();
863
                        // int[] pk=new int[1];
864
                        /*
865
                         * for (int i=0;i<getRowCount();i++){ pk[i]=i; }
866
                         */
867
                        // pk[0]=1;
868
                        // return pk;
869
                }
870

    
871
                /*
872
                 * (non-Javadoc)
873
                 * 
874
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
875
                 */
876
                public void write(DataWare dataWare) throws DriverException {
877
                        DataWare dataWareOrig = ods
878
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
879
                        dataWareOrig.commitTrans();
880
                }
881

    
882
                /*
883
                 * (non-Javadoc)
884
                 * 
885
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
886
                 */
887
                public void setDataSourceFactory(DataSourceFactory dsf) {
888
                        ods.setDataSourceFactory(dsf);
889
                }
890

    
891
                /*
892
                 * (non-Javadoc)
893
                 * 
894
                 * @see com.hardcode.driverManager.Driver#getName()
895
                 */
896
                public String getName() {
897
                        return ods.getName();
898
                }
899

    
900
                /*
901
                 * (non-Javadoc)
902
                 * 
903
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
904
                 *      int)
905
                 */
906
                public Value getFieldValue(long rowIndex, int fieldId)
907
                                throws DriverException {
908
                        // Si no est? en el fichero de expansi?n
909
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
910

    
911

    
912
                        try {
913
                                IRow row = getRow((int)rowIndex);
914
                                return row.getAttribute(fieldId);
915
//                                if (!relations.containsKey(integer)) {
916
//                                        return ods.getFieldValue(rowIndex, fieldId);
917
//                                } else {
918
//                                        int num = ((Integer) relations.get(integer)).intValue();
919
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
920
//                                                        .getRow(num);
921
//
922
//                                        if (feat == null) {
923
//                                                return null;
924
//                                        }
925
//
926
//                                        return feat.getAttribute(fieldId);
927
//                                }
928
//                        } catch (DriverException e) {
929
//                                e.printStackTrace();
930
//                                throw new DriverException(e);
931
                        } catch (IOException e) {
932
                                e.printStackTrace();
933
                                throw new DriverException(e);
934
                        } catch (DriverIOException e) {
935
                                e.printStackTrace();
936
                                throw new DriverException(e);
937
                        }
938

    
939
                        /**
940
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
941
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
942
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
943
                         * num = ((Integer) relations.get(integer)).intValue();
944
                         * DefaultRowEdited feat = (DefaultRowEdited)
945
                         * expansionFile.getRow(num); if (feat==null)return null; return
946
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
947
                         * e.printStackTrace(); throw new DriverException(e); } catch
948
                         * (IOException e) { e.printStackTrace(); throw new
949
                         * DriverException(e); }
950
                         */
951
                }
952

    
953
                /*
954
                 * (non-Javadoc)
955
                 * 
956
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
957
                 */
958
                public int getFieldCount() throws DriverException {
959
                        return actualFields.size();
960
                }
961

    
962
                /*
963
                 * (non-Javadoc)
964
                 * 
965
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
966
                 */
967
                public String getFieldName(int fieldId) throws DriverException {
968
                        
969
                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
970
                                InternalField fld = (InternalField) iter.next();
971
                                if (fld.getFieldIndex() == fieldId)
972
                                        return fld.getFieldDesc().getFieldAlias();
973
                                
974
                        }
975
                        throw new DriverException("FieldId " + fieldId + " not found ");
976
                        // return null;
977
                        // return ods.getFieldName(fieldId);
978
                }
979

    
980
                /*
981
                 * (non-Javadoc)
982
                 * 
983
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
984
                 */
985
                public long getRowCount() {
986
                        try {
987
                                return (int) (ods.getRowCount() + numAdd)
988
                                                - delRows.cardinality();// -
989
                                // expansionFile.getInvalidRows().cardinality();
990
                        } catch (DriverException e) {
991
                                // TODO Auto-generated catch block
992
                                e.printStackTrace();
993
                        }
994

    
995
                        return 0;
996
                }
997

    
998
                /*
999
                 * (non-Javadoc)
1000
                 * 
1001
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1002
                 */
1003
                public int getFieldType(int i) throws DriverException {
1004
                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1005
                                InternalField fld = (InternalField) iter.next();
1006
                                if (fld.getFieldIndex() == i)
1007
                                        return fld.getFieldDesc().getFieldType();
1008
                                
1009
                        }
1010
                        
1011
                        return ods.getFieldType(i);
1012
                }
1013

    
1014
                public int getFieldWidth(int i) throws DriverException {
1015
                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1016
                                InternalField fld = (InternalField) iter.next();
1017
                                if (fld.getFieldIndex() == i)
1018
                                        return fld.getFieldDesc().getFieldLength();
1019
                                
1020
                        }
1021

    
1022
                        return ods.getFieldWidth(i);
1023
                }
1024

    
1025
                public void reload() throws IOException, DriverException {
1026
                        ods.reload();
1027
                        
1028
                }
1029
        }
1030

    
1031
        public CommandRecord getCommandRecord() {
1032
                return cr;
1033
        }
1034

    
1035
        protected void fireAfterRemoveRow(int index, int sourceType) {
1036
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1037
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1038
                for (int i = 0; i < editionListeners.size(); i++) {
1039
                        IEditionListener listener = (IEditionListener) editionListeners
1040
                                        .get(i);
1041
                        listener.afterRowEditEvent(event);
1042
                }
1043

    
1044
        }
1045

    
1046
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1047
                Cancel cancel = new Cancel();
1048
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1049
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1050
                for (int i = 0; i < editionListeners.size(); i++) {
1051
                        IEditionListener listener = (IEditionListener) editionListeners
1052
                                        .get(i);
1053
                        listener.beforeRowEditEvent(null, event);
1054
                        if (cancel.isCanceled())
1055
                                return true;
1056
                }
1057
                return false;
1058
        }
1059

    
1060
        protected void fireAfterRowAdded(int calculatedIndex, int sourceType) {
1061
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1062
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1063
                for (int i = 0; i < editionListeners.size(); i++) {
1064
                        IEditionListener listener = (IEditionListener) editionListeners
1065
                                        .get(i);
1066
                        listener.afterRowEditEvent(event);
1067
                }
1068
        }
1069

    
1070
        protected void fireAfterFieldAdded(FieldDescription field) {
1071
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1072
                                EditionEvent.CHANGE_TYPE_ADD);
1073
                for (int i = 0; i < editionListeners.size(); i++) {
1074
                        IEditionListener listener = (IEditionListener) editionListeners
1075
                                        .get(i);
1076
                        listener.afterFieldEditEvent(event);
1077
                }
1078
        }
1079

    
1080
        protected void fireAfterFieldRemoved(FieldDescription field) {
1081
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1082
                                EditionEvent.CHANGE_TYPE_DELETE);
1083
                for (int i = 0; i < editionListeners.size(); i++) {
1084
                        IEditionListener listener = (IEditionListener) editionListeners
1085
                                        .get(i);
1086
                        listener.afterFieldEditEvent(event);
1087
                }
1088
        }
1089

    
1090
        protected boolean fireBeforeRowAdded(int sourceType)
1091
                        throws DriverIOException, IOException {
1092
                Cancel cancel = new Cancel();
1093
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, getRowCount(),
1094
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1095
                for (int i = 0; i < editionListeners.size(); i++) {
1096
                        IEditionListener listener = (IEditionListener) editionListeners
1097
                                        .get(i);
1098
                        listener.beforeRowEditEvent(null, event);
1099
                        if (cancel.isCanceled())
1100
                                return true;
1101
                }
1102
                return false;
1103
        }
1104

    
1105
        protected boolean fireBeforeFieldAdded(FieldDescription field)
1106
        throws EditionException {
1107
                Cancel cancel = new Cancel();
1108
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1109
                EditionEvent.CHANGE_TYPE_ADD, cancel);
1110
                for (int i = 0; i < editionListeners.size(); i++) {
1111
                        IEditionListener listener = (IEditionListener) editionListeners
1112
                        .get(i);
1113
                        listener.beforeFieldEditEvent(event);
1114
                        if (cancel.isCanceled())
1115
                                return true;
1116
                }
1117
                return false;
1118
        }
1119

    
1120
        protected boolean fireBeforeRemoveField(FieldDescription field)
1121
        throws EditionException {
1122
                Cancel cancel = new Cancel();
1123
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1124
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1125
                for (int i = 0; i < editionListeners.size(); i++) {
1126
                        IEditionListener listener = (IEditionListener) editionListeners
1127
                        .get(i);
1128
                        listener.beforeFieldEditEvent(event);
1129
                        if (cancel.isCanceled())
1130
                                return true;
1131
                }
1132
                return false;
1133
        }
1134

    
1135
        
1136
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1137
                Cancel cancel = new Cancel();
1138
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1139
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1140
                for (int i = 0; i < editionListeners.size(); i++) {
1141
                        IEditionListener listener = (IEditionListener) editionListeners
1142
                                        .get(i);
1143
                        listener.beforeRowEditEvent(feat, event);
1144
                        if (cancel.isCanceled())
1145
                                return true;
1146
                }
1147
                return false;
1148
        }
1149

    
1150
        protected void fireAfterModifyRow(int index, int sourceType) {
1151
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1152
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1153
                for (int i = 0; i < editionListeners.size(); i++) {
1154
                        IEditionListener listener = (IEditionListener) editionListeners
1155
                                        .get(i);
1156
                        listener.afterRowEditEvent(event);
1157
                }
1158

    
1159
        }
1160

    
1161
        protected void fireStartEditionEvent(int sourceType) {
1162
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1163
                                sourceType);
1164
                for (int i = 0; i < editionListeners.size(); i++) {
1165
                        IEditionListener listener = (IEditionListener) editionListeners
1166
                                        .get(i);
1167
                        listener.processEvent(ev);
1168
                }
1169

    
1170
        }
1171

    
1172
        protected void fireStopEditionEvent(int sourceType) {
1173
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1174
                                sourceType);
1175
                for (int i = 0; i < editionListeners.size(); i++) {
1176
                        IEditionListener listener = (IEditionListener) editionListeners
1177
                                        .get(i);
1178
                        listener.processEvent(ev);
1179
                }
1180

    
1181
        }
1182

    
1183
        protected void fireCancelEditionEvent(int sourceType) {
1184
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1185
                                sourceType);
1186
                for (int i = 0; i < editionListeners.size(); i++) {
1187
                        IEditionListener listener = (IEditionListener) editionListeners
1188
                                        .get(i);
1189
                        listener.processEvent(ev);
1190
                }
1191

    
1192
        }
1193

    
1194
        public void addEditionListener(IEditionListener listener) {
1195
                if (!editionListeners.contains(listener))
1196
                        editionListeners.add(listener);
1197
        }
1198

    
1199
        public void removeEditionListener(IEditionListener listener) {
1200
                editionListeners.remove(listener);
1201
        }
1202

    
1203
        public IWriter getWriter() {
1204
                return writer;
1205
        }
1206

    
1207
        protected void setWriter(IWriter writer) {
1208
                this.writer = writer;
1209

    
1210
        }
1211

    
1212
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1213
                        DriverException {
1214
                TableDefinition tableDef = new TableDefinition();
1215
                tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1216
                tableDef.setName(getRecordset().getSourceInfo().name);
1217
                return tableDef;
1218
        }
1219

    
1220
        public void validateRow(IRow row) throws EditionException {
1221
                for (int i = 0; i < rules.size(); i++) {
1222
                        IRule rule = (IRule) rules.get(i);
1223
                        boolean bAux = rule.validate(row);
1224
                        if (bAux == false) {
1225
                                EditionException ex = new EditionException(
1226
                                                "NOT follow the rule: " + rule.getDescription());
1227
                                // TODO: Lanzar una RuleException con datos como el registro
1228
                                // que no cumple, la regla que no lo ha cumplido, etc.
1229
                                throw ex;
1230
                        }
1231
                }
1232
        }
1233

    
1234
        public ArrayList getRules() {
1235
                return rules;
1236
        }
1237

    
1238
        public void setRules(ArrayList rules) {
1239
                this.rules = rules;
1240
        }
1241

    
1242
        private void clean() throws IOException, DriverException {
1243
                expansionFile.close();
1244
                relations.clear();
1245
                numAdd = 0;
1246
                delRows.clear();
1247
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1248
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1249
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1250
                // reload completo.
1251
                initalizeFields(ods);
1252
                
1253
//                listInternalFields.clear();
1254
//                listInternalFields.add(actualFields);
1255
        }
1256

    
1257
        /*
1258
         * (non-Javadoc)
1259
         * 
1260
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1261
         */
1262
        public IFieldManager getFieldManager() {
1263
                if (ods.getDriver() instanceof IFieldManager)
1264
                        return (IFieldManager) ods.getDriver();
1265
                return null;
1266
        }
1267

    
1268
        /**
1269
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1270
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1271
         * 
1272
         * @param edRow
1273
         * @param indexInternalFields
1274
         * @return
1275
         */
1276
        public IRowEdited createExternalRow(IRowEdited edRow,
1277
                        int indexInternalFields) {
1278
                Value[] att = edRow.getAttributes();
1279
                TreeMap ancientFields = (TreeMap) listInternalFields
1280
                                .get(indexInternalFields);
1281
                Value[] newAtt = new Value[actualFields.size()];
1282
                Collection aux = actualFields.values();
1283
                Iterator it = aux.iterator();
1284
                int i = 0;
1285
                Value val = null;
1286
                while (it.hasNext()) {
1287
                        InternalField fld = (InternalField) it.next();
1288
                        System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() + " index=" + fld.getFieldIndex() + " id=" + fld.getFieldId());
1289
                        if (ancientFields.containsKey(fld.getFieldId())) {
1290
                                InternalField ancientField = (InternalField) ancientFields
1291
                                                .get(fld.getFieldId());
1292
                                val = att[ancientField.getFieldIndex()];
1293
                                System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + ancientField.getFieldIndex() + " val" + val);
1294
                        } else
1295
                                val = fld.getFieldDesc().getDefaultValue();
1296
                        newAtt[i++] = val;
1297
                }
1298
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1299
                newRow.setAttributes(newAtt);
1300
                return newRow;
1301
        }
1302

    
1303
        public void removeField(String fieldName) throws EditionException {
1304

    
1305
                InternalField fld = findFieldByName(fieldName);
1306
                if (fld == null)
1307
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1308
                Command command = new RemoveFieldCommand(this, fld);
1309
                if (complex) {
1310
                        commands.add(command);
1311
                } else {
1312
                        cr.pushCommand(command);
1313
                }
1314
                doRemoveField(fld);
1315

    
1316
        }
1317

    
1318
        private InternalField findFieldByName(String fieldName) {
1319
                Collection aux = actualFields.values();
1320
                Iterator it = aux.iterator();
1321
                while (it.hasNext()) {
1322
                        InternalField fld = (InternalField) it.next();
1323
                        if (fld.getFieldDesc().getFieldName().compareToIgnoreCase(fieldName) == 0)
1324
                                return fld;
1325
                }
1326
                
1327
                return null;
1328
        }
1329

    
1330
        public void undoRemoveField(InternalField field) throws EditionException {
1331
                field.setDeleted(false);
1332
                field.setFieldIndex(actualFields.size());
1333
                actualFields.put(field.getFieldId(), field);
1334
                fieldsChanged();
1335
        }
1336

    
1337
        public void doRemoveField(InternalField field) throws EditionException {
1338
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1339
                if (cancel) return;
1340
                field.setDeleted(true);
1341
                actualFields.remove(field.getFieldId());
1342
                fieldsChanged();
1343
                fireAfterFieldRemoved(field.getFieldDesc());
1344
        }
1345

    
1346
        public void renameField(String antName, String newName) throws EditionException {
1347

    
1348
                InternalField fld = findFieldByName(antName);
1349
                Command command = new RenameFieldCommand(this, fld, newName);
1350
                if (complex) {
1351
                        commands.add(command);
1352
                } else {
1353
                        cr.pushCommand(command);
1354
                }
1355
                doRenameField(fld, newName);
1356

    
1357
        }
1358
        
1359
        public void undoRenameField(InternalField field, String antName) {
1360
                field.getFieldDesc().setFieldAlias(antName);
1361
        }
1362

    
1363
        public void doRenameField(InternalField field, String newName) {
1364
                field.getFieldDesc().setFieldAlias(newName);
1365
        }
1366

    
1367

    
1368
        public void addField(FieldDescription field) throws EditionException {
1369

    
1370
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1371
                Command command = new AddFieldCommand(this, fld);
1372
                if (complex) {
1373
                        commands.add(command);
1374
                } else {
1375
                        cr.pushCommand(command);
1376
                }
1377
                listFields.add(fld);
1378
                doAddField(fld);
1379

    
1380
        }
1381

    
1382
        public void undoAddField(InternalField field) throws EditionException {
1383
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1384
                if (cancel)
1385
                        return;
1386

    
1387
                field.setDeleted(true);
1388
                
1389
                actualFields.remove(field.getFieldId());
1390
                fieldsChanged();
1391
                fireAfterFieldRemoved(field.getFieldDesc());
1392
                
1393
        }
1394

    
1395
        public int doAddField(InternalField field) throws EditionException {
1396
                boolean cancel;
1397
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1398
                if (cancel)
1399
                        return -1;
1400

    
1401
                field.setDeleted(false);
1402
                field.setFieldIndex(actualFields.size());
1403
                actualFields.put(field.getFieldId(), field);
1404
                fieldsChanged();
1405
                fireAfterFieldAdded(field.getFieldDesc());
1406
                return field.getFieldIndex();
1407
        }
1408
        
1409
}