Statistics
| Revision:

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

History | View | Annotate | Download (48.1 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 fieldEvents=new ArrayList();
142
        private ArrayList rowEvents=new ArrayList();
143

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

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

    
167

    
168
        }
169

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

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

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

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

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

    
242
                fireStartEditionEvent(sourceType);
243
        }
244

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

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

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

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

    
316
                writer.preProcess();
317

    
318
                try {
319

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

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

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

    
348
                        }
349

    
350
                        int rowCount = getRowCount();
351
                        if (writer.isWriteAll())
352
                        {
353
                                for (int i = 0; i < rowCount; i++) {
354
                                        IRowEdited rowEdited = getRow(i);
355

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

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

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

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

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

    
407
        }
408

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

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

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

    
467

    
468

    
469
        }
470

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

    
489
        }
490
        public int getNewIndex() throws com.hardcode.gdbms.engine.data.driver.DriverException {
491
                int index=(int)ods.getRowCount() + numAdd;
492
                return index;
493
        }
494
        /*
495
         * (non-Javadoc)
496
         *
497
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
498
         *      java.lang.String)
499
         */
500
        public int addRow(IRow row, String descrip, int sourceType)
501
                        throws DriverIOException, IOException {
502

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

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

    
520
                return calculatedIndex;
521
        }
522

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

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

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

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

    
572
        }
573

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

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

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

    
601
                return pos;
602
        }
603

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
872
                                try {
873

    
874
                                        /*
875
                                        ds = new SelectableDataSource(LayerFactory
876
                                                        .getDataSourceFactory().createRandomDataSource(
877
                                                                        name, DataSourceFactory.MANUAL_OPENING));
878
                                        */
879
                                        // CHEMA: AUTOMATIC DATA SOURCE
880
                                        ds = new SelectableDataSource(LayerFactory
881
                                                        .getDataSourceFactory().createRandomDataSource(
882
                                                                        name, DataSourceFactory.AUTOMATIC_OPENING));
883
                                        ds.start();
884
                                        ds.setSelectionSupport(ods.getSelectionSupport());
885

    
886
                                } catch (NoSuchTableException e) {
887
                                        throw new RuntimeException(e);
888
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
889
                                        throw new RuntimeException(e);
890
                                }
891
                        }
892

    
893
                        return ds;
894
                } else {
895
                        return ods;
896
                }
897
        }
898

    
899
        /**
900
         * Return always the original recordset (even when is editing,
901
         * nor the getRecorset() method)
902
         *
903
         * */
904
        public SelectableDataSource getOriginalRecordset(){
905
                return ods;
906
        }
907

    
908

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

    
923
        public void setSelection(FBitSet selection) {
924
                /*
925
                 * try { getRecordset().setSelection(selection); } catch
926
                 * (DriverLoadException e) { // TODO Auto-generated catch block
927
                 * e.printStackTrace(); }
928
                 */
929
                getRecordset().setSelection(selection);
930
        }
931

    
932
        /**
933
         * DOCUMENT ME!
934
         *
935
         * @return DOCUMENT ME!
936
         */
937
        public boolean isEditing() {
938
                return isEditing;
939
        }
940

    
941
        public int getInversedIndex(long rowIndex) {
942
                int intervalNotDeleted = 0;
943
                int antDeleted = -1;
944
                int idPedido = (int) rowIndex;
945
                int numNotDeleted = 0;
946
                int numBorradosAnt = 0;
947

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

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

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

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

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

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

    
1038
                /*
1039
                 * (non-Javadoc)
1040
                 *
1041
                 * @see com.hardcode.driverManager.Driver#getName()
1042
                 */
1043
                public String getName() {
1044
                        return ods.getName();
1045
                }
1046

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

    
1058

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

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

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

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

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

    
1145
                        return 0;
1146
                }
1147

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

    
1165
//                        return ods.getFieldType(i);
1166
                }
1167

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

    
1184
                }
1185

    
1186
                public void reload() throws IOException, DriverException {
1187
                        ods.reload();
1188

    
1189
                }
1190
        }
1191

    
1192
        public CommandRecord getCommandRecord() {
1193
                return cr;
1194
        }
1195

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

    
1209
        }
1210

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

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

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

    
1251
                }
1252
        }
1253

    
1254
        protected void fireAfterFieldRemoved(FieldDescription field) {
1255
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1256
                                EditionEvent.CHANGE_TYPE_DELETE);
1257
                if (complex) {
1258
                        fieldEvents.add(event);
1259
                        return;
1260
                }
1261
                for (int i = 0; i < editionListeners.size(); i++) {
1262
                        IEditionListener listener = (IEditionListener) editionListeners
1263
                                        .get(i);
1264
                        listener.afterFieldEditEvent(event);
1265
                }
1266
        }
1267

    
1268
        protected void fireAfterFieldModified(FieldDescription field) {
1269
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1270
                                EditionEvent.CHANGE_TYPE_MODIFY);
