Statistics
| Revision:

svn-gvsig-desktop / branches / simbologia / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / EditableAdapter.java @ 10450

History | View | Annotate | Download (48 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
 * @author   Vicente Caballero Navarro
45
 */
46
public class EditableAdapter implements IEditableSource, IWriteable {
47
        /**
48
         * @uml.property  name="isEditing"
49
         */
50
        protected boolean isEditing = false;
51

    
52
        private SelectableDataSource ds = null;
53

    
54
        protected FBitSet delRows = new FBitSet();
55

    
56
        private CommandRecord cr;
57

    
58
        protected IWriter writer;
59

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

    
66
        private CommandCollection commands = null;
67

    
68
        protected ArrayList listFields = new ArrayList();
69

    
70
        protected ArrayList listInternalFields = new ArrayList();
71

    
72
        protected boolean bFieldsHasBeenChanged = false;
73

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

    
84
        protected ArrayList fastAccessFields = new ArrayList();
85

    
86
        protected class MyFieldManager extends AbstractFieldManager {
87

    
88
                public boolean alterTable() throws EditionException {
89
                        return getFieldManager().alterTable();
90
                }
91

    
92
                public void addField(FieldDescription fieldDesc) {
93
                        super.addField(fieldDesc);
94
                }
95

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

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

    
106
        }
107

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

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

    
129
        protected int numAdd = 0;
130

    
131
        private ObjectDriver editingDriver = new myObjectDriver();
132

    
133
        private SelectableDataSource ods;
134

    
135
        private ArrayList editionListeners = new ArrayList();
136

    
137
        /**
138
         * @uml.property  name="rules"
139
         */
140
        private ArrayList rules = new ArrayList();
141

    
142
        protected int actualIndexFields;
143

    
144
        protected boolean isFullExtentDirty = false;
145

    
146
        private ArrayList fieldEvents=new ArrayList();
147
        private ArrayList rowEvents=new ArrayList();
148

    
149
        /**
150
         * Crea un nuevo EditableAdapter.
151
         */
152
        public EditableAdapter() {
153
                expansionFile = new MemoryExpansionFile(this);
154
                cr = new MemoryCommandRecord();
155
        }
156

    
157
        /**
158
         * DOCUMENT ME!
159
         *
160
         * @param ds
161
         *            DOCUMENT ME!
162
         * @throws DriverException
163
         */
164
        public void setOriginalDataSource(SelectableDataSource ds) throws DriverException {
165
                this.ods = ds;
166
                initalizeFields(ds);
167
                Driver drv = ods.getDriver();
168
                if (drv instanceof IWriteable) {
169
                        setWriter(((IWriteable) drv).getWriter());
170
                }
171

    
172

    
173
        }
174

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

    
203
        private TreeMap deepCloneInternalFields(TreeMap col)
204
        {
205
                TreeMap clonedFields = new TreeMap();
206
                for (Iterator iter = col.values().iterator(); iter.hasNext();) {
207
                        InternalField fld = (InternalField) iter.next();
208
                        InternalField clonedField = fld.cloneInternalField();
209
                        clonedFields.put(clonedField.getFieldId(), clonedField);
210
                }
211

    
212
                return clonedFields;
213
        }
214
        private void fieldsChanged() throws EditionException {
215
                fastAccessFields= new ArrayList();
216
                int index = 0;
217
                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
218
                        InternalField fld = (InternalField) iter.next();
219
                        fastAccessFields.add(fld.getFieldDesc());
220
                        fld.setFieldIndex(index++);
221
                }
222

    
223
                listInternalFields.add(deepCloneInternalFields(actualFields));
224
                actualIndexFields = listInternalFields.size()-1;
225
                try {
226
                        ds = null;
227
                        getRecordset().mapExternalFields();
228
                        bFieldsHasBeenChanged = true;
229
                } catch (DriverLoadException e) {
230
                        e.printStackTrace();
231
                        throw new EditionException(e);
232
                } catch (DriverException e) {
233
                        e.printStackTrace();
234
                        throw new EditionException(e);
235
                }
236
        }
237

    
238
        /**
239
         * DOCUMENT ME!
240
         *
241
         * @throws EditionException
242
         *             DOCUMENT ME!
243
         */
244
        public void startEdition(int sourceType) throws EditionException {
245
                isEditing = true;
246

    
247
                fireStartEditionEvent(sourceType);
248
        }
249

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

    
272
        public void saveEdits(IWriter writer, int sourceType)
273
                        throws EditionException {
274

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

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

    
321
                writer.preProcess();
322

    
323
                try {
324

    
325
                        // Procesamos primero los borrados.
326
                        // Cuando se genere un tema nuevo, no se les debe hacer caso
327
                        // a estos registros
328

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

    
344
                                        // return expansionFile.getRow(num);
345
                                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
346
                                        // ?Habr?a que hacer aqu? setID(index + "")?
347
                                        edRow = new DefaultRowEdited(rowFromExpansion
348
                                                        .getLinkedRow().cloneRow(),
349
                                                        DefaultRowEdited.STATUS_DELETED, calculatedIndex);
350
                                        writer.process(edRow);
351
                                }
352

    
353
                        }
354

    
355
                        int rowCount = getRowCount();
356
                        if (writer.isWriteAll())
357
                        {
358
                                for (int i = 0; i < rowCount; i++) {
359
                                        IRowEdited rowEdited = getRow(i);
360

    
361
                                        if (rowEdited != null) {
362
                                                writer.process(rowEdited);
363
                                        }
364
                                }
365
                        }
366
                        else
367
                        {
368
                                // Escribimos solo aquellos registros que han cambiado
369
                                for (int i = 0; i < rowCount; i++) {
370
                                        int calculatedIndex = getCalculatedIndex(i);
371
                                        Integer integer = new Integer(calculatedIndex);
372
                                        DefaultRowEdited edRow = null;
373
                                        // Si est? en el fichero de expansi?n hay que modificar
374
                                        if (relations.containsKey(integer)) {
375
                                                int num = ((Integer) relations.get(integer)).intValue();
376

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

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

    
397
                        ods.reload();
398
                        ds = null;
399
                        clean();
400

    
401
                } catch (DriverIOException e) {
402
                        e.printStackTrace();
403
                        throw new EditionException(e);
404
                } catch (IOException e) {
405
                        e.printStackTrace();
406
                        throw new EditionException(e);
407
                } catch (DriverException e) {
408
                        e.printStackTrace();
409
                        throw new EditionException(e);
410
                }
411

    
412
        }
413

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

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

    
463
                        // return expansionFile.getRow(num);
464
                        // ExpansionFile ya entrega el registro formateado como debe
465
                        IRowEdited rowFromExpansion = expansionFile.getRow(num);
466
                        // ?Habr?a que hacer aqu? setID(index + "")?
467
                        edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
468
                                        .cloneRow(), rowFromExpansion.getStatus(), index);
469
                        return edRow;
470
                }
