Statistics
| Revision:

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

History | View | Annotate | Download (46.7 KB)

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

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

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

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

    
50
        private SelectableDataSource ds = null;
51

    
52
        protected FBitSet delRows = new FBitSet();
53

    
54
        private CommandRecord cr;
55

    
56
        protected IWriter writer;
57

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

    
64
        private CommandCollection commands = null;
65

    
66
        protected ArrayList listFields = new ArrayList();
67

    
68
        protected ArrayList listInternalFields = new ArrayList();
69

    
70
        protected boolean bFieldsHasBeenChanged = false;
71

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

    
82
        protected ArrayList fastAccessFields = new ArrayList();
83

    
84
        protected class MyFieldManager extends AbstractFieldManager {
85

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

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

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

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

    
104
        }
105

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

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

    
127
        protected int numAdd = 0;
128

    
129
        private ObjectDriver editingDriver = new myObjectDriver();
130

    
131
        private SelectableDataSource ods;
132

    
133
        private ArrayList editionListeners = new ArrayList();
134

    
135
        private ArrayList rules = new ArrayList();
136

    
137
        protected int actualIndexFields;
138

    
139
        protected boolean isFullExtentDirty = false;
140

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

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

    
164

    
165
        }
166

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

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

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

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

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

    
239
                fireStartEditionEvent(sourceType);
240
        }
241

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

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

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

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

    
313
                writer.preProcess();
314

    
315
                try {
316

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

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

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

    
345
                        }
346

    
347
                        int rowCount = getRowCount();
348
                        if (writer.isWriteAll())
349
                        {
350
                                for (int i = 0; i < rowCount; i++) {
351
                                        IRowEdited rowEdited = getRow(i);
352
        
353
                                        if (rowEdited != null) {
354
                                                writer.process(rowEdited);
355
                                        }
356
                                }
357
                        }
358
                        else
359
                        {
360
                                // Escribimos solo aquellos registros que han cambiado
361
                                for (int i = 0; i < rowCount; i++) {
362
                                        int calculatedIndex = getCalculatedIndex(i);
363
                                        Integer integer = new Integer(calculatedIndex);
364
                                        DefaultRowEdited edRow = null;
365
                                        // Si est? en el fichero de expansi?n hay que modificar
366
                                        if (relations.containsKey(integer)) {
367
                                                int num = ((Integer) relations.get(integer)).intValue();
368

    
369
                                                // return expansionFile.getRow(num);
370
                                                // ExpansionFile ya entrega el registro formateado como debe
371
                                                IRowEdited rowFromExpansion = expansionFile.getRow(num);
372
                                                // ?Habr?a que hacer aqu? setID(index + "")?
373
                                                edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
374
                                                                .cloneRow(), rowFromExpansion.getStatus(), i);
375
                                                writer.process(edRow);
376
                                        }
377
                                }
378
                        }
379
                        writer.postProcess();
380

    
381
                        // Hacemos que el escritor se entere de los nuevos campos
382
                        // que tiene. El escritor debe guardar una referencia
383
                        // a los campos con los que trabaja el drier, de forma
384
                        // que al recargar la capa (por ejemplo en el caso de
385
                        // PostGIS, se haga un setData con los campos que se hayan
386
                        // a?adido, borrado o renombrado).
387
                        writer.getTableDefinition().setFieldsDesc(getRecordset().getFieldsDescription());
388

    
389
                        ods.reload();
390
                        ds = null;
391
                        clean();
392

    
393
                } catch (DriverIOException e) {
394
                        e.printStackTrace();
395
                        throw new EditionException(e);
396
                } catch (IOException e) {
397
                        e.printStackTrace();
398
                        throw new EditionException(e);
399
                } catch (DriverException e) {
400
                        e.printStackTrace();
401
                        throw new EditionException(e);
402
                }
403

    
404
        }
405

    
406
        /**
407
         * DOCUMENT ME!
408
         *
409
         * @throws IOException
410
         *             DOCUMENT ME!
411
         */
412
        public void cancelEdition(int sourceType) throws IOException {
413
                isEditing = false;
414
                try {
415
                        ds= null;
416
                        clean();
417
                        cr.clearAll();
418
                } catch (DriverException e) {
419
                        e.printStackTrace();
420
                        throw new IOException("Error: " + e.getMessage());
421
                }
422
                fireCancelEditionEvent(sourceType);
423
        }
424

    
425
        /*
426
         * (non-Javadoc)
427
         *
428
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getRow(int)
429
         */
430
        public IRowEdited getRow(int index) throws DriverIOException, IOException {
431
                int calculatedIndex = getCalculatedIndex(index);
432
                Integer integer = new Integer(calculatedIndex);
433
                DefaultRowEdited edRow = null;
434
                // Si no est? en el fichero de expansi?n
435
                if (!relations.containsKey(integer)) {
436
                        try {
437
                                /*
438
                                 * edRow = new DefaultRowEdited(new
439
                                 * DefaultRow(ods.getRow(calculatedIndex), "" + index),
440
                                 * DefaultRowEdited.STATUS_ORIGINAL, index);
441
                                 */
442
                                DefaultRow auxR = new DefaultRow(ods.getRow(calculatedIndex));
443
                                edRow = new DefaultRowEdited(auxR,
444
                                                DefaultRowEdited.STATUS_ORIGINAL, index);
445
                                return createExternalRow(edRow, 0);
446
//                                edRow = new DefaultRowEdited(new DefaultRow(ods
447
//                                                .getRow(calculatedIndex)),
448
//                                                DefaultRowEdited.STATUS_ORIGINAL, index);
449
                        } catch (DriverException e) {
450
                                throw new DriverIOException(e);
451
                        }
452
                } else {
453
                        int num = ((Integer) relations.get(integer)).intValue();
454

    
455
                        // return expansionFile.getRow(num);
456
                        // ExpansionFile ya entrega el registro formateado como debe
457
                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
458
                        // ?Habr?a que hacer aqu? setID(index + "")?
459
                        edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
460
                                        .cloneRow(), rowFromExpansion.getStatus(), index);
461
                        return edRow;
462
                }