1271
                if (complex) {
1272
                        fieldEvents.add(event);
1273
                        return;
1274
                }
1275
                for (int i = 0; i < editionListeners.size(); i++) {
1276
                        IEditionListener listener = (IEditionListener) editionListeners
1277
                                        .get(i);
1278
                        listener.afterFieldEditEvent(event);
1279
                }
1280
        }
1281

    
1282

    
1283
        protected boolean fireBeforeRowAdded(int sourceType)
1284
                        throws DriverIOException, IOException {
1285
                Cancel cancel = new Cancel();
1286
                BeforeRowEditEvent event;
1287
                try {
1288
                        event = new BeforeRowEditEvent(this, getNewIndex(),
1289
                                        EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1290
                } catch (DriverException e) {
1291
                        throw new DriverIOException(e);
1292
                }
1293
                for (int i = 0; i < editionListeners.size(); i++) {
1294
                        IEditionListener listener = (IEditionListener) editionListeners
1295
                                        .get(i);
1296
                        listener.beforeRowEditEvent(null, event);
1297
                        if (cancel.isCanceled())
1298
                                return true;
1299
                }
1300
                return false;
1301
        }
1302

    
1303
        protected boolean fireBeforeFieldAdded(FieldDescription field)
1304
        throws EditionException {
1305
                Cancel cancel = new Cancel();
1306
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1307
                EditionEvent.CHANGE_TYPE_ADD, cancel);
1308
                for (int i = 0; i < editionListeners.size(); i++) {
1309
                        IEditionListener listener = (IEditionListener) editionListeners
1310
                        .get(i);
1311
                        listener.beforeFieldEditEvent(event);
1312
                        if (cancel.isCanceled())
1313
                                return true;
1314
                }
1315
                return false;
1316
        }
1317

    
1318
        protected boolean fireBeforeRemoveField(FieldDescription field)
1319
        throws EditionException {
1320
                Cancel cancel = new Cancel();
1321
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1322
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1323
                for (int i = 0; i < editionListeners.size(); i++) {
1324
                        IEditionListener listener = (IEditionListener) editionListeners
1325
                        .get(i);
1326
                        listener.beforeFieldEditEvent(event);
1327
                        if (cancel.isCanceled())
1328
                                return true;
1329
                }
1330
                return false;
1331
        }
1332

    
1333

    
1334
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1335
                Cancel cancel = new Cancel();
1336
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1337
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1338
                for (int i = 0; i < editionListeners.size(); i++) {
1339
                        IEditionListener listener = (IEditionListener) editionListeners
1340
                                        .get(i);
1341
                        listener.beforeRowEditEvent(feat, event);
1342
                        if (cancel.isCanceled())
1343
                                return true;
1344
                }
1345
                return false;
1346
        }
1347

    
1348
        protected void fireAfterModifyRow(int index, int sourceType) {
1349
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1350
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1351
                if (complex){
1352
                        rowEvents.add(event);
1353
                        return;
1354
                }
1355
                for (int i = 0; i < editionListeners.size(); i++) {
1356
                        IEditionListener listener = (IEditionListener) editionListeners
1357
                                        .get(i);
1358
                        listener.afterRowEditEvent(null, event);
1359
                }
1360

    
1361
        }
1362

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

    
1372
        }
1373

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

    
1383
        }
1384

    
1385
        protected void fireCancelEditionEvent(int sourceType) {
1386
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1387
                                sourceType);
1388
                for (int i = 0; i < editionListeners.size(); i++) {
1389
                        IEditionListener listener = (IEditionListener) editionListeners
1390
                                        .get(i);
1391
                        listener.processEvent(ev);
1392
                }
1393

    
1394
        }
1395

    
1396
        public void addEditionListener(IEditionListener listener) {
1397
                if (!editionListeners.contains(listener))
1398
                        editionListeners.add(listener);
1399
        }
1400

    
1401
        public void removeEditionListener(IEditionListener listener) {
1402
                editionListeners.remove(listener);
1403
        }
1404

    
1405
        public IWriter getWriter() {
1406
                return writer;
1407
        }
1408

    
1409
        protected void setWriter(IWriter writer) {
1410
                this.writer = writer;
1411

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

    
1435

    
1436
        }
1437

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

    
1452
        public ArrayList getRules() {
1453
                return rules;
1454
        }
1455

    
1456
        public void setRules(ArrayList rules) {
1457
                this.rules = rules;
1458
        }
1459

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

    
1471
//                listInternalFields.clear();
1472
//                listInternalFields.add(actualFields);
1473
        }
1474

    
1475
        /*
1476
         * (non-Javadoc)
1477
         *
1478
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1479
         */