471

    
472

    
473

    
474
        }
475

    
476
        /**
477
         * DOCUMENT ME!
478
         *
479
         * @return DOCUMENT ME!
480
         *
481
         * @throws DriverIOException
482
         *             DOCUMENT ME!
483
         * @throws IOException
484
         *             DOCUMENT ME!
485
         */
486
        public int getRowCount() throws DriverIOException, IOException {
487
                try {
488
                        return (int) (ods.getRowCount() + numAdd) - delRows.cardinality();// -
489
                        // expansionFile.getInvalidRows().cardinality();
490
                } catch (DriverException e) {
491
                        throw new DriverIOException(e);
492
                }
493

    
494
        }
495

    
496
        /*
497
         * (non-Javadoc)
498
         *
499
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
500
         *      java.lang.String)
501
         */
502
        public int addRow(IRow row, String descrip, int sourceType)
503
                        throws DriverIOException, IOException {
504

    
505
                try {
506
                        validateRow(row,sourceType);
507
                } catch (EditionException e) {
508
                        e.printStackTrace();
509
                        throw new IOException(e.getMessage());
510
                }
511

    
512
                int calculatedIndex = doAddRow(row, sourceType);
513
                Command command = new AddRowCommand(this, row, calculatedIndex,
514
                                sourceType);
515
                command.setDescription(descrip);
516
                if (complex) {
517
                        commands.add(command);
518
                } else {
519
                        cr.pushCommand(command);
520
                }
521

    
522
                return calculatedIndex;
523
        }
524

    
525
        /**
526
         * DOCUMENT ME!
527
         *
528
         * @throws DriverIOException
529
         *             DOCUMENT ME!
530
         * @throws IOException
531
         *             DOCUMENT ME!
532
         */
533
        public void undo() throws DriverIOException, IOException {
534
                // seleccion.clear();
535
                if (cr.moreUndoCommands()) {
536
                        cr.undoCommand();
537
                }
538
        }
539

    
540
        /**
541
         * DOCUMENT ME!
542
         *
543
         * @throws DriverIOException
544
         *             DOCUMENT ME!
545
         * @throws IOException
546
         *             DOCUMENT ME!
547
         */
548
        public void redo() throws DriverIOException, IOException {
549
                // seleccion.clear();
550
                if (cr.moreRedoCommands()) {
551
                        cr.redoCommand();
552
                }
553
        }
554

    
555
        /*
556
         * (non-Javadoc)
557
         *
558
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
559
         */
560
        public void removeRow(int index, String descrip, int sourceType)
561
                        throws IOException, DriverIOException {
562

    
563
                int calculatedIndex = getCalculatedIndex(index);
564
                Command command = new RemoveRowCommand(this, calculatedIndex,
565
                                sourceType);
566
                command.setDescription(descrip);
567
                if (complex) {
568
                        commands.add(command);
569
                } else {
570
                        cr.pushCommand(command);
571
                }
572
                doRemoveRow(calculatedIndex, sourceType);
573

    
574
        }
575

    
576
        /*
577
         * (non-Javadoc)
578
         *
579
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#modifyRow(int,
580
         *      com.iver.cit.gvsig.fmap.core.IRow)
581
         */
582
        public int modifyRow(int index, IRow row, String descrip, int sourceType)
583
                        throws IOException, DriverIOException {
584

    
585
                try {
586
                        validateRow(row,sourceType);
587
                } catch (EditionException e) {
588
                        e.printStackTrace();
589
                        throw new IOException(e.getMessage());
590
                }
591

    
592
                int calculatedIndex = getCalculatedIndex(index);
593
                int pos = doModifyRow(calculatedIndex, row, sourceType);
594
                Command command = new ModifyRowCommand(this, calculatedIndex, pos, row,
595
                                sourceType);
596
                command.setDescription(descrip);
597
                if (complex) {
598
                        commands.add(command);
599
                } else {
600
                        cr.pushCommand(command);
601
                }
602

    
603
                return pos;
604
        }
605

    
606
        /**
607
         * DOCUMENT ME!
608
         */
609
        public void compact() {
610
                expansionFile.compact(relations);
611
        }
612

    
613
        /**
614
         * DOCUMENT ME!
615
         */
616
        public void startComplexRow() {
617
                complex = true;
618
                commands = new CommandCollection();
619
        }
620

    
621
        /**
622
         * DOCUMENT ME!
623
         *
624
         * @throws IOException
625
         *             DOCUMENT ME!
626
         * @throws DriverIOException
627
         *             DOCUMENT ME!
628
         */
629
        public void endComplexRow(String description) throws IOException,
630
                        DriverIOException {
631
                commands.setDescription(description);
632
                cr.pushCommand(commands);
633
                complex = false;
634
                for (int j = 0; j < editionListeners.size(); j++) {
635
                        for (int i = 0; i < fieldEvents.size(); i++) {
636
                                IEditionListener listener = (IEditionListener) editionListeners
637
                                        .get(j);
638
                                listener.afterFieldEditEvent((AfterFieldEditEvent)fieldEvents.get(i));
639
                        }
640
                        for (int i = 0; i < rowEvents.size(); i++) {
641
                                IEditionListener listener = (IEditionListener) editionListeners
642
                                                .get(j);
643
                                listener.afterRowEditEvent(null,(AfterRowEditEvent)rowEvents.get(i));
644
                        }
645
                }
646
                fieldEvents.clear();
647
                rowEvents.clear();
648
        }
649

    
650
        /**
651
         * Actualiza en el mapa de ?ndices, la posici?n en la que estaba la
652
         * geometr?a antes de ser modificada. Se marca como v?lida, en caso de que
653
         * fuera una modificaci?n de una geometr?a que estuviese en el fichero de
654
         * expansi?n antes de ser modificada y se pone el puntero de escritura del
655
         * expansion file a justo despues de la penultima geometr?a
656
         *
657
         * @param geometryIndex
658
         *            ?ndice de la geometr?a que se quiere deshacer su modificaci?n
659
         * @param previousExpansionFileIndex
660
         *            ?ndice que ten?a antes la geometr?a en el expansionFile. Si
661
         *            vale -1 quiere decir que es una modificaci?n de una geometr?a
662
         *            original y por tanto no hay que actualizar el mapa de indices
663
         *            sino eliminar su entrada.
664
         *
665
         * @throws IOException
666
         * @throws DriverIOException
667
         */
668
        public void undoModifyRow(int geometryIndex,
669
                        int previousExpansionFileIndex, int sourceType) throws IOException,
670
                        DriverIOException {
671

    
672
                if (previousExpansionFileIndex == -1) {
673
                        DefaultRowEdited edRow = null;
674
                        try {
675
                                edRow = new DefaultRowEdited(new DefaultRow(ods
676
                                                .getRow(geometryIndex)),
677
                                                DefaultRowEdited.STATUS_ORIGINAL, geometryIndex);
678
                        } catch (DriverException e) {
679
                                e.printStackTrace();
680
                        }
681
                        boolean cancel = fireBeforeModifyRow(edRow, geometryIndex,
682
                                        sourceType);
683
                        if (cancel)
684
                                return;
685
                        // Se elimina de las relaciones y del fichero de expansi?n
686
                        relations.remove(new Integer(geometryIndex));
687
                        expansionFile.deleteLastRow();
688
                } else {
689
                        boolean cancel = fireBeforeModifyRow(expansionFile
690
                                        .getRow(previousExpansionFileIndex), geometryIndex,
691
                                        sourceType);
692
                        if (cancel)
693
                                return;
694
                        // Se actualiza la relaci?n de ?ndices
695
                        relations.put(new Integer(geometryIndex), new Integer(
696
                                        previousExpansionFileIndex));
697
                }
698
                //fireAfterModifyRow(geometryIndex, sourceType);
699
        }
700

    
701
        /**
702
         * Elimina una geometria. Si es una geometr?a original de la capa en edici?n
703
         * se marca como eliminada (haya sido modificada o no). Si es una geometr?a
704
         * a?adida posteriormente se invalida en el fichero de expansi?n, para que
705
         * una futura compactaci?n termine con ella.
706
         *
707
         * @param index
708
         *            ?ndice de la geometr?a.
709
         *
710
         * @throws DriverIOException
711
         * @throws IOException
712
         */
713
        public IRow doRemoveRow(int index, int sourceType)
714
                        throws DriverIOException, IOException {
715
                boolean cancel = fireBeforeRemoveRow(index, sourceType);
716
                if (cancel)
717
                        return null;
718
                // Llega un calculatedIndex
719
                delRows.set(index, true);
720
                System.err.println("Elimina una Row en la posici?n: " + index);
721
                // TODO: Con tablas no es necesario devolver la anterior feature. Por
722
                // ahora.
723
                isFullExtentDirty = true;
724
                fireAfterRemoveRow(index, sourceType);
725
                return null;
726
        }
727

    
728
        /**
729
         ** Si se intenta modificar una geometr?a original de la capa en edici?n se
730
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
731
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
732
         * fichero de expansi?n, ?sta puede estar ah? (en el ExpansionFile
733
         * por haber sido a?adida o modificada. Si ha sido a?adida, entonces hay
734
         * que respetar su estatus para que los writers puedan saber que es
735
         * un registro NUEVO).
736
         *
737
         * @param index
738
         *            DOCUMENT ME!
739
         * @param feat
740
         *            DOCUMENT ME!
741
         *
742
         * @return DOCUMENT ME!
743
         *
744
         * @throws IOException
745
         * @throws DriverIOException
746
         */
747
        public int doModifyRow(int index, IRow feat, int sourceType)
748
                        throws IOException, DriverIOException {
749
                boolean cancel = fireBeforeModifyRow(feat, index, sourceType);
750
                if (cancel)
751
                        return -1;
752

    
753
                int pos = -1;
754
                Integer integer = new Integer(index);
755
//                System.err.println("Modifica una Row en la posici?n: " + index);
756
                // Si la geometr?a no ha sido modificada
757
                if (!relations.containsKey(integer)) {
758
                        int expansionIndex = expansionFile.addRow(feat,
759
                                        IRowEdited.STATUS_MODIFIED, actualIndexFields);
760
                        relations.put(integer, new Integer(expansionIndex));
761
                } else {
762
                        // Obtenemos el ?ndice en el fichero de expansi?n
763
                        int num = ((Integer) relations.get(integer)).intValue();
764
                        pos = num;
765

    
766
                        /*
767
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
768
                         * fichero de expansi?n en el que se encuentra la geometr?a
769
                         * modificada
770
                         */
771
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
772

    
773
                        /*
774
                         * Actualiza la relaci?n del ?ndice de la geometr?a al ?ndice en el
775
                         * fichero de expansi?n.
776
                         */
777
                        relations.put(integer, new Integer(num));
778
                }
779
                isFullExtentDirty = true;
780
                //fireAfterModifyRow(index, sourceType);
781
                return pos;
782
        }
783

    
784
        /**
785
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
786
         * en la tabla relations.
787
         *
788
         * @param feat
789
         *            geometr?a a guardar.
790
         *
791
         * @return calculatedIndex
792
         *
793
         * @throws DriverIOException
794
         * @throws IOException
795
         */
796
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
797
                        IOException {
798
                boolean cancel = fireBeforeRowAdded(sourceType);
799
                if (cancel)
800
                        return -1;
801
                // A?ade la geometr?a
802
                // int virtualIndex = 0;
803
                int calculatedIndex = -1;
804

    
805
                try {
806
                        calculatedIndex = (int) ods.getRowCount() + numAdd;
807
                        // int externalIndex = getRowCount();
808
                        // calculatedIndex = getCalculatedIndex(externalIndex);
809
                } catch (DriverException e) {
810
                        throw new DriverIOException(e);
811
                }
812

    
813
                int pos = expansionFile.addRow(feat, IRowEdited.STATUS_ADDED, actualIndexFields);
814
                relations.put(new Integer(calculatedIndex), new Integer(pos));
815
                numAdd++;
816
                System.err.println("A?ade una Row en la posici?n: " + calculatedIndex);
817
                isFullExtentDirty = true;
818
                fireAfterRowAdded(feat,calculatedIndex, sourceType);
819
                return calculatedIndex;
820
        }
821

    
822
        /**
823
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
824
         * en el fichero original
825
         *
826
         * @param index
827
         *            DOCUMENT ME!
828
         *
829
         * @throws IOException
830
         * @throws DriverIOException
831
         */
832
        public void undoRemoveRow(int index, int sourceType) throws IOException,
833
                        DriverIOException {
834
                boolean cancel = fireBeforeRowAdded(sourceType);
835
                if (cancel)
836
                        return;
837
                delRows.set(index, false);
838
                fireAfterRowAdded(null,index, sourceType);
839
        }
840

    
841
        /**
842
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
843
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
844
         * relaci?n del mapa de relaciones
845
         *
846
         * @param index
847
         *            ?ndice de la geometr?a que se a?adi?
848
         *
849
         * @throws DriverIOException
850
         * @throws IOException
851
         */
852
        public void undoAddRow(int calculatedIndex, int sourceType)
853
                        throws DriverIOException, IOException {
854
                boolean cancel = fireBeforeRemoveRow(calculatedIndex, sourceType);
855
                if (cancel)
856
                        return;
857
                expansionFile.deleteLastRow();
858
                relations.remove(new Integer(calculatedIndex));
859
                numAdd--;
860
                fireAfterRemoveRow(calculatedIndex, sourceType);
861
        }
862

    
863
        /*
864
         * (non-Javadoc)
865
         *
866
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
867
         */
868
        public SelectableDataSource getRecordset() throws DriverLoadException {
869
                if (isEditing) {
870
                        if (ds == null) {
871
                                String name = LayerFactory.getDataSourceFactory()
872
                                                .addDataSource((ObjectDriver) editingDriver);
873

    
874
                                try {
875

    
876
                                        ds = new SelectableDataSource(LayerFactory
877
                                                        .getDataSourceFactory().createRandomDataSource(
878
                                                                        name, DataSourceFactory.MANUAL_OPENING));
879
                                        ds.start();
880
                                        ds.setSelectionSupport(ods.getSelectionSupport());
881

    
882
                                } catch (NoSuchTableException e) {
883
                                        throw new RuntimeException(e);
884
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
885
                                        throw new RuntimeException(e);
886
                                }
887
                        }
888

    
889
                        return ds;
890
                } else {
891
                        return ods;
892
                }
893
        }
894

    
895
        /**
896
         * Return always the original recordset (even when is editing,
897
         * nor the getRecorset() method)
898
         *
899
         * */
900
        public SelectableDataSource getOriginalRecordset(){
901
                return ods;
902
        }
903

    
904

    
905
        /**
906
         * DOCUMENT ME!
907
         *
908
         * @return
909
         */
910
        public FBitSet getSelection() {
911
                /*
912
                 * try { return getRecordset().getSelection(); } catch
913
                 * (DriverLoadException e) { // TODO Auto-generated catch block
914
                 * e.printStackTrace(); } return null;
915
                 */
916
                return getRecordset().getSelection();
917
        }
918

    
919
        public void setSelection(FBitSet selection) {
920
                /*
921
                 * try { getRecordset().setSelection(selection); } catch
922
                 * (DriverLoadException e) { // TODO Auto-generated catch block
923
                 * e.printStackTrace(); }
924
                 */
925
                getRecordset().setSelection(selection);
926
        }
927

    
928
        /**
929
         * DOCUMENT ME!
930
         * @return  DOCUMENT ME!
931
         * @uml.property  name="isEditing"
932
         */
933
        public boolean isEditing() {
934
                return isEditing;
935
        }
936

    
937
        public int getInversedIndex(long rowIndex) {
938
                int intervalNotDeleted = 0;
939
                int antDeleted = -1;
940
                int idPedido = (int) rowIndex;
941
                int numNotDeleted = 0;
942
                int numBorradosAnt = 0;
943

    
944
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
945
                                .nextSetBit(i + 1)) {
946
                        intervalNotDeleted = i - antDeleted - 1;
947
                        numNotDeleted += intervalNotDeleted;
948
                        if (i > idPedido) {
949
                                numNotDeleted = numNotDeleted + (i - idPedido);
950
                                break;
951
                        }
952
                        numBorradosAnt++;
953
                        antDeleted = i;
954
                }
955
                numNotDeleted = idPedido - numBorradosAnt;
956
                // System.out.println("Piden Viejo : "+ rowIndex + " y devuelvo como
957
                // nuevo " + (numNotDeleted));
958
                return numNotDeleted;
959
        }
960

    
961
        /**
962
         * DOCUMENT ME!
963
         *
964
         * @param rowIndex
965
         *            DOCUMENT ME!
966
         *
967
         * @return DOCUMENT ME!
968
         */
969
        public int getCalculatedIndex(long rowIndex) {
970
                int numNotDeleted = 0;
971
                int intervalNotDeleted = 0;
972
                int antDeleted = -1;
973
                int calculatedIndex;
974
                int idPedido = (int) rowIndex;
975
                int numBorradosAnt = 0;
976

    
977
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
978
                                .nextSetBit(i + 1)) {
979
                        intervalNotDeleted = i - antDeleted - 1;
980
                        numNotDeleted += intervalNotDeleted;
981
                        if (numNotDeleted > idPedido) {
982
                                break;
983
                        }
984
                        numBorradosAnt++;
985
                        antDeleted = i;
986
                }
987
                calculatedIndex = numBorradosAnt + idPedido;
988
                // System.out.println("Piden Registro : "+ rowIndex + " y devuelvo el "
989
                // + (calculatedIndex));
990
                return calculatedIndex;
991
        }
992

    
993
        /**
994
         * DOCUMENT ME!
995
         *
996
         * @author Vicente Caballero Navarro
997
         */
998
        private class myObjectDriver implements ObjectDriver {
999
                /*
1000
                 * (non-Javadoc)
1001
                 *
1002
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
1003
                 */
1004
                public int[] getPrimaryKeys() throws DriverException {
1005
                        return ods.getPrimaryKeys();
1006
                        // int[] pk=new int[1];
1007
                        /*
1008
                         * for (int i=0;i<getRowCount();i++){ pk[i]=i; }
1009
                         */
1010
                        // pk[0]=1;
1011
                        // return pk;
1012
                }
1013

    
1014
                /*
1015
                 * (non-Javadoc)
1016
                 *
1017
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
1018
                 */
1019
                public void write(DataWare dataWare) throws DriverException {
1020
                        DataWare dataWareOrig = ods
1021
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
1022
                        dataWareOrig.commitTrans();
1023
                }
1024

    
1025
                /*
1026
                 * (non-Javadoc)
1027
                 *
1028
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
1029
                 */
1030
                public void setDataSourceFactory(DataSourceFactory dsf) {
1031
                        ods.setDataSourceFactory(dsf);
1032
                }
1033

    
1034
                /*
1035
                 * (non-Javadoc)
1036
                 *
1037
                 * @see com.hardcode.driverManager.Driver#getName()
1038
                 */
1039
                public String getName() {
1040
                        return ods.getName();
1041
                }
1042

    
1043
                /*
1044
                 * (non-Javadoc)
1045
                 *
1046
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
1047
                 *      int)
1048
                 */
1049
                public Value getFieldValue(long rowIndex, int fieldId)
1050
                                throws DriverException {
1051
                        // Si no est? en el fichero de expansi?n
1052
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
1053

    
1054

    
1055
                        try {
1056
                                IRow row = getRow((int)rowIndex);
1057
                                return row.getAttribute(fieldId);
1058
//                                if (!relations.containsKey(integer)) {
1059
//                                        return ods.getFieldValue(rowIndex, fieldId);
1060
//                                } else {
1061
//                                        int num = ((Integer) relations.get(integer)).intValue();
1062
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
1063
//                                                        .getRow(num);
1064
//
1065
//                                        if (feat == null) {
1066
//                                                return null;
1067
//                                        }
1068
//
1069
//                                        return feat.getAttribute(fieldId);
1070
//                                }
1071
//                        } catch (DriverException e) {
1072
//                                e.printStackTrace();
1073
//                                throw new DriverException(e);
1074
                        } catch (IOException e) {
1075
                                e.printStackTrace();
1076
                                throw new DriverException(e);
1077
                        } catch (DriverIOException e) {
1078
                                e.printStackTrace();
1079
                                throw new DriverException(e);
1080
                        }
1081

    
1082
                        /**
1083
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
1084
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
1085
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
1086
                         * num = ((Integer) relations.get(integer)).intValue();
1087
                         * DefaultRowEdited feat = (DefaultRowEdited)
1088
                         * expansionFile.getRow(num); if (feat==null)return null; return
1089
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
1090
                         * e.printStackTrace(); throw new DriverException(e); } catch
1091
                         * (IOException e) { e.printStackTrace(); throw new
1092
                         * DriverException(e); }
1093
                         */
1094
                }
1095

    
1096
                /*
1097
                 * (non-Javadoc)
1098
                 *
1099
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1100
                 */
1101
                public int getFieldCount() throws DriverException {
1102
                        return fastAccessFields.size();
1103
                }
1104

    
1105
                /*
1106
                 * (non-Javadoc)
1107
                 *
1108
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
1109
                 */
1110
                public String getFieldName(int fieldId) throws DriverException {
1111
//                        int i=0;
1112
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1113
//                                InternalField fld = (InternalField) iter.next();
1114
//                                if (i == fieldId)
1115
//                                        return fld.getFieldDesc().getFieldAlias();
1116
//                                i++;
1117
//
1118
//                        }
1119
//                        throw new DriverException("FieldId " + fieldId + " not found ");
1120
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1121
                        return aux.getFieldAlias();
1122
                        // return null;
1123
                        // return ods.getFieldName(fieldId);
1124
                }
1125

    
1126
                /*
1127
                 * (non-Javadoc)
1128
                 *
1129
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1130
                 */
1131
                public long getRowCount() {
1132
                        try {
1133
                                return (int) (ods.getRowCount() + numAdd)
1134
                                                - delRows.cardinality();// -
1135
                                // expansionFile.getInvalidRows().cardinality();
1136
                        } catch (DriverException e) {
1137
                                // TODO Auto-generated catch block
1138
                                e.printStackTrace();
1139
                        }
1140

    
1141
                        return 0;
1142
                }
1143

    
1144
                /*
1145
                 * (non-Javadoc)
1146
                 *
1147
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1148
                 */
1149
                public int getFieldType(int fieldId) throws DriverException {
1150
//                        int i=0;
1151
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1152
//                                InternalField fld = (InternalField) iter.next();
1153
//                                if (i == fieldId)
1154
//                                        return fld.getFieldDesc().getFieldType();
1155
//                                i++;
1156
//
1157
//                        }
1158
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1159
                        return aux.getFieldType();
1160

    
1161
//                        return ods.getFieldType(i);
1162
                }
1163

    
1164
                public int getFieldWidth(int fieldId) throws DriverException {
1165
//                        int i=0;
1166
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1167
//                                InternalField fld = (InternalField) iter.next();
1168
////                                if (fld.getFieldIndex() == i)
1169
////                                        return fld.getFieldDesc().getFieldLength();
1170
//                                if (i == fieldId)
1171
//                                        return fld.getFieldDesc().getFieldLength();
1172
//                                i++;
1173
//
1174
//                        }
1175
//
1176
//                        return ods.getFieldWidth(i);
1177
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1178
                        return aux.getFieldLength();
1179

    
1180
                }
1181

    
1182
                public void reload() throws IOException, DriverException {
1183
                        ods.reload();
1184

    
1185
                }
1186
        }
1187

    
1188
        public CommandRecord getCommandRecord() {
1189
                return cr;
1190
        }
1191

    
1192
        protected void fireAfterRemoveRow(int index, int sourceType) {
1193
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1194
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1195
                if (complex){
1196
                        rowEvents.add(event);
1197
                        return;
1198
                }
1199
                for (int i = 0; i < editionListeners.size(); i++) {
1200
                        IEditionListener listener = (IEditionListener) editionListeners
1201
                                        .get(i);
1202
                        listener.afterRowEditEvent(null, event);
1203
                }
1204

    
1205
        }
1206

    
1207
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1208
                Cancel cancel = new Cancel();
1209
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1210
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1211
                for (int i = 0; i < editionListeners.size(); i++) {
1212
                        IEditionListener listener = (IEditionListener) editionListeners
1213
                                        .get(i);
1214
                        listener.beforeRowEditEvent(null, event);
1215
                        if (cancel.isCanceled())
1216
                                return true;
1217
                }
1218
                return false;
1219
        }
1220

    
1221
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1222
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1223
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1224
                if (complex){
1225
                        rowEvents.add(event);
1226
                        return;
1227
                }
1228
                for (int i = 0; i < editionListeners.size(); i++) {
1229
                        IEditionListener listener = (IEditionListener) editionListeners
1230
                                        .get(i);
1231
                        listener.afterRowEditEvent(feat, event);
1232
                }
1233
        }
1234

    
1235
        protected void fireAfterFieldAdded(FieldDescription field) {
1236
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1237
                                EditionEvent.CHANGE_TYPE_ADD);
1238
                if (complex) {
1239
                        fieldEvents.add(event);
1240
                        return;
1241
                }
1242
                for (int i = 0; i < editionListeners.size(); i++) {
1243
                        IEditionListener listener = (IEditionListener) editionListeners
1244
                                        .get(i);
1245
                        listener.afterFieldEditEvent(event);
1246

    
1247
                }
1248
        }
1249

    
1250
        protected void fireAfterFieldRemoved(FieldDescription field) {
1251
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1252
                                EditionEvent.CHANGE_TYPE_DELETE);
1253
                if (complex) {
1254
                        fieldEvents.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
        protected void fireAfterFieldModified(FieldDescription field) {
1265
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1266
                                EditionEvent.CHANGE_TYPE_MODIFY);
1267
                if (complex) {
1268
                        fieldEvents.add(event);
1269
                        return;
1270
                }
1271
                for (int i = 0; i < editionListeners.size(); i++) {
1272
                        IEditionListener listener = (IEditionListener) editionListeners
1273
                                        .get(i);
1274
                        listener.afterFieldEditEvent(event);
1275
                }
1276
        }
1277

    
1278

    
1279
        protected boolean fireBeforeRowAdded(int sourceType)
1280
                        throws DriverIOException, IOException {
1281
                Cancel cancel = new Cancel();
1282
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, getRowCount(),
1283
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1284
                for (int i = 0; i < editionListeners.size(); i++) {
1285
                        IEditionListener listener = (IEditionListener) editionListeners
1286
                                        .get(i);
1287
                        listener.beforeRowEditEvent(null, event);
1288
                        if (cancel.isCanceled())
1289
                                return true;
1290
                }
1291
                return false;
1292
        }
1293

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

    
1309
        protected boolean fireBeforeRemoveField(FieldDescription field)
1310
        throws EditionException {
1311
                Cancel cancel = new Cancel();
1312
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1313
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1314
                for (int i = 0; i < editionListeners.size(); i++) {
1315
                        IEditionListener listener = (IEditionListener) editionListeners
1316
                        .get(i);
1317
                        listener.beforeFieldEditEvent(event);
1318
                        if (cancel.isCanceled())
1319
                                return true;
1320
                }
1321
                return false;
1322
        }
1323

    
1324

    
1325
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1326
                Cancel cancel = new Cancel();
1327
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1328
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1329
                for (int i = 0; i < editionListeners.size(); i++) {
1330
                        IEditionListener listener = (IEditionListener) editionListeners
1331
                                        .get(i);
1332
                        listener.beforeRowEditEvent(feat, event);
1333
                        if (cancel.isCanceled())
1334
                                return true;
1335
                }
1336
                return false;
1337
        }
1338

    
1339
        protected void fireAfterModifyRow(int index, int sourceType) {
1340
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1341
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1342
                if (complex){
1343
                        rowEvents.add(event);
1344
                        return;
1345
                }
1346
                for (int i = 0; i < editionListeners.size(); i++) {
1347
                        IEditionListener listener = (IEditionListener) editionListeners
1348
                                        .get(i);
1349
                        listener.afterRowEditEvent(null, event);
1350
                }
1351

    
1352
        }
1353

    
1354
        protected void fireStartEditionEvent(int sourceType) {
1355
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1356
                                sourceType);
1357
                for (int i = 0; i < editionListeners.size(); i++) {
1358
                        IEditionListener listener = (IEditionListener) editionListeners
1359
                                        .get(i);
1360
                        listener.processEvent(ev);
1361
                }
1362

    
1363
        }
1364

    
1365
        protected void fireStopEditionEvent(int sourceType) {
1366
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1367
                                sourceType);
1368
                for (int i = 0; i < editionListeners.size(); i++) {
1369
                        IEditionListener listener = (IEditionListener) editionListeners
1370
                                        .get(i);
1371
                        listener.processEvent(ev);
1372
                }
1373

    
1374
        }
1375

    
1376
        protected void fireCancelEditionEvent(int sourceType) {
1377
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1378
                                sourceType);
1379
                for (int i = 0; i < editionListeners.size(); i++) {
1380
                        IEditionListener listener = (IEditionListener) editionListeners
1381
                                        .get(i);
1382
                        listener.processEvent(ev);
1383
                }
1384

    
1385
        }
1386

    
1387
        public void addEditionListener(IEditionListener listener) {
1388
                if (!editionListeners.contains(listener))
1389
                        editionListeners.add(listener);
1390
        }
1391

    
1392
        public void removeEditionListener(IEditionListener listener) {
1393
                editionListeners.remove(listener);
1394
        }
1395

    
1396
        /**
1397
         * @return
1398
         * @uml.property  name="writer"
1399
         */
1400
        public IWriter getWriter() {
1401
                return writer;
1402
        }
1403

    
1404
        /**
1405
         * @param writer
1406
         * @uml.property  name="writer"
1407
         */
1408
        protected void setWriter(IWriter writer) {
1409
                this.writer = writer;
1410

    
1411
        }
1412
        /*
1413
         * azabala: esto funciona para todos los drivers gdbms
1414
         * salvo para MySQL, que necesita que el ITableDefinition
1415
         * contenga el nombre de la tabla (y por tanto requiere
1416
         * DBLayerDefinition-en realidad hace falta DBTableDefinition)
1417
         * TODO REVISAR LA ARQUITECTURA DE ESTO
1418
         *
1419
         * */
1420
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1421
                        DriverException {
1422
                Driver originalDriver = getOriginalDriver();
1423
                if(! (originalDriver instanceof AlphanumericDBDriver)){
1424
                        TableDefinition tableDef = new TableDefinition();
1425
                        tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1426
                        tableDef.setName(getRecordset().getSourceInfo().name);
1427
                        return tableDef;
1428
                }else{
1429
                        AlphanumericDBDriver dbDriver = (AlphanumericDBDriver)originalDriver;
1430
                        return dbDriver.getTableDefinition();
1431

    
1432
                }
1433

    
1434

    
1435
        }
1436

    
1437
        public void validateRow(IRow row,int sourceType) throws EditionException {
1438
                for (int i = 0; i < rules.size(); i++) {
1439
                        IRule rule = (IRule) rules.get(i);
1440
                        boolean bAux = rule.validate(row,sourceType);
1441
                        if (bAux == false) {
1442
                                EditionException ex = new EditionException(
1443
                                                "NOT follow the rule: " + rule.getDescription());
1444
                                // TODO: Lanzar una RuleException con datos como el registro
1445
                                // que no cumple, la regla que no lo ha cumplido, etc.
1446
                                throw ex;
1447
                        }
1448
                }
1449
        }
1450

    
1451
        /**
1452
         * @return
1453
         * @uml.property  name="rules"
1454
         */
1455
        public ArrayList getRules() {
1456
                return rules;
1457
        }
1458

    
1459
        /**
1460
         * @param rules
1461
         * @uml.property  name="rules"
1462
         */
1463
        public void setRules(ArrayList rules) {
1464
                this.rules = rules;
1465
        }
1466

    
1467
        private void clean() throws IOException, DriverException {
1468
                expansionFile.close();
1469
                relations.clear();
1470
                numAdd = 0;
1471
                delRows.clear();
1472
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1473
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1474
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1475
                // reload completo.
1476
                initalizeFields(ods);
1477

    
1478
//                listInternalFields.clear();
1479
//                listInternalFields.add(actualFields);
1480
        }
1481

    
1482
        /*
1483
         * (non-Javadoc)
1484
         *
1485
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1486
         */
1487
        public IFieldManager getFieldManager() {
1488
                if (ods.getDriver() instanceof IWriteable)
1489
                {
1490
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1491
                        if ((writer != null) && (writer instanceof IFieldManager))
1492
                        {
1493
                                IFieldManager fldManager = (IFieldManager) writer;
1494
                                return fldManager;
1495
                        }
1496
                }
1497
                return null;
1498
        }
1499

    
1500
        /**
1501
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1502
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1503
         *
1504
         * @param edRow
1505
         * @param indexInternalFields
1506
         * @return
1507
         */
1508
        public IRowEdited createExternalRow(IRowEdited edRow,
1509
                        int indexInternalFields) {
1510

    
1511
                // para acelerar
1512
                if (bFieldsHasBeenChanged == false)
1513
                        return edRow;
1514

    
1515
                Value[] att = edRow.getAttributes();
1516
                TreeMap ancientFields = (TreeMap) listInternalFields
1517
                                .get(indexInternalFields);
1518
                Value[] newAtt = new Value[actualFields.size()];
1519
                Collection aux = actualFields.values();
1520
                Iterator it = aux.iterator();
1521
                int i = 0;
1522
                Value val = null;
1523
                while (it.hasNext()) {
1524
                        // Para cada campo de los actuales, miramos si ya estaba cuando
1525
                        // el registro estaba guardado.
1526
                        // Si estaba, cogemos el valor de ese campo en el registro
1527
                        // guardado. Si no estaba, ha sido a?adido despu?s y ponemos
1528
                        // su valor por defecto.
1529
                        // Nota importante: fieldIndex es el ?ndice del campo cuando
1530
                        // se guard?. NO es el ?ndice actual dentro de actualFields.
1531
                        // Se usa SOLO para recuperar el valor de los atributos
1532
                        // antiguos. Por eso no nos preocupamos de mantener actuallizados
1533
                        // el resto de campos cuando se borra o a?ade un nuevo campo.
1534
                        InternalField fld = (InternalField) it.next();
1535
                        // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
1536
                        if (ancientFields.containsKey(fld.getFieldId())) {
1537
                                InternalField ancientField = (InternalField) ancientFields
1538
                                                .get(fld.getFieldId());
1539
                                val = att[ancientField.getFieldIndex()];
1540
                                // val = att[ancientField.getFieldId().intValue()];
1541
                                // System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + " val" + val);
1542
                        } else
1543
                                val = fld.getFieldDesc().getDefaultValue();
1544
                        newAtt[i++] = val;
1545
                }
1546
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1547
                newRow.setAttributes(newAtt);
1548
                return newRow;
1549
        }
1550

    
1551
        public void removeField(String fieldName) throws EditionException {
1552

    
1553
                InternalField fld = findFieldByName(fieldName);
1554
                if (fld == null)
1555
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1556
                Command command = new RemoveFieldCommand(this, fld);
1557
                if (complex) {
1558
                        commands.add(command);
1559
                } else {
1560
                        cr.pushCommand(command);
1561
                }
1562
                doRemoveField(fld);
1563

    
1564
        }
1565

    
1566
        private InternalField findFieldByName(String fieldName) {
1567
                Collection aux = actualFields.values();
1568
                Iterator it = aux.iterator();
1569
                while (it.hasNext()) {
1570
                        InternalField fld = (InternalField) it.next();
1571
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1572
                                return fld;
1573
                }
1574

    
1575
                return null;
1576
        }
1577

    
1578
        public void undoRemoveField(InternalField field) throws EditionException {
1579
                // field.setDeleted(false);
1580
//                field.setFieldIndex(actualFields.size());
1581
                actualFields.put(field.getFieldId(), field);
1582
                fieldsChanged();
1583
                fireAfterFieldAdded(field.getFieldDesc());
1584
        }
1585

    
1586
        public void doRemoveField(InternalField field) throws EditionException {
1587
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1588
                if (cancel) return;
1589
                actualFields.remove(field.getFieldId());
1590
                fieldsChanged();
1591
                fireAfterFieldRemoved(field.getFieldDesc());
1592
        }
1593

    
1594
        public void renameField(String antName, String newName) throws EditionException {
1595

    
1596
                InternalField fld = findFieldByName(antName);
1597
                Command command = new RenameFieldCommand(this, fld, newName);
1598
                if (complex) {
1599
                        commands.add(command);
1600
                } else {
1601
                        cr.pushCommand(command);
1602
                }
1603
                doRenameField(fld, newName);
1604

    
1605
        }
1606

    
1607
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1608
                field.getFieldDesc().setFieldAlias(antName);
1609
                fieldsChanged();
1610
                fireAfterFieldModified(field.getFieldDesc());
1611

    
1612
        }
1613

    
1614
        public void doRenameField(InternalField field, String newName) throws EditionException  {
1615
                field.getFieldDesc().setFieldAlias(newName);
1616
                fieldsChanged();
1617
                fireAfterFieldModified(field.getFieldDesc());
1618

    
1619
        }
1620

    
1621

    
1622
        public void addField(FieldDescription field) throws EditionException {
1623

    
1624
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1625
                Command command = new AddFieldCommand(this, fld);
1626
                if (complex) {
1627
                        commands.add(command);
1628
                } else {
1629
                        cr.pushCommand(command);
1630
                }
1631
                listFields.add(fld);
1632
                doAddField(fld);
1633

    
1634
        }
1635

    
1636
        public void undoAddField(InternalField field) throws EditionException {
1637
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1638
                if (cancel)
1639
                        return;
1640

    
1641
                // field.setDeleted(true);
1642
                actualFields.remove(field.getFieldId());
1643
                fieldsChanged();
1644
                fireAfterFieldRemoved(field.getFieldDesc());
1645

    
1646
        }
1647

    
1648
        public int doAddField(InternalField field) throws EditionException {
1649
                boolean cancel;
1650
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1651
                if (cancel)
1652
                        return -1;
1653

    
1654
                // field.setDeleted(false);
1655
//                field.setFieldIndex(actualFields.size());
1656
                actualFields.put(field.getFieldId(), field);
1657
                fieldsChanged();
1658
                fireAfterFieldAdded(field.getFieldDesc());
1659
//                return field.getFieldIndex();
1660
                return field.getFieldId().intValue();
1661
        }
1662

    
1663
        public Driver getOriginalDriver()
1664
        {
1665
                return ods.getDriver();
1666
        }
1667

    
1668
        /**
1669
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1670
         * to be created next time it is needed
1671
         */
1672
        public void cleanSelectableDatasource() {
1673
                ds = null;
1674
        }
1675

    
1676
        public FieldDescription[] getFieldsDescription() {
1677
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1678
        }
1679

    
1680

    
1681
//        private InternalField getInternalFieldByIndex(int fieldId)
1682
//        {
1683
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1684
//                        InternalField fld = (InternalField) iter.next();
1685
//                        if (fld.getFieldIndex() == fieldId)
1686
//                                return fld;
1687
//                }
1688
//                return null;
1689
//        }
1690

    
1691
}