463

    
464

    
465

    
466
        }
467

    
468
        /**
469
         * DOCUMENT ME!
470
         *
471
         * @return DOCUMENT ME!
472
         *
473
         * @throws DriverIOException
474
         *             DOCUMENT ME!
475
         * @throws IOException
476
         *             DOCUMENT ME!
477
         */
478
        public int getRowCount() throws DriverIOException, IOException {
479
                try {
480
                        return (int) (ods.getRowCount() + numAdd) - delRows.cardinality();// -
481
                        // expansionFile.getInvalidRows().cardinality();
482
                } catch (DriverException e) {
483
                        throw new DriverIOException(e);
484
                }
485

    
486
        }
487

    
488
        /*
489
         * (non-Javadoc)
490
         *
491
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
492
         *      java.lang.String)
493
         */
494
        public int addRow(IRow row, String descrip, int sourceType)
495
                        throws DriverIOException, IOException {
496

    
497
                try {
498
                        validateRow(row);
499
                } catch (EditionException e) {
500
                        e.printStackTrace();
501
                        throw new IOException(e.getMessage());
502
                }
503

    
504
                int calculatedIndex = doAddRow(row, sourceType);
505
                Command command = new AddRowCommand(this, row, calculatedIndex,
506
                                sourceType);
507
                command.setDescription(descrip);
508
                if (complex) {
509
                        commands.add(command);
510
                } else {
511
                        cr.pushCommand(command);
512
                }
513

    
514
                return calculatedIndex;
515
        }
516

    
517
        /**
518
         * DOCUMENT ME!
519
         *
520
         * @throws DriverIOException
521
         *             DOCUMENT ME!
522
         * @throws IOException
523
         *             DOCUMENT ME!
524
         */
525
        public void undo() throws DriverIOException, IOException {
526
                // seleccion.clear();
527
                if (cr.moreUndoCommands()) {
528
                        cr.undoCommand();
529
                }
530
        }
531

    
532
        /**
533
         * DOCUMENT ME!
534
         *
535
         * @throws DriverIOException
536
         *             DOCUMENT ME!
537
         * @throws IOException
538
         *             DOCUMENT ME!
539
         */
540
        public void redo() throws DriverIOException, IOException {
541
                // seleccion.clear();
542
                if (cr.moreRedoCommands()) {
543
                        cr.redoCommand();
544
                }
545
        }
546

    
547
        /*
548
         * (non-Javadoc)
549
         *
550
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
551
         */
552
        public void removeRow(int index, String descrip, int sourceType)
553
                        throws IOException, DriverIOException {
554

    
555
                int calculatedIndex = getCalculatedIndex(index);
556
                Command command = new RemoveRowCommand(this, calculatedIndex,
557
                                sourceType);
558
                command.setDescription(descrip);
559
                if (complex) {
560
                        commands.add(command);
561
                } else {
562
                        cr.pushCommand(command);
563
                }
564
                doRemoveRow(calculatedIndex, sourceType);
565

    
566
        }
567

    
568
        /*
569
         * (non-Javadoc)
570
         *
571
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#modifyRow(int,
572
         *      com.iver.cit.gvsig.fmap.core.IRow)
573
         */
574
        public int modifyRow(int index, IRow row, String descrip, int sourceType)
575
                        throws IOException, DriverIOException {
576

    
577
                try {
578
                        validateRow(row);
579
                } catch (EditionException e) {
580
                        e.printStackTrace();
581
                        throw new IOException(e.getMessage());
582
                }
583

    
584
                int calculatedIndex = getCalculatedIndex(index);
585
                int pos = doModifyRow(calculatedIndex, row, sourceType);
586
                Command command = new ModifyRowCommand(this, calculatedIndex, pos, row,
587
                                sourceType);
588
                command.setDescription(descrip);
589
                if (complex) {
590
                        commands.add(command);
591
                } else {
592
                        cr.pushCommand(command);
593
                }
594

    
595
                return pos;
596
        }
597

    
598
        /**
599
         * DOCUMENT ME!
600
         */
601
        public void compact() {
602
                expansionFile.compact(relations);
603
        }
604

    
605
        /**
606
         * DOCUMENT ME!
607
         */
608
        public void startComplexRow() {
609
                complex = true;
610
                commands = new CommandCollection();
611
        }
612

    
613
        /**
614
         * DOCUMENT ME!
615
         *
616
         * @throws IOException
617
         *             DOCUMENT ME!
618
         * @throws DriverIOException
619
         *             DOCUMENT ME!
620
         */
621
        public void endComplexRow(String description) throws IOException,
622
                        DriverIOException {
623
                commands.setDescription(description);
624
                cr.pushCommand(commands);
625
                complex = false;
626
        }
627

    
628
        /**
629
         * Actualiza en el mapa de ?ndices, la posici?n en la que estaba la
630
         * geometr?a antes de ser modificada. Se marca como v?lida, en caso de que
631
         * fuera una modificaci?n de una geometr?a que estuviese en el fichero de
632
         * expansi?n antes de ser modificada y se pone el puntero de escritura del
633
         * expansion file a justo despues de la penultima geometr?a
634
         *
635
         * @param geometryIndex
636
         *            ?ndice de la geometr?a que se quiere deshacer su modificaci?n
637
         * @param previousExpansionFileIndex
638
         *            ?ndice que ten?a antes la geometr?a en el expansionFile. Si
639
         *            vale -1 quiere decir que es una modificaci?n de una geometr?a
640
         *            original y por tanto no hay que actualizar el mapa de indices
641
         *            sino eliminar su entrada.
642
         *
643
         * @throws IOException
644
         * @throws DriverIOException
645
         */
646
        public void undoModifyRow(int geometryIndex,
647
                        int previousExpansionFileIndex, int sourceType) throws IOException,
648
                        DriverIOException {
649

    
650
                if (previousExpansionFileIndex == -1) {
651
                        DefaultRowEdited edRow = null;
652
                        try {
653
                                edRow = new DefaultRowEdited(new DefaultRow(ods
654
                                                .getRow(geometryIndex)),
655
                                                DefaultRowEdited.STATUS_ORIGINAL, geometryIndex);
656
                        } catch (DriverException e) {
657
                                e.printStackTrace();
658
                        }
659
                        boolean cancel = fireBeforeModifyRow(edRow, geometryIndex,
660
                                        sourceType);
661
                        if (cancel)
662
                                return;
663
                        // Se elimina de las relaciones y del fichero de expansi?n
664
                        relations.remove(new Integer(geometryIndex));
665
                        expansionFile.deleteLastRow();
666
                } else {
667
                        boolean cancel = fireBeforeModifyRow(expansionFile
668
                                        .getRow(previousExpansionFileIndex), geometryIndex,
669
                                        sourceType);
670
                        if (cancel)
671
                                return;
672
                        // Se actualiza la relaci?n de ?ndices
673
                        relations.put(new Integer(geometryIndex), new Integer(
674
                                        previousExpansionFileIndex));
675
                }
676
                fireAfterModifyRow(geometryIndex, sourceType);
677
        }
678

    
679
        /**
680
         * Elimina una geometria. Si es una geometr?a original de la capa en edici?n
681
         * se marca como eliminada (haya sido modificada o no). Si es una geometr?a
682
         * a?adida posteriormente se invalida en el fichero de expansi?n, para que
683
         * una futura compactaci?n termine con ella.
684
         *
685
         * @param index
686
         *            ?ndice de la geometr?a.
687
         *
688
         * @throws DriverIOException
689
         * @throws IOException
690
         */
691
        public IRow doRemoveRow(int index, int sourceType)
692
                        throws DriverIOException, IOException {
693
                boolean cancel = fireBeforeRemoveRow(index, sourceType);
694
                if (cancel)
695
                        return null;
696
                // Llega un calculatedIndex
697
                delRows.set(index, true);
698
                System.err.println("Elimina una Row en la posici?n: " + index);
699
                // TODO: Con tablas no es necesario devolver la anterior feature. Por
700
                // ahora.
701
                isFullExtentDirty = true;
702
                fireAfterRemoveRow(index, sourceType);
703
                return null;
704
        }
705

    
706
        /**
707
         ** Si se intenta modificar una geometr?a original de la capa en edici?n se
708
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
709
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
710
         * fichero de expansi?n, ?sta puede estar ah? (en el ExpansionFile
711
         * por haber sido a?adida o modificada. Si ha sido a?adida, entonces hay
712
         * que respetar su estatus para que los writers puedan saber que es
713
         * un registro NUEVO).
714
         *
715
         * @param index
716
         *            DOCUMENT ME!
717
         * @param feat
718
         *            DOCUMENT ME!
719
         *
720
         * @return DOCUMENT ME!
721
         *
722
         * @throws IOException
723
         * @throws DriverIOException
724
         */
725
        public int doModifyRow(int index, IRow feat, int sourceType)
726
                        throws IOException, DriverIOException {
727
                boolean cancel = fireBeforeModifyRow(feat, index, sourceType);
728
                if (cancel)
729
                        return -1;
730

    
731
                int pos = -1;
732
                Integer integer = new Integer(index);
733
                System.err.println("Modifica una Row en la posici?n: " + index);
734
                // Si la geometr?a no ha sido modificada
735
                if (!relations.containsKey(integer)) {
736
                        int expansionIndex = expansionFile.addRow(feat,
737
                                        IRowEdited.STATUS_MODIFIED, actualIndexFields);
738
                        relations.put(integer, new Integer(expansionIndex));
739
                } else {
740
                        // Obtenemos el ?ndice en el fichero de expansi?n
741
                        int num = ((Integer) relations.get(integer)).intValue();
742
                        pos = num;
743

    
744
                        /*
745
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
746
                         * fichero de expansi?n en el que se encuentra la geometr?a
747
                         * modificada
748
                         */
749
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
750

    
751
                        /*
752
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
753
                         * fichero de expansi?n.
754
                         */
755
                        relations.put(integer, new Integer(num));
756
                }
757
                isFullExtentDirty = true;
758
                fireAfterModifyRow(index, sourceType);
759
                return pos;
760
        }
761

    
762
        /**
763
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
764
         * en la tabla relations.
765
         *
766
         * @param feat
767
         *            geometr?a a guardar.
768
         *
769
         * @return calculatedIndex
770
         *
771
         * @throws DriverIOException
772
         * @throws IOException
773
         */
774
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
775
                        IOException {
776
                boolean cancel = fireBeforeRowAdded(sourceType);
777
                if (cancel)
778
                        return -1;
779
                // A?ade la geometr?a
780
                // int virtualIndex = 0;
781
                int calculatedIndex = -1;
782

    
783
                try {
784
                        calculatedIndex = (int) ods.getRowCount() + numAdd;
785
                        // int externalIndex = getRowCount();
786
                        // calculatedIndex = getCalculatedIndex(externalIndex);
787
                } catch (DriverException e) {
788
                        throw new DriverIOException(e);
789
                }
790

    
791
                int pos = expansionFile.addRow(feat, IRowEdited.STATUS_ADDED, actualIndexFields);
792
                relations.put(new Integer(calculatedIndex), new Integer(pos));
793
                numAdd++;
794
                System.err.println("A?ade una Row en la posici?n: " + calculatedIndex);
795
                isFullExtentDirty = true;
796
                fireAfterRowAdded(feat,calculatedIndex, sourceType);
797
                return calculatedIndex;
798
        }
799

    
800
        /**
801
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
802
         * en el fichero original
803
         *
804
         * @param index
805
         *            DOCUMENT ME!
806
         *
807
         * @throws IOException
808
         * @throws DriverIOException
809
         */
810
        public void undoRemoveRow(int index, int sourceType) throws IOException,
811
                        DriverIOException {
812
                boolean cancel = fireBeforeRowAdded(sourceType);
813
                if (cancel)
814
                        return;
815
                delRows.set(index, false);
816
                fireAfterRowAdded(null,index, sourceType);
817
        }
818

    
819
        /**
820
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
821
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
822
         * relaci?n del mapa de relaciones
823
         *
824
         * @param index
825
         *            ?ndice de la geometr?a que se a?adi?
826
         *
827
         * @throws DriverIOException
828
         * @throws IOException
829
         */
830
        public void undoAddRow(int calculatedIndex, int sourceType)
831
                        throws DriverIOException, IOException {
832
                boolean cancel = fireBeforeRemoveRow(calculatedIndex, sourceType);
833
                if (cancel)
834
                        return;
835
                expansionFile.deleteLastRow();
836
                relations.remove(new Integer(calculatedIndex));
837
                numAdd--;
838
                fireAfterRemoveRow(calculatedIndex, sourceType);
839
        }
840

    
841
        /*
842
         * (non-Javadoc)
843
         *
844
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
845
         */
846
        public SelectableDataSource getRecordset() throws DriverLoadException {
847
                if (isEditing) {
848
                        if (ds == null) {
849
                                String name = LayerFactory.getDataSourceFactory()
850
                                                .addDataSource((ObjectDriver) editingDriver);
851

    
852
                                try {
853

    
854
                                        ds = new SelectableDataSource(LayerFactory
855
                                                        .getDataSourceFactory().createRandomDataSource(
856
                                                                        name, DataSourceFactory.MANUAL_OPENING));
857
                                        ds.start();
858
                                        ds.setSelectionSupport(ods.getSelectionSupport());
859

    
860
                                } catch (NoSuchTableException e) {
861
                                        throw new RuntimeException(e);
862
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
863
                                        throw new RuntimeException(e);
864
                                }
865
                        }
866

    
867
                        return ds;
868
                } else {
869
                        return ods;
870
                }
871
        }
872
        
873
        /**
874
         * Return always the original recordset (even when is editing,
875
         * nor the getRecorset() method)
876
         * 
877
         * */
878
        public SelectableDataSource getOriginalRecordset(){
879
                return ods;
880
        }
881

    
882

    
883
        /**
884
         * DOCUMENT ME!
885
         *
886
         * @return
887
         */
888
        public FBitSet getSelection() {
889
                /*
890
                 * try { return getRecordset().getSelection(); } catch
891
                 * (DriverLoadException e) { // TODO Auto-generated catch block
892
                 * e.printStackTrace(); } return null;
893
                 */
894
                return getRecordset().getSelection();
895
        }
896

    
897
        public void setSelection(FBitSet selection) {
898
                /*
899
                 * try { getRecordset().setSelection(selection); } catch
900
                 * (DriverLoadException e) { // TODO Auto-generated catch block
901
                 * e.printStackTrace(); }
902
                 */
903
                getRecordset().setSelection(selection);
904
        }
905

    
906
        /**
907
         * DOCUMENT ME!
908
         *
909
         * @return DOCUMENT ME!
910
         */
911
        public boolean isEditing() {
912
                return isEditing;
913
        }
914

    
915
        public int getInversedIndex(long rowIndex) {
916
                int intervalNotDeleted = 0;
917
                int antDeleted = -1;
918
                int idPedido = (int) rowIndex;
919
                int numNotDeleted = 0;
920
                int numBorradosAnt = 0;
921

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

    
939
        /**
940
         * DOCUMENT ME!
941
         *
942
         * @param rowIndex
943
         *            DOCUMENT ME!
944
         *
945
         * @return DOCUMENT ME!
946
         */
947
        public int getCalculatedIndex(long rowIndex) {
948
                int numNotDeleted = 0;
949
                int intervalNotDeleted = 0;
950
                int antDeleted = -1;
951
                int calculatedIndex;
952
                int idPedido = (int) rowIndex;
953
                int numBorradosAnt = 0;
954

    
955
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
956
                                .nextSetBit(i + 1)) {
957
                        intervalNotDeleted = i - antDeleted - 1;
958
                        numNotDeleted += intervalNotDeleted;
959
                        if (numNotDeleted > idPedido) {
960
                                break;
961
                        }
962
                        numBorradosAnt++;
963
                        antDeleted = i;
964
                }
965
                calculatedIndex = numBorradosAnt + idPedido;
966
                // System.out.println("Piden Registro : "+ rowIndex + " y devuelvo el "
967
                // + (calculatedIndex));
968
                return calculatedIndex;
969
        }
970

    
971
        /**
972
         * DOCUMENT ME!
973
         *
974
         * @author Vicente Caballero Navarro
975
         */
976
        private class myObjectDriver implements ObjectDriver {
977
                /*
978
                 * (non-Javadoc)
979
                 *
980
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
981
                 */
982
                public int[] getPrimaryKeys() throws DriverException {
983
                        return ods.getPrimaryKeys();
984
                        // int[] pk=new int[1];
985
                        /*
986
                         * for (int i=0;i<getRowCount();i++){ pk[i]=i; }
987
                         */
988
                        // pk[0]=1;
989
                        // return pk;
990
                }
991

    
992
                /*
993
                 * (non-Javadoc)
994
                 *
995
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
996
                 */
997
                public void write(DataWare dataWare) throws DriverException {
998
                        DataWare dataWareOrig = ods
999
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
1000
                        dataWareOrig.commitTrans();
1001
                }
1002

    
1003
                /*
1004
                 * (non-Javadoc)
1005
                 *
1006
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
1007
                 */
1008
                public void setDataSourceFactory(DataSourceFactory dsf) {
1009
                        ods.setDataSourceFactory(dsf);
1010
                }
1011

    
1012
                /*
1013
                 * (non-Javadoc)
1014
                 *
1015
                 * @see com.hardcode.driverManager.Driver#getName()
1016
                 */
1017
                public String getName() {
1018
                        return ods.getName();
1019
                }
1020

    
1021
                /*
1022
                 * (non-Javadoc)
1023
                 *
1024
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
1025
                 *      int)
1026
                 */
1027
                public Value getFieldValue(long rowIndex, int fieldId)
1028
                                throws DriverException {
1029
                        // Si no est? en el fichero de expansi?n
1030
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
1031

    
1032

    
1033
                        try {
1034
                                IRow row = getRow((int)rowIndex);
1035
                                return row.getAttribute(fieldId);
1036
//                                if (!relations.containsKey(integer)) {
1037
//                                        return ods.getFieldValue(rowIndex, fieldId);
1038
//                                } else {
1039
//                                        int num = ((Integer) relations.get(integer)).intValue();
1040
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
1041
//                                                        .getRow(num);
1042
//
1043
//                                        if (feat == null) {
1044
//                                                return null;
1045
//                                        }
1046
//
1047
//                                        return feat.getAttribute(fieldId);
1048
//                                }
1049
//                        } catch (DriverException e) {
1050
//                                e.printStackTrace();
1051
//                                throw new DriverException(e);
1052
                        } catch (IOException e) {
1053
                                e.printStackTrace();
1054
                                throw new DriverException(e);
1055
                        } catch (DriverIOException e) {
1056
                                e.printStackTrace();
1057
                                throw new DriverException(e);
1058
                        }
1059

    
1060
                        /**
1061
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
1062
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
1063
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
1064
                         * num = ((Integer) relations.get(integer)).intValue();
1065
                         * DefaultRowEdited feat = (DefaultRowEdited)
1066
                         * expansionFile.getRow(num); if (feat==null)return null; return
1067
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
1068
                         * e.printStackTrace(); throw new DriverException(e); } catch
1069
                         * (IOException e) { e.printStackTrace(); throw new
1070
                         * DriverException(e); }
1071
                         */
1072
                }
1073

    
1074
                /*
1075
                 * (non-Javadoc)
1076
                 *
1077
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1078
                 */
1079
                public int getFieldCount() throws DriverException {
1080
                        return fastAccessFields.size();
1081
                }
1082

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

    
1104
                /*
1105
                 * (non-Javadoc)
1106
                 *
1107
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1108
                 */
1109
                public long getRowCount() {
1110
                        try {
1111
                                return (int) (ods.getRowCount() + numAdd)
1112
                                                - delRows.cardinality();// -
1113
                                // expansionFile.getInvalidRows().cardinality();
1114
                        } catch (DriverException e) {
1115
                                // TODO Auto-generated catch block
1116
                                e.printStackTrace();
1117
                        }
1118

    
1119
                        return 0;
1120
                }
1121

    
1122
                /*
1123
                 * (non-Javadoc)
1124
                 *
1125
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1126
                 */
1127
                public int getFieldType(int fieldId) throws DriverException {
1128
//                        int i=0;
1129
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1130
//                                InternalField fld = (InternalField) iter.next();
1131
//                                if (i == fieldId)
1132
//                                        return fld.getFieldDesc().getFieldType();
1133
//                                i++;
1134
//
1135
//                        }
1136
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1137
                        return aux.getFieldType();
1138

    
1139
//                        return ods.getFieldType(i);
1140
                }
1141

    
1142
                public int getFieldWidth(int fieldId) throws DriverException {
1143
//                        int i=0;
1144
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1145
//                                InternalField fld = (InternalField) iter.next();
1146
////                                if (fld.getFieldIndex() == i)
1147
////                                        return fld.getFieldDesc().getFieldLength();
1148
//                                if (i == fieldId)
1149
//                                        return fld.getFieldDesc().getFieldLength();
1150
//                                i++;
1151
//
1152
//                        }
1153
//
1154
//                        return ods.getFieldWidth(i);
1155
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1156
                        return aux.getFieldLength();
1157

    
1158
                }
1159

    
1160
                public void reload() throws IOException, DriverException {
1161
                        ods.reload();
1162

    
1163
                }
1164
        }
1165

    
1166
        public CommandRecord getCommandRecord() {
1167
                return cr;
1168
        }
1169

    
1170
        protected void fireAfterRemoveRow(int index, int sourceType) {
1171
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1172
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1173
                for (int i = 0; i < editionListeners.size(); i++) {
1174
                        IEditionListener listener = (IEditionListener) editionListeners
1175
                                        .get(i);
1176
                        listener.afterRowEditEvent(null, event);
1177
                }
1178

    
1179
        }
1180

    
1181
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1182
                Cancel cancel = new Cancel();
1183
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1184
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1185
                for (int i = 0; i < editionListeners.size(); i++) {
1186
                        IEditionListener listener = (IEditionListener) editionListeners
1187
                                        .get(i);
1188
                        listener.beforeRowEditEvent(null, event);
1189
                        if (cancel.isCanceled())
1190
                                return true;
1191
                }
1192
                return false;
1193
        }
1194

    
1195
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1196
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1197
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1198
                for (int i = 0; i < editionListeners.size(); i++) {
1199
                        IEditionListener listener = (IEditionListener) editionListeners
1200
                                        .get(i);
1201
                        listener.afterRowEditEvent(feat, event);
1202
                }
1203
        }
1204

    
1205
        protected void fireAfterFieldAdded(FieldDescription field) {
1206
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1207
                                EditionEvent.CHANGE_TYPE_ADD);
1208
                for (int i = 0; i < editionListeners.size(); i++) {
1209
                        IEditionListener listener = (IEditionListener) editionListeners
1210
                                        .get(i);
1211
                        listener.afterFieldEditEvent(event);
1212
                }
1213
        }
1214

    
1215
        protected void fireAfterFieldRemoved(FieldDescription field) {
1216
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1217
                                EditionEvent.CHANGE_TYPE_DELETE);
1218
                for (int i = 0; i < editionListeners.size(); i++) {
1219
                        IEditionListener listener = (IEditionListener) editionListeners
1220
                                        .get(i);
1221
                        listener.afterFieldEditEvent(event);
1222
                }
1223
        }
1224

    
1225
        protected void fireAfterFieldModified(FieldDescription field) {
1226
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1227
                                EditionEvent.CHANGE_TYPE_MODIFY);
1228
                for (int i = 0; i < editionListeners.size(); i++) {
1229
                        IEditionListener listener = (IEditionListener) editionListeners
1230
                                        .get(i);
1231
                        listener.afterFieldEditEvent(event);
1232
                }
1233
        }
1234

    
1235

    
1236
        protected boolean fireBeforeRowAdded(int sourceType)
1237
                        throws DriverIOException, IOException {
1238
                Cancel cancel = new Cancel();
1239
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, getRowCount(),
1240
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1241
                for (int i = 0; i < editionListeners.size(); i++) {
1242
                        IEditionListener listener = (IEditionListener) editionListeners
1243
                                        .get(i);
1244
                        listener.beforeRowEditEvent(null, event);
1245
                        if (cancel.isCanceled())
1246
                                return true;
1247
                }
1248
                return false;
1249
        }
1250

    
1251
        protected boolean fireBeforeFieldAdded(FieldDescription field)
1252
        throws EditionException {
1253
                Cancel cancel = new Cancel();
1254
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1255
                EditionEvent.CHANGE_TYPE_ADD, cancel);
1256
                for (int i = 0; i < editionListeners.size(); i++) {
1257
                        IEditionListener listener = (IEditionListener) editionListeners
1258
                        .get(i);
1259
                        listener.beforeFieldEditEvent(event);
1260
                        if (cancel.isCanceled())
1261
                                return true;
1262
                }
1263
                return false;
1264
        }
1265

    
1266
        protected boolean fireBeforeRemoveField(FieldDescription field)
1267
        throws EditionException {
1268
                Cancel cancel = new Cancel();
1269
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1270
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1271
                for (int i = 0; i < editionListeners.size(); i++) {
1272
                        IEditionListener listener = (IEditionListener) editionListeners
1273
                        .get(i);
1274
                        listener.beforeFieldEditEvent(event);
1275
                        if (cancel.isCanceled())
1276
                                return true;
1277
                }
1278
                return false;
1279
        }
1280

    
1281

    
1282
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1283
                Cancel cancel = new Cancel();
1284
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1285
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1286
                for (int i = 0; i < editionListeners.size(); i++) {
1287
                        IEditionListener listener = (IEditionListener) editionListeners
1288
                                        .get(i);
1289
                        listener.beforeRowEditEvent(feat, event);
1290
                        if (cancel.isCanceled())
1291
                                return true;
1292
                }
1293
                return false;
1294
        }
1295

    
1296
        protected void fireAfterModifyRow(int index, int sourceType) {
1297
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1298
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1299
                for (int i = 0; i < editionListeners.size(); i++) {
1300
                        IEditionListener listener = (IEditionListener) editionListeners
1301
                                        .get(i);
1302
                        listener.afterRowEditEvent(null, event);
1303
                }
1304

    
1305
        }
1306

    
1307
        protected void fireStartEditionEvent(int sourceType) {
1308
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1309
                                sourceType);
1310
                for (int i = 0; i < editionListeners.size(); i++) {
1311
                        IEditionListener listener = (IEditionListener) editionListeners
1312
                                        .get(i);
1313
                        listener.processEvent(ev);
1314
                }
1315

    
1316
        }
1317

    
1318
        protected void fireStopEditionEvent(int sourceType) {
1319
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1320
                                sourceType);
1321
                for (int i = 0; i < editionListeners.size(); i++) {
1322
                        IEditionListener listener = (IEditionListener) editionListeners
1323
                                        .get(i);
1324
                        listener.processEvent(ev);
1325
                }
1326

    
1327
        }
1328

    
1329
        protected void fireCancelEditionEvent(int sourceType) {
1330
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1331
                                sourceType);
1332
                for (int i = 0; i < editionListeners.size(); i++) {
1333
                        IEditionListener listener = (IEditionListener) editionListeners
1334
                                        .get(i);
1335
                        listener.processEvent(ev);
1336
                }
1337

    
1338
        }
1339

    
1340
        public void addEditionListener(IEditionListener listener) {
1341
                if (!editionListeners.contains(listener))
1342
                        editionListeners.add(listener);
1343
        }
1344

    
1345
        public void removeEditionListener(IEditionListener listener) {
1346
                editionListeners.remove(listener);
1347
        }
1348

    
1349
        public IWriter getWriter() {
1350
                return writer;
1351
        }
1352

    
1353
        protected void setWriter(IWriter writer) {
1354
                this.writer = writer;
1355

    
1356
        }
1357
        /*
1358
         * azabala: esto funciona para todos los drivers gdbms
1359
         * salvo para MySQL, que necesita que el ITableDefinition
1360
         * contenga el nombre de la tabla (y por tanto requiere
1361
         * DBLayerDefinition-en realidad hace falta DBTableDefinition)
1362
         * TODO REVISAR LA ARQUITECTURA DE ESTO
1363
         * 
1364
         * */
1365
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1366
                        DriverException {
1367
                Driver originalDriver = getOriginalDriver();
1368
                if(! (originalDriver instanceof AlphanumericDBDriver)){
1369
                        TableDefinition tableDef = new TableDefinition();
1370
                        tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1371
                        tableDef.setName(getRecordset().getSourceInfo().name);
1372
                        return tableDef;
1373
                }else{
1374
                        AlphanumericDBDriver dbDriver = (AlphanumericDBDriver)originalDriver;
1375
                        return dbDriver.getTableDefinition();
1376
                        
1377
                }
1378
                
1379
                
1380
        }
1381

    
1382
        public void validateRow(IRow row) throws EditionException {
1383
                for (int i = 0; i < rules.size(); i++) {
1384
                        IRule rule = (IRule) rules.get(i);
1385
                        boolean bAux = rule.validate(row);
1386
                        if (bAux == false) {
1387
                                EditionException ex = new EditionException(
1388
                                                "NOT follow the rule: " + rule.getDescription());
1389
                                // TODO: Lanzar una RuleException con datos como el registro
1390
                                // que no cumple, la regla que no lo ha cumplido, etc.
1391
                                throw ex;
1392
                        }
1393
                }
1394
        }
1395

    
1396
        public ArrayList getRules() {
1397
                return rules;
1398
        }
1399

    
1400
        public void setRules(ArrayList rules) {
1401
                this.rules = rules;
1402
        }
1403

    
1404
        private void clean() throws IOException, DriverException {
1405
                expansionFile.close();
1406
                relations.clear();
1407
                numAdd = 0;
1408
                delRows.clear();
1409
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1410
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1411
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1412
                // reload completo.
1413
                initalizeFields(ods);
1414

    
1415
//                listInternalFields.clear();
1416
//                listInternalFields.add(actualFields);
1417
        }
1418

    
1419
        /*
1420
         * (non-Javadoc)
1421
         *
1422
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1423
         */
1424
        public IFieldManager getFieldManager() {
1425
                if (ods.getDriver() instanceof IWriteable)
1426
                {
1427
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1428
                        if ((writer != null) && (writer instanceof IFieldManager))
1429
                        {
1430
                                IFieldManager fldManager = (IFieldManager) writer;
1431
                                return fldManager;
1432
                        }
1433
                }
1434
                return null;
1435
        }
1436

    
1437
        /**
1438
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1439
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1440
         *
1441
         * @param edRow
1442
         * @param indexInternalFields
1443
         * @return
1444
         */
1445
        public IRowEdited createExternalRow(IRowEdited edRow,
1446
                        int indexInternalFields) {
1447

    
1448
                // para acelerar
1449
                if (bFieldsHasBeenChanged == false)
1450
                        return edRow;
1451

    
1452
                Value[] att = edRow.getAttributes();
1453
                TreeMap ancientFields = (TreeMap) listInternalFields
1454
                                .get(indexInternalFields);
1455
                Value[] newAtt = new Value[actualFields.size()];
1456
                Collection aux = actualFields.values();
1457
                Iterator it = aux.iterator();
1458
                int i = 0;
1459
                Value val = null;
1460
                while (it.hasNext()) {
1461
                        // Para cada campo de los actuales, miramos si ya estaba cuando
1462
                        // el registro estaba guardado.
1463
                        // Si estaba, cogemos el valor de ese campo en el registro
1464
                        // guardado. Si no estaba, ha sido a?adido despu?s y ponemos
1465
                        // su valor por defecto.
1466
                        // Nota importante: fieldIndex es el ?ndice del campo cuando
1467
                        // se guard?. NO es el ?ndice actual dentro de actualFields.
1468
                        // Se usa SOLO para recuperar el valor de los atributos
1469
                        // antiguos. Por eso no nos preocupamos de mantener actuallizados
1470
                        // el resto de campos cuando se borra o a?ade un nuevo campo.
1471
                        InternalField fld = (InternalField) it.next();
1472
                        // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
1473
                        if (ancientFields.containsKey(fld.getFieldId())) {
1474
                                InternalField ancientField = (InternalField) ancientFields
1475
                                                .get(fld.getFieldId());
1476
                                val = att[ancientField.getFieldIndex()];
1477
                                // val = att[ancientField.getFieldId().intValue()];
1478
                                // System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + " val" + val);
1479
                        } else
1480
                                val = fld.getFieldDesc().getDefaultValue();
1481
                        newAtt[i++] = val;
1482
                }
1483
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1484
                newRow.setAttributes(newAtt);
1485
                return newRow;
1486
        }
1487

    
1488
        public void removeField(String fieldName) throws EditionException {
1489

    
1490
                InternalField fld = findFieldByName(fieldName);
1491
                if (fld == null)
1492
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1493
                Command command = new RemoveFieldCommand(this, fld);
1494
                if (complex) {
1495
                        commands.add(command);
1496
                } else {
1497
                        cr.pushCommand(command);
1498
                }
1499
                doRemoveField(fld);
1500

    
1501
        }
1502

    
1503
        private InternalField findFieldByName(String fieldName) {
1504
                Collection aux = actualFields.values();
1505
                Iterator it = aux.iterator();
1506
                while (it.hasNext()) {
1507
                        InternalField fld = (InternalField) it.next();
1508
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1509
                                return fld;
1510
                }
1511

    
1512
                return null;
1513
        }
1514

    
1515
        public void undoRemoveField(InternalField field) throws EditionException {
1516
                // field.setDeleted(false);
1517
//                field.setFieldIndex(actualFields.size());
1518
                actualFields.put(field.getFieldId(), field);
1519
                fieldsChanged();
1520
                fireAfterFieldAdded(field.getFieldDesc());
1521
        }
1522

    
1523
        public void doRemoveField(InternalField field) throws EditionException {
1524
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1525
                if (cancel) return;
1526
                actualFields.remove(field.getFieldId());
1527
                fieldsChanged();
1528
                fireAfterFieldRemoved(field.getFieldDesc());
1529
        }
1530

    
1531
        public void renameField(String antName, String newName) throws EditionException {
1532

    
1533
                InternalField fld = findFieldByName(antName);
1534
                Command command = new RenameFieldCommand(this, fld, newName);
1535
                if (complex) {
1536
                        commands.add(command);
1537
                } else {
1538
                        cr.pushCommand(command);
1539
                }
1540
                doRenameField(fld, newName);
1541

    
1542
        }
1543

    
1544
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1545
                field.getFieldDesc().setFieldAlias(antName);
1546
                fieldsChanged();
1547
                fireAfterFieldModified(field.getFieldDesc());
1548

    
1549
        }
1550

    
1551
        public void doRenameField(InternalField field, String newName) throws EditionException  {
1552
                field.getFieldDesc().setFieldAlias(newName);
1553
                fieldsChanged();
1554
                fireAfterFieldModified(field.getFieldDesc());
1555

    
1556
        }
1557

    
1558

    
1559
        public void addField(FieldDescription field) throws EditionException {
1560

    
1561
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1562
                Command command = new AddFieldCommand(this, fld);
1563
                if (complex) {
1564
                        commands.add(command);
1565
                } else {
1566
                        cr.pushCommand(command);
1567
                }
1568
                listFields.add(fld);
1569
                doAddField(fld);
1570

    
1571
        }
1572

    
1573
        public void undoAddField(InternalField field) throws EditionException {
1574
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1575
                if (cancel)
1576
                        return;
1577

    
1578
                // field.setDeleted(true);
1579
                actualFields.remove(field.getFieldId());
1580
                fieldsChanged();
1581
                fireAfterFieldRemoved(field.getFieldDesc());
1582

    
1583
        }
1584

    
1585
        public int doAddField(InternalField field) throws EditionException {
1586
                boolean cancel;
1587
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1588
                if (cancel)
1589
                        return -1;
1590

    
1591
                // field.setDeleted(false);
1592
//                field.setFieldIndex(actualFields.size());
1593
                actualFields.put(field.getFieldId(), field);
1594
                fieldsChanged();
1595
                fireAfterFieldAdded(field.getFieldDesc());
1596
//                return field.getFieldIndex();
1597
                return field.getFieldId().intValue();
1598
        }
1599

    
1600
        public Driver getOriginalDriver()
1601
        {
1602
                return ods.getDriver();
1603
        }
1604

    
1605
        /**
1606
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1607
         * to be created next time it is needed
1608
         */
1609
        public void cleanSelectableDatasource() {
1610
                ds = null;
1611
        }
1612

    
1613
        public FieldDescription[] getFieldsDescription() {
1614
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1615
        }
1616

    
1617

    
1618
//        private InternalField getInternalFieldByIndex(int fieldId)
1619
//        {
1620
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1621
//                        InternalField fld = (InternalField) iter.next();
1622
//                        if (fld.getFieldIndex() == fieldId)
1623
//                                return fld;
1624
//                }
1625
//                return null;
1626
//        }
1627

    
1628
}