1480
        public IFieldManager getFieldManager() {
1481
                if (ods.getDriver() instanceof IWriteable)
1482
                {
1483
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1484
                        if ((writer != null) && (writer instanceof IFieldManager))
1485
                        {
1486
                                IFieldManager fldManager = (IFieldManager) writer;
1487
                                return fldManager;
1488
                        }
1489
                }
1490
                return null;
1491
        }
1492

    
1493
        /**
1494
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1495
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1496
         *
1497
         * @param edRow
1498
         * @param indexInternalFields
1499
         * @return
1500
         */
1501
        public IRowEdited createExternalRow(IRowEdited edRow,
1502
                        int indexInternalFields) {
1503

    
1504
                // para acelerar
1505
                if (bFieldsHasBeenChanged == false)
1506
                        return edRow;
1507

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

    
1544
        public void removeField(String fieldName) throws EditionException {
1545

    
1546
                InternalField fld = findFieldByName(fieldName);
1547
                if (fld == null)
1548
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1549
                Command command = new RemoveFieldCommand(this, fld);
1550
                if (complex) {
1551
                        commands.add(command);
1552
                } else {
1553
                        cr.pushCommand(command);
1554
                }
1555
                doRemoveField(fld);
1556

    
1557
        }
1558

    
1559
        private InternalField findFieldByName(String fieldName) {
1560
                Collection aux = actualFields.values();
1561
                Iterator it = aux.iterator();
1562
                while (it.hasNext()) {
1563
                        InternalField fld = (InternalField) it.next();
1564
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1565
                                return fld;
1566
                }
1567

    
1568
                return null;
1569
        }
1570

    
1571
        public void undoRemoveField(InternalField field) throws EditionException {
1572
                // field.setDeleted(false);
1573
//                field.setFieldIndex(actualFields.size());
1574
                actualFields.put(field.getFieldId(), field);
1575
                fieldsChanged();
1576
                fireAfterFieldAdded(field.getFieldDesc());
1577
        }
1578

    
1579
        public void doRemoveField(InternalField field) throws EditionException {
1580
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1581
                if (cancel) return;
1582
                actualFields.remove(field.getFieldId());
1583
                fieldsChanged();
1584
                fireAfterFieldRemoved(field.getFieldDesc());
1585
        }
1586

    
1587
        public void renameField(String antName, String newName) throws EditionException {
1588

    
1589
                InternalField fld = findFieldByName(antName);
1590
                Command command = new RenameFieldCommand(this, fld, newName);
1591
                if (complex) {
1592
                        commands.add(command);
1593
                } else {
1594
                        cr.pushCommand(command);
1595
                }
1596
                doRenameField(fld, newName);
1597

    
1598
        }
1599

    
1600
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1601
                field.getFieldDesc().setFieldAlias(antName);
1602
                fieldsChanged();
1603
                fireAfterFieldModified(field.getFieldDesc());
1604

    
1605
        }
1606

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

    
1612
        }
1613

    
1614

    
1615
        public void addField(FieldDescription field) throws EditionException {
1616

    
1617
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1618
                Command command = new AddFieldCommand(this, fld);
1619
                if (complex) {
1620
                        commands.add(command);
1621
                } else {
1622
                        cr.pushCommand(command);
1623
                }
1624
                listFields.add(fld);
1625
                doAddField(fld);
1626

    
1627
        }
1628

    
1629
        public void undoAddField(InternalField field) throws EditionException {
1630
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1631
                if (cancel)
1632
                        return;
1633

    
1634
                // field.setDeleted(true);
1635
                actualFields.remove(field.getFieldId());
1636
                fieldsChanged();
1637
                fireAfterFieldRemoved(field.getFieldDesc());
1638

    
1639
        }
1640

    
1641
        public int doAddField(InternalField field) throws EditionException {
1642
                boolean cancel;
1643
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1644
                if (cancel)
1645
                        return -1;
1646

    
1647
                // field.setDeleted(false);
1648
//                field.setFieldIndex(actualFields.size());
1649
                actualFields.put(field.getFieldId(), field);
1650
                fieldsChanged();
1651
                fireAfterFieldAdded(field.getFieldDesc());
1652
//                return field.getFieldIndex();
1653
                return field.getFieldId().intValue();
1654
        }
1655

    
1656
        public Driver getOriginalDriver()
1657
        {
1658
                return ods.getDriver();
1659
        }
1660

    
1661
        /**
1662
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1663
         * to be created next time it is needed
1664
         */
1665
        public void cleanSelectableDatasource() {
1666
                ds = null;
1667
        }
1668

    
1669
        public FieldDescription[] getFieldsDescription() {
1670
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1671
        }
1672

    
1673

    
1674
//        private InternalField getInternalFieldByIndex(int fieldId)
1675
//        {
1676
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1677
//                        InternalField fld = (InternalField) iter.next();
1678
//                        if (fld.getFieldIndex() == fieldId)
1679
//                                return fld;
1680
//                }
1681
//                return null;
1682
//        }
1683

    
1684
}