Statistics
| Revision:

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

History | View | Annotate | Download (47.3 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
        private ArrayList events=new ArrayList();
142

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

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

    
166

    
167
        }
168

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

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

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

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

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

    
241
                fireStartEditionEvent(sourceType);
242
        }
243

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

    
266
        public void saveEdits(IWriter writer, int sourceType)
267
                        throws EditionException {
268

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

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

    
315
                writer.preProcess();
316

    
317
                try {
318

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

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

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

    
347
                        }
348

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

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

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

    
391
                        ods.reload();
392
                        ds = null;
393
                        clean();
394

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

    
406
        }
407

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

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

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

    
466

    
467

    
468
        }
469

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

    
488
        }
489

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

    
499
                try {
500
                        validateRow(row,sourceType);
501
                } catch (EditionException e) {
502
                        e.printStackTrace();
503
                        throw new IOException(e.getMessage());
504
                }
505

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

    
516
                return calculatedIndex;
517
        }
518

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

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

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

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

    
568
        }
569

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

    
579
                try {
580
                        validateRow(row,sourceType);
581
                } catch (EditionException e) {
582
                        e.printStackTrace();
583
                        throw new IOException(e.getMessage());
584
                }
585

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

    
597
                return pos;
598
        }
599

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

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

    
615
        /**
616
         * DOCUMENT ME!
617
         *
618
         * @throws IOException
619
         *             DOCUMENT ME!
620
         * @throws DriverIOException
621
         *             DOCUMENT ME!
622
         */
623
        public void endComplexRow(String description) throws IOException,
624
                        DriverIOException {
625
                commands.setDescription(description);
626
                cr.pushCommand(commands);
627
                complex = false;
628
                for (int i = 0; i < events.size(); i++) {
629
                        IEditionListener listener = (IEditionListener) editionListeners
630
                                        .get(i);
631
                        listener.afterFieldEditEvent((AfterFieldEditEvent)events.get(i));
632
                }
633
                events.clear();
634
        }
635

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

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

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

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

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

    
752
                        /*
753
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
754
                         * fichero de expansi?n en el que se encuentra la geometr?a
755
                         * modificada
756
                         */
757
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
758

    
759
                        /*
760
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
761
                         * fichero de expansi?n.
762
                         */
763
                        relations.put(integer, new Integer(num));
764
                }
765
                isFullExtentDirty = true;
766
                //fireAfterModifyRow(index, sourceType);
767
                return pos;
768
        }
769

    
770
        /**
771
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
772
         * en la tabla relations.
773
         *
774
         * @param feat
775
         *            geometr?a a guardar.
776
         *
777
         * @return calculatedIndex
778
         *
779
         * @throws DriverIOException
780
         * @throws IOException
781
         */
782
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
783
                        IOException {
784
                boolean cancel = fireBeforeRowAdded(sourceType);
785
                if (cancel)
786
                        return -1;
787
                // A?ade la geometr?a
788
                // int virtualIndex = 0;
789
                int calculatedIndex = -1;
790

    
791
                try {
792
                        calculatedIndex = (int) ods.getRowCount() + numAdd;
793
                        // int externalIndex = getRowCount();
794
                        // calculatedIndex = getCalculatedIndex(externalIndex);
795
                } catch (DriverException e) {
796
                        throw new DriverIOException(e);
797
                }
798

    
799
                int pos = expansionFile.addRow(feat, IRowEdited.STATUS_ADDED, actualIndexFields);
800
                relations.put(new Integer(calculatedIndex), new Integer(pos));
801
                numAdd++;
802
                System.err.println("A?ade una Row en la posici?n: " + calculatedIndex);
803
                isFullExtentDirty = true;
804
                fireAfterRowAdded(feat,calculatedIndex, sourceType);
805
                return calculatedIndex;
806
        }
807

    
808
        /**
809
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
810
         * en el fichero original
811
         *
812
         * @param index
813
         *            DOCUMENT ME!
814
         *
815
         * @throws IOException
816
         * @throws DriverIOException
817
         */
818
        public void undoRemoveRow(int index, int sourceType) throws IOException,
819
                        DriverIOException {
820
                boolean cancel = fireBeforeRowAdded(sourceType);
821
                if (cancel)
822
                        return;
823
                delRows.set(index, false);
824
                fireAfterRowAdded(null,index, sourceType);
825
        }
826

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

    
849
        /*
850
         * (non-Javadoc)
851
         *
852
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
853
         */
854
        public SelectableDataSource getRecordset() throws DriverLoadException {
855
                if (isEditing) {
856
                        if (ds == null) {
857
                                String name = LayerFactory.getDataSourceFactory()
858
                                                .addDataSource((ObjectDriver) editingDriver);
859

    
860
                                try {
861

    
862
                                        ds = new SelectableDataSource(LayerFactory
863
                                                        .getDataSourceFactory().createRandomDataSource(
864
                                                                        name, DataSourceFactory.MANUAL_OPENING));
865
                                        ds.start();
866
                                        ds.setSelectionSupport(ods.getSelectionSupport());
867

    
868
                                } catch (NoSuchTableException e) {
869
                                        throw new RuntimeException(e);
870
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
871
                                        throw new RuntimeException(e);
872
                                }
873
                        }
874

    
875
                        return ds;
876
                } else {
877
                        return ods;
878
                }
879
        }
880
        
881
        /**
882
         * Return always the original recordset (even when is editing,
883
         * nor the getRecorset() method)
884
         * 
885
         * */
886
        public SelectableDataSource getOriginalRecordset(){
887
                return ods;
888
        }
889

    
890

    
891
        /**
892
         * DOCUMENT ME!
893
         *
894
         * @return
895
         */
896
        public FBitSet getSelection() {
897
                /*
898
                 * try { return getRecordset().getSelection(); } catch
899
                 * (DriverLoadException e) { // TODO Auto-generated catch block
900
                 * e.printStackTrace(); } return null;
901
                 */
902
                return getRecordset().getSelection();
903
        }
904

    
905
        public void setSelection(FBitSet selection) {
906
                /*
907
                 * try { getRecordset().setSelection(selection); } catch
908
                 * (DriverLoadException e) { // TODO Auto-generated catch block
909
                 * e.printStackTrace(); }
910
                 */
911
                getRecordset().setSelection(selection);
912
        }
913

    
914
        /**
915
         * DOCUMENT ME!
916
         *
917
         * @return DOCUMENT ME!
918
         */
919
        public boolean isEditing() {
920
                return isEditing;
921
        }
922

    
923
        public int getInversedIndex(long rowIndex) {
924
                int intervalNotDeleted = 0;
925
                int antDeleted = -1;
926
                int idPedido = (int) rowIndex;
927
                int numNotDeleted = 0;
928
                int numBorradosAnt = 0;
929

    
930
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
931
                                .nextSetBit(i + 1)) {
932
                        intervalNotDeleted = i - antDeleted - 1;
933
                        numNotDeleted += intervalNotDeleted;
934
                        if (i > idPedido) {
935
                                numNotDeleted = numNotDeleted + (i - idPedido);
936
                                break;
937
                        }
938
                        numBorradosAnt++;
939
                        antDeleted = i;
940
                }
941
                numNotDeleted = idPedido - numBorradosAnt;
942
                // System.out.println("Piden Viejo : "+ rowIndex + " y devuelvo como
943
                // nuevo " + (numNotDeleted));
944
                return numNotDeleted;
945
        }
946

    
947
        /**
948
         * DOCUMENT ME!
949
         *
950
         * @param rowIndex
951
         *            DOCUMENT ME!
952
         *
953
         * @return DOCUMENT ME!
954
         */
955
        public int getCalculatedIndex(long rowIndex) {
956
                int numNotDeleted = 0;
957
                int intervalNotDeleted = 0;
958
                int antDeleted = -1;
959
                int calculatedIndex;
960
                int idPedido = (int) rowIndex;
961
                int numBorradosAnt = 0;
962

    
963
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
964
                                .nextSetBit(i + 1)) {
965
                        intervalNotDeleted = i - antDeleted - 1;
966
                        numNotDeleted += intervalNotDeleted;
967
                        if (numNotDeleted > idPedido) {
968
                                break;
969
                        }
970
                        numBorradosAnt++;
971
                        antDeleted = i;
972
                }
973
                calculatedIndex = numBorradosAnt + idPedido;
974
                // System.out.println("Piden Registro : "+ rowIndex + " y devuelvo el "
975
                // + (calculatedIndex));
976
                return calculatedIndex;
977
        }
978

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

    
1000
                /*
1001
                 * (non-Javadoc)
1002
                 *
1003
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
1004
                 */
1005
                public void write(DataWare dataWare) throws DriverException {
1006
                        DataWare dataWareOrig = ods
1007
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
1008
                        dataWareOrig.commitTrans();
1009
                }
1010

    
1011
                /*
1012
                 * (non-Javadoc)
1013
                 *
1014
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
1015
                 */
1016
                public void setDataSourceFactory(DataSourceFactory dsf) {
1017
                        ods.setDataSourceFactory(dsf);
1018
                }
1019

    
1020
                /*
1021
                 * (non-Javadoc)
1022
                 *
1023
                 * @see com.hardcode.driverManager.Driver#getName()
1024
                 */
1025
                public String getName() {
1026
                        return ods.getName();
1027
                }
1028

    
1029
                /*
1030
                 * (non-Javadoc)
1031
                 *
1032
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
1033
                 *      int)
1034
                 */
1035
                public Value getFieldValue(long rowIndex, int fieldId)
1036
                                throws DriverException {
1037
                        // Si no est? en el fichero de expansi?n
1038
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
1039

    
1040

    
1041
                        try {
1042
                                IRow row = getRow((int)rowIndex);
1043
                                return row.getAttribute(fieldId);
1044
//                                if (!relations.containsKey(integer)) {
1045
//                                        return ods.getFieldValue(rowIndex, fieldId);
1046
//                                } else {
1047
//                                        int num = ((Integer) relations.get(integer)).intValue();
1048
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
1049
//                                                        .getRow(num);
1050
//
1051
//                                        if (feat == null) {
1052
//                                                return null;
1053
//                                        }
1054
//
1055
//                                        return feat.getAttribute(fieldId);
1056
//                                }
1057
//                        } catch (DriverException e) {
1058
//                                e.printStackTrace();
1059
//                                throw new DriverException(e);
1060
                        } catch (IOException e) {
1061
                                e.printStackTrace();
1062
                                throw new DriverException(e);
1063
                        } catch (DriverIOException e) {
1064
                                e.printStackTrace();
1065
                                throw new DriverException(e);
1066
                        }
1067

    
1068
                        /**
1069
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
1070
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
1071
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
1072
                         * num = ((Integer) relations.get(integer)).intValue();
1073
                         * DefaultRowEdited feat = (DefaultRowEdited)
1074
                         * expansionFile.getRow(num); if (feat==null)return null; return
1075
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
1076
                         * e.printStackTrace(); throw new DriverException(e); } catch
1077
                         * (IOException e) { e.printStackTrace(); throw new
1078
                         * DriverException(e); }
1079
                         */
1080
                }
1081

    
1082
                /*
1083
                 * (non-Javadoc)
1084
                 *
1085
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1086
                 */
1087
                public int getFieldCount() throws DriverException {
1088
                        return fastAccessFields.size();
1089
                }
1090

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

    
1112
                /*
1113
                 * (non-Javadoc)
1114
                 *
1115
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1116
                 */
1117
                public long getRowCount() {
1118
                        try {
1119
                                return (int) (ods.getRowCount() + numAdd)
1120
                                                - delRows.cardinality();// -
1121
                                // expansionFile.getInvalidRows().cardinality();
1122
                        } catch (DriverException e) {
1123
                                // TODO Auto-generated catch block
1124
                                e.printStackTrace();
1125
                        }
1126

    
1127
                        return 0;
1128
                }
1129

    
1130
                /*
1131
                 * (non-Javadoc)
1132
                 *
1133
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1134
                 */
1135
                public int getFieldType(int fieldId) throws DriverException {
1136
//                        int i=0;
1137
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1138
//                                InternalField fld = (InternalField) iter.next();
1139
//                                if (i == fieldId)
1140
//                                        return fld.getFieldDesc().getFieldType();
1141
//                                i++;
1142
//
1143
//                        }
1144
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1145
                        return aux.getFieldType();
1146

    
1147
//                        return ods.getFieldType(i);
1148
                }
1149

    
1150
                public int getFieldWidth(int fieldId) throws DriverException {
1151
//                        int i=0;
1152
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1153
//                                InternalField fld = (InternalField) iter.next();
1154
////                                if (fld.getFieldIndex() == i)
1155
////                                        return fld.getFieldDesc().getFieldLength();
1156
//                                if (i == fieldId)
1157
//                                        return fld.getFieldDesc().getFieldLength();
1158
//                                i++;
1159
//
1160
//                        }
1161
//
1162
//                        return ods.getFieldWidth(i);
1163
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1164
                        return aux.getFieldLength();
1165

    
1166
                }
1167

    
1168
                public void reload() throws IOException, DriverException {
1169
                        ods.reload();
1170

    
1171
                }
1172
        }
1173

    
1174
        public CommandRecord getCommandRecord() {
1175
                return cr;
1176
        }
1177

    
1178
        protected void fireAfterRemoveRow(int index, int sourceType) {
1179
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1180
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1181
                if (complex) {
1182
                        //events.add(event);
1183
                        return;
1184
                }
1185
                for (int i = 0; i < editionListeners.size(); i++) {
1186
                        IEditionListener listener = (IEditionListener) editionListeners
1187
                                        .get(i);
1188
                        listener.afterRowEditEvent(null, event);
1189
                }
1190

    
1191
        }
1192

    
1193
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1194
                Cancel cancel = new Cancel();
1195
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1196
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1197
                for (int i = 0; i < editionListeners.size(); i++) {
1198
                        IEditionListener listener = (IEditionListener) editionListeners
1199
                                        .get(i);
1200
                        listener.beforeRowEditEvent(null, event);
1201
                        if (cancel.isCanceled())
1202
                                return true;
1203
                }
1204
                return false;
1205
        }
1206

    
1207
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1208
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1209
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1210
                if (complex) {
1211
                        //events.add(event);
1212
                        return;
1213
                }
1214
                for (int i = 0; i < editionListeners.size(); i++) {
1215
                        IEditionListener listener = (IEditionListener) editionListeners
1216
                                        .get(i);
1217
                        listener.afterRowEditEvent(feat, event);
1218
                }
1219
        }
1220

    
1221
        protected void fireAfterFieldAdded(FieldDescription field) {
1222
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1223
                                EditionEvent.CHANGE_TYPE_ADD);
1224
                if (complex) {
1225
                        events.add(event);
1226
                        return;
1227
                }
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 void fireAfterFieldRemoved(FieldDescription field) {
1237
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1238
                                EditionEvent.CHANGE_TYPE_DELETE);
1239
                if (complex) {
1240
                        events.add(event);
1241
                        return;
1242
                }
1243
                for (int i = 0; i < editionListeners.size(); i++) {
1244
                        IEditionListener listener = (IEditionListener) editionListeners
1245
                                        .get(i);
1246
                        listener.afterFieldEditEvent(event);
1247
                }
1248
        }
1249

    
1250
        protected void fireAfterFieldModified(FieldDescription field) {
1251
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1252
                                EditionEvent.CHANGE_TYPE_MODIFY);
1253
                if (complex) {
1254
                        events.add(event);
1255
                        return;
1256
                }
1257
                for (int i = 0; i < editionListeners.size(); i++) {
1258
                        IEditionListener listener = (IEditionListener) editionListeners
1259
                                        .get(i);
1260
                        listener.afterFieldEditEvent(event);
1261
                }
1262
        }
1263

    
1264

    
1265
        protected boolean fireBeforeRowAdded(int sourceType)
1266
                        throws DriverIOException, IOException {
1267
                Cancel cancel = new Cancel();
1268
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, getRowCount(),
1269
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1270
                for (int i = 0; i < editionListeners.size(); i++) {
1271
                        IEditionListener listener = (IEditionListener) editionListeners
1272
                                        .get(i);
1273
                        listener.beforeRowEditEvent(null, event);
1274
                        if (cancel.isCanceled())
1275
                                return true;
1276
                }
1277
                return false;
1278
        }
1279

    
1280
        protected boolean fireBeforeFieldAdded(FieldDescription field)
1281
        throws EditionException {
1282
                Cancel cancel = new Cancel();
1283
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1284
                EditionEvent.CHANGE_TYPE_ADD, cancel);
1285
                for (int i = 0; i < editionListeners.size(); i++) {
1286
                        IEditionListener listener = (IEditionListener) editionListeners
1287
                        .get(i);
1288
                        listener.beforeFieldEditEvent(event);
1289
                        if (cancel.isCanceled())
1290
                                return true;
1291
                }
1292
                return false;
1293
        }
1294

    
1295
        protected boolean fireBeforeRemoveField(FieldDescription field)
1296
        throws EditionException {
1297
                Cancel cancel = new Cancel();
1298
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1299
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1300
                for (int i = 0; i < editionListeners.size(); i++) {
1301
                        IEditionListener listener = (IEditionListener) editionListeners
1302
                        .get(i);
1303
                        listener.beforeFieldEditEvent(event);
1304
                        if (cancel.isCanceled())
1305
                                return true;
1306
                }
1307
                return false;
1308
        }
1309

    
1310

    
1311
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1312
                Cancel cancel = new Cancel();
1313
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1314
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1315
                for (int i = 0; i < editionListeners.size(); i++) {
1316
                        IEditionListener listener = (IEditionListener) editionListeners
1317
                                        .get(i);
1318
                        listener.beforeRowEditEvent(feat, event);
1319
                        if (cancel.isCanceled())
1320
                                return true;
1321
                }
1322
                return false;
1323
        }
1324

    
1325
        protected void fireAfterModifyRow(int index, int sourceType) {
1326
                if (complex)
1327
                        return;
1328
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1329
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1330
                for (int i = 0; i < editionListeners.size(); i++) {
1331
                        IEditionListener listener = (IEditionListener) editionListeners
1332
                                        .get(i);
1333
                        listener.afterRowEditEvent(null, event);
1334
                }
1335

    
1336
        }
1337

    
1338
        protected void fireStartEditionEvent(int sourceType) {
1339
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1340
                                sourceType);
1341
                for (int i = 0; i < editionListeners.size(); i++) {
1342
                        IEditionListener listener = (IEditionListener) editionListeners
1343
                                        .get(i);
1344
                        listener.processEvent(ev);
1345
                }
1346

    
1347
        }
1348

    
1349
        protected void fireStopEditionEvent(int sourceType) {
1350
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1351
                                sourceType);
1352
                for (int i = 0; i < editionListeners.size(); i++) {
1353
                        IEditionListener listener = (IEditionListener) editionListeners
1354
                                        .get(i);
1355
                        listener.processEvent(ev);
1356
                }
1357

    
1358
        }
1359

    
1360
        protected void fireCancelEditionEvent(int sourceType) {
1361
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1362
                                sourceType);
1363
                for (int i = 0; i < editionListeners.size(); i++) {
1364
                        IEditionListener listener = (IEditionListener) editionListeners
1365
                                        .get(i);
1366
                        listener.processEvent(ev);
1367
                }
1368

    
1369
        }
1370

    
1371
        public void addEditionListener(IEditionListener listener) {
1372
                if (!editionListeners.contains(listener))
1373
                        editionListeners.add(listener);
1374
        }
1375

    
1376
        public void removeEditionListener(IEditionListener listener) {
1377
                editionListeners.remove(listener);
1378
        }
1379

    
1380
        public IWriter getWriter() {
1381
                return writer;
1382
        }
1383

    
1384
        protected void setWriter(IWriter writer) {
1385
                this.writer = writer;
1386

    
1387
        }
1388
        /*
1389
         * azabala: esto funciona para todos los drivers gdbms
1390
         * salvo para MySQL, que necesita que el ITableDefinition
1391
         * contenga el nombre de la tabla (y por tanto requiere
1392
         * DBLayerDefinition-en realidad hace falta DBTableDefinition)
1393
         * TODO REVISAR LA ARQUITECTURA DE ESTO
1394
         * 
1395
         * */
1396
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1397
                        DriverException {
1398
                Driver originalDriver = getOriginalDriver();
1399
//                if(! (originalDriver instanceof AlphanumericDBDriver)){
1400
                        TableDefinition tableDef = new TableDefinition();
1401
                        tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1402
                        tableDef.setName(getRecordset().getSourceInfo().name);
1403
                        return tableDef;
1404
//                }else{
1405
//                        AlphanumericDBDriver dbDriver = (AlphanumericDBDriver)originalDriver;
1406
//                        return dbDriver.getTableDefinition();
1407
//                        
1408
//                }
1409
                
1410
                
1411
        }
1412

    
1413
        public void validateRow(IRow row,int sourceType) throws EditionException {
1414
                for (int i = 0; i < rules.size(); i++) {
1415
                        IRule rule = (IRule) rules.get(i);
1416
                        boolean bAux = rule.validate(row,sourceType);
1417
                        if (bAux == false) {
1418
                                EditionException ex = new EditionException(
1419
                                                "NOT follow the rule: " + rule.getDescription());
1420
                                // TODO: Lanzar una RuleException con datos como el registro
1421
                                // que no cumple, la regla que no lo ha cumplido, etc.
1422
                                throw ex;
1423
                        }
1424
                }
1425
        }
1426

    
1427
        public ArrayList getRules() {
1428
                return rules;
1429
        }
1430

    
1431
        public void setRules(ArrayList rules) {
1432
                this.rules = rules;
1433
        }
1434

    
1435
        private void clean() throws IOException, DriverException {
1436
                expansionFile.close();
1437
                relations.clear();
1438
                numAdd = 0;
1439
                delRows.clear();
1440
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1441
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1442
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1443
                // reload completo.
1444
                initalizeFields(ods);
1445

    
1446
//                listInternalFields.clear();
1447
//                listInternalFields.add(actualFields);
1448
        }
1449

    
1450
        /*
1451
         * (non-Javadoc)
1452
         *
1453
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1454
         */
1455
        public IFieldManager getFieldManager() {
1456
                if (ods.getDriver() instanceof IWriteable)
1457
                {
1458
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1459
                        if ((writer != null) && (writer instanceof IFieldManager))
1460
                        {
1461
                                IFieldManager fldManager = (IFieldManager) writer;
1462
                                return fldManager;
1463
                        }
1464
                }
1465
                return null;
1466
        }
1467

    
1468
        /**
1469
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1470
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1471
         *
1472
         * @param edRow
1473
         * @param indexInternalFields
1474
         * @return
1475
         */
1476
        public IRowEdited createExternalRow(IRowEdited edRow,
1477
                        int indexInternalFields) {
1478

    
1479
                // para acelerar
1480
                if (bFieldsHasBeenChanged == false)
1481
                        return edRow;
1482

    
1483
                Value[] att = edRow.getAttributes();
1484
                TreeMap ancientFields = (TreeMap) listInternalFields
1485
                                .get(indexInternalFields);
1486
                Value[] newAtt = new Value[actualFields.size()];
1487
                Collection aux = actualFields.values();
1488
                Iterator it = aux.iterator();
1489
                int i = 0;
1490
                Value val = null;
1491
                while (it.hasNext()) {
1492
                        // Para cada campo de los actuales, miramos si ya estaba cuando
1493
                        // el registro estaba guardado.
1494
                        // Si estaba, cogemos el valor de ese campo en el registro
1495
                        // guardado. Si no estaba, ha sido a?adido despu?s y ponemos
1496
                        // su valor por defecto.
1497
                        // Nota importante: fieldIndex es el ?ndice del campo cuando
1498
                        // se guard?. NO es el ?ndice actual dentro de actualFields.
1499
                        // Se usa SOLO para recuperar el valor de los atributos
1500
                        // antiguos. Por eso no nos preocupamos de mantener actuallizados
1501
                        // el resto de campos cuando se borra o a?ade un nuevo campo.
1502
                        InternalField fld = (InternalField) it.next();
1503
                        // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
1504
                        if (ancientFields.containsKey(fld.getFieldId())) {
1505
                                InternalField ancientField = (InternalField) ancientFields
1506
                                                .get(fld.getFieldId());
1507
                                val = att[ancientField.getFieldIndex()];
1508
                                // val = att[ancientField.getFieldId().intValue()];
1509
                                // System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + " val" + val);
1510
                        } else
1511
                                val = fld.getFieldDesc().getDefaultValue();
1512
                        newAtt[i++] = val;
1513
                }
1514
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1515
                newRow.setAttributes(newAtt);
1516
                return newRow;
1517
        }
1518

    
1519
        public void removeField(String fieldName) throws EditionException {
1520

    
1521
                InternalField fld = findFieldByName(fieldName);
1522
                if (fld == null)
1523
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1524
                Command command = new RemoveFieldCommand(this, fld);
1525
                if (complex) {
1526
                        commands.add(command);
1527
                } else {
1528
                        cr.pushCommand(command);
1529
                }
1530
                doRemoveField(fld);
1531

    
1532
        }
1533

    
1534
        private InternalField findFieldByName(String fieldName) {
1535
                Collection aux = actualFields.values();
1536
                Iterator it = aux.iterator();
1537
                while (it.hasNext()) {
1538
                        InternalField fld = (InternalField) it.next();
1539
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1540
                                return fld;
1541
                }
1542

    
1543
                return null;
1544
        }
1545

    
1546
        public void undoRemoveField(InternalField field) throws EditionException {
1547
                // field.setDeleted(false);
1548
//                field.setFieldIndex(actualFields.size());
1549
                actualFields.put(field.getFieldId(), field);
1550
                fieldsChanged();
1551
                fireAfterFieldAdded(field.getFieldDesc());
1552
        }
1553

    
1554
        public void doRemoveField(InternalField field) throws EditionException {
1555
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1556
                if (cancel) return;
1557
                actualFields.remove(field.getFieldId());
1558
                fieldsChanged();
1559
                fireAfterFieldRemoved(field.getFieldDesc());
1560
        }
1561

    
1562
        public void renameField(String antName, String newName) throws EditionException {
1563

    
1564
                InternalField fld = findFieldByName(antName);
1565
                Command command = new RenameFieldCommand(this, fld, newName);
1566
                if (complex) {
1567
                        commands.add(command);
1568
                } else {
1569
                        cr.pushCommand(command);
1570
                }
1571
                doRenameField(fld, newName);
1572

    
1573
        }
1574

    
1575
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1576
                field.getFieldDesc().setFieldAlias(antName);
1577
                fieldsChanged();
1578
                fireAfterFieldModified(field.getFieldDesc());
1579

    
1580
        }
1581

    
1582
        public void doRenameField(InternalField field, String newName) throws EditionException  {
1583
                field.getFieldDesc().setFieldAlias(newName);
1584
                fieldsChanged();
1585
                fireAfterFieldModified(field.getFieldDesc());
1586

    
1587
        }
1588

    
1589

    
1590
        public void addField(FieldDescription field) throws EditionException {
1591

    
1592
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1593
                Command command = new AddFieldCommand(this, fld);
1594
                if (complex) {
1595
                        commands.add(command);
1596
                } else {
1597
                        cr.pushCommand(command);
1598
                }
1599
                listFields.add(fld);
1600
                doAddField(fld);
1601

    
1602
        }
1603

    
1604
        public void undoAddField(InternalField field) throws EditionException {
1605
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1606
                if (cancel)
1607
                        return;
1608

    
1609
                // field.setDeleted(true);
1610
                actualFields.remove(field.getFieldId());
1611
                fieldsChanged();
1612
                fireAfterFieldRemoved(field.getFieldDesc());
1613

    
1614
        }
1615

    
1616
        public int doAddField(InternalField field) throws EditionException {
1617
                boolean cancel;
1618
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1619
                if (cancel)
1620
                        return -1;
1621

    
1622
                // field.setDeleted(false);
1623
//                field.setFieldIndex(actualFields.size());
1624
                actualFields.put(field.getFieldId(), field);
1625
                fieldsChanged();
1626
                fireAfterFieldAdded(field.getFieldDesc());
1627
//                return field.getFieldIndex();
1628
                return field.getFieldId().intValue();
1629
        }
1630

    
1631
        public Driver getOriginalDriver()
1632
        {
1633
                return ods.getDriver();
1634
        }
1635

    
1636
        /**
1637
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1638
         * to be created next time it is needed
1639
         */
1640
        public void cleanSelectableDatasource() {
1641
                ds = null;
1642
        }
1643

    
1644
        public FieldDescription[] getFieldsDescription() {
1645
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1646
        }
1647

    
1648

    
1649
//        private InternalField getInternalFieldByIndex(int fieldId)
1650
//        {
1651
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1652
//                        InternalField fld = (InternalField) iter.next();
1653
//                        if (fld.getFieldIndex() == fieldId)
1654
//                                return fld;
1655
//                }
1656
//                return null;
1657
//        }
1658

    
1659
}