Statistics
| Revision:

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

History | View | Annotate | Download (51.6 KB)

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

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

    
11
import com.hardcode.driverManager.Driver;
12
import com.hardcode.driverManager.DriverLoadException;
13
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
14
import com.hardcode.gdbms.driver.exceptions.ReloadDriverException;
15
import com.hardcode.gdbms.driver.exceptions.WriteDriverException;
16
import com.hardcode.gdbms.engine.data.DataSourceFactory;
17
import com.hardcode.gdbms.engine.data.NoSuchTableException;
18
import com.hardcode.gdbms.engine.data.driver.AlphanumericDBDriver;
19
import com.hardcode.gdbms.engine.data.driver.DriverException;
20
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
21
import com.hardcode.gdbms.engine.data.edition.DataWare;
22
import com.hardcode.gdbms.engine.values.Value;
23
import com.iver.cit.gvsig.exceptions.commands.EditionCommandException;
24
import com.iver.cit.gvsig.exceptions.expansionfile.CloseExpansionFileException;
25
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
26
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileWriteException;
27
import com.iver.cit.gvsig.exceptions.layers.CancelEditingLayerException;
28
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
29
import com.iver.cit.gvsig.exceptions.validate.ValidateRowException;
30
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
31
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
32
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
33
import com.iver.cit.gvsig.fmap.core.DefaultRow;
34
import com.iver.cit.gvsig.fmap.core.IRow;
35
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
36
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
37
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
38
import com.iver.cit.gvsig.fmap.drivers.TableDefinition;
39
import com.iver.cit.gvsig.fmap.edition.commands.AddFieldCommand;
40
import com.iver.cit.gvsig.fmap.edition.commands.AddRowCommand;
41
import com.iver.cit.gvsig.fmap.edition.commands.Command;
42
import com.iver.cit.gvsig.fmap.edition.commands.CommandCollection;
43
import com.iver.cit.gvsig.fmap.edition.commands.CommandRecord;
44
import com.iver.cit.gvsig.fmap.edition.commands.MemoryCommandRecord;
45
import com.iver.cit.gvsig.fmap.edition.commands.ModifyRowCommand;
46
import com.iver.cit.gvsig.fmap.edition.commands.RemoveFieldCommand;
47
import com.iver.cit.gvsig.fmap.edition.commands.RemoveRowCommand;
48
import com.iver.cit.gvsig.fmap.edition.commands.RenameFieldCommand;
49
import com.iver.cit.gvsig.fmap.edition.fieldmanagers.AbstractFieldManager;
50
import com.iver.cit.gvsig.fmap.edition.rules.IRule;
51
import com.iver.cit.gvsig.fmap.layers.FBitSet;
52
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
53
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
54
import com.iver.cit.gvsig.fmap.operations.Cancel;
55

    
56
/**
57
 * DOCUMENT ME!
58
 *
59
 * @author Vicente Caballero Navarro
60
 */
61
public class EditableAdapter implements IEditableSource, IWriteable {
62
        protected boolean isEditing = false;
63

    
64
        private SelectableDataSource ds = null;
65

    
66
        protected FBitSet delRows = new FBitSet();
67

    
68
        private CommandRecord cr;
69

    
70
        protected IWriter writer;
71

    
72
        /**
73
         * Flag que indica que hay que tomar las siguientes operaciones como una
74
         * operaci?n at?mica
75
         */
76
        private boolean complex = false;
77

    
78
        private CommandCollection commands = null;
79

    
80
        protected ArrayList listFields = new ArrayList();
81

    
82
        protected ArrayList listInternalFields = new ArrayList();
83

    
84
        protected boolean bFieldsHasBeenChanged = false;
85

    
86
        /**
87
         * La clave ser? el fieldId. Para buscar si un value de una row ha de ser
88
         * rellenado con defaultValue o con lo que venga del expansion file,
89
         * miraremos si existe en este hash. Si existe, usamos el value del
90
         * expansion file. Si no existe, usamos el defaultValue del campo busc?ndolo
91
         * en la lista internalFields. Por cierto, en listInternalFields NO se
92
         * borran campos. Solo se van a?adiendo nuevos actualFields.
93
         */
94
        protected TreeMap actualFields; // la clave ser? el fieldId.
95

    
96
        protected ArrayList fastAccessFields = new ArrayList();
97

    
98
        protected class MyFieldManager extends AbstractFieldManager {
99

    
100
                public boolean alterTable() throws WriteDriverException {
101
                        return getFieldManager().alterTable();
102
                }
103

    
104
                public void addField(FieldDescription fieldDesc) {
105
                        super.addField(fieldDesc);
106
                }
107

    
108
                public FieldDescription removeField(String fieldName) {
109
                        // TODO Auto-generated method stub
110
                        return super.removeField(fieldName);
111
                }
112

    
113
                public void renameField(String antName, String newName) {
114
                        // TODO Auto-generated method stub
115
                        super.renameField(antName, newName);
116
                }
117

    
118
        }
119

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

    
135
        /*
136
         * Fichero en el que se guardan las nuevas geometr?as, producto de adiciones
137
         * o de modificaciones
138
         */
139
        protected ExpansionFile expansionFile;
140

    
141
        protected int numAdd = 0;
142

    
143
        private ObjectDriver editingDriver = new myObjectDriver();
144

    
145
        private SelectableDataSource ods;
146

    
147
        private ArrayList editionListeners = new ArrayList();
148

    
149
        private ArrayList rules = new ArrayList();
150

    
151
        protected int actualIndexFields;
152

    
153
        protected boolean isFullExtentDirty = false;
154

    
155
        private ArrayList fieldEvents=new ArrayList();
156
        private ArrayList rowEvents=new ArrayList();
157

    
158
        /**
159
         * Crea un nuevo EditableAdapter.
160
         */
161
        public EditableAdapter() {
162
                expansionFile = new MemoryExpansionFile(this);
163
                cr = new MemoryCommandRecord();
164
        }
165

    
166
        /**
167
         * DOCUMENT ME!
168
         *
169
         * @param ds
170
         *            DOCUMENT ME!
171
         * @throws DriverException
172
         */
173
        public void setOriginalDataSource(SelectableDataSource ds) throws ReadDriverException {
174
                this.ods = ds;
175
                initalizeFields(ds);
176
                Driver drv = ods.getDriver();
177
                if (drv instanceof IWriteable) {
178
                        setWriter(((IWriteable) drv).getWriter());
179
                }
180

    
181

    
182
        }
183

    
184
        /**
185
         * @param ds
186
         * @throws ReadDriverException
187
         * @throws DriverException
188
         */
189
        private void initalizeFields(SelectableDataSource ds) throws ReadDriverException {
190
                FieldDescription[] fields = ds.getFieldsDescription();
191
                listInternalFields.clear();
192
                actualIndexFields = 0;
193
                actualFields = new TreeMap();
194
//                fastAccessFields = new ArrayList();
195
                for (int i=0; i < fields.length; i++)
196
                {
197
                        InternalField field = new InternalField(fields[i], InternalField.ORIGINAL, new Integer(i));
198
                        listFields.add(field);
199
                        // field.setFieldIndex(i);
200
                        actualFields.put(field.getFieldId(), field);
201
//                        fastAccessFields.add(fields[i]);
202
                        System.out.println("INITIALIZEFIELDS: FIELD " + field.getFieldDesc().getFieldAlias());
203
                }
204
                        fieldsChanged();
205
                        bFieldsHasBeenChanged = false;
206
        }
207

    
208
        private TreeMap deepCloneInternalFields(TreeMap col)
209
        {
210
                TreeMap clonedFields = new TreeMap();
211
                for (Iterator iter = col.values().iterator(); iter.hasNext();) {
212
                        InternalField fld = (InternalField) iter.next();
213
                        InternalField clonedField = fld.cloneInternalField();
214
                        clonedFields.put(clonedField.getFieldId(), clonedField);
215
                }
216

    
217
                return clonedFields;
218
        }
219
        private void fieldsChanged() throws ReadDriverException {
220
                fastAccessFields= new ArrayList();
221
                int index = 0;
222
                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
223
                        InternalField fld = (InternalField) iter.next();
224
                        fastAccessFields.add(fld.getFieldDesc());
225
                        fld.setFieldIndex(index++);
226
                }
227

    
228
                listInternalFields.add(deepCloneInternalFields(actualFields));
229
                actualIndexFields = listInternalFields.size()-1;
230
                ds = null;
231
                getRecordset().mapExternalFields();
232
                bFieldsHasBeenChanged = true;
233
        }
234

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

    
246
                fireStartEditionEvent(sourceType);
247
        }
248

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

    
271
        public void saveEdits(IWriter writer, int sourceType)
272
                        throws StopWriterVisitorException {
273

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

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

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

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

    
349
                        }
350

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

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

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

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

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

    
397
                } catch (ReadDriverException e) {
398
                        throw new StopWriterVisitorException(writer.getName(),e);
399
                } catch (StartWriterVisitorException e) {
400
                        throw new StopWriterVisitorException(writer.getName(),e);
401
                } catch (VisitorException e) {
402
                        throw new StopWriterVisitorException(writer.getName(),e);
403
                }
404

    
405
        }
406

    
407
        /**
408
         * DOCUMENT ME!
409
         *
410
         * @throws IOException
411
         *             DOCUMENT ME!
412
         */
413
        public void cancelEdition(int sourceType) throws CancelEditingLayerException {
414
                isEditing = false;
415
                try {
416
                        ds= null;
417
                        clean();
418
                        cr.clearAll();
419
                } catch (ReadDriverException e) {
420
                        throw new CancelEditingLayerException(writer.getName(),e);
421
                }
422
                fireCancelEditionEvent(sourceType);
423
        }
424

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

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

    
460

    
461

    
462
        }
463

    
464
        /**
465
         * DOCUMENT ME!
466
         *
467
         * @return DOCUMENT ME!
468
         * @throws ReadDriverException
469
         *
470
         * @throws DriverIOException
471
         *             DOCUMENT ME!
472
         * @throws IOException
473
         *             DOCUMENT ME!
474
         */
475
        public int getRowCount() throws ReadDriverException {
476
                        return (int) (ods.getRowCount() + numAdd) - delRows.cardinality();// -
477
                        // expansionFile.getInvalidRows().cardinality();
478
        }
479

    
480
        /*
481
         * (non-Javadoc)
482
         *
483
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
484
         *      java.lang.String)
485
         */
486
        public int addRow(IRow row, String descrip, int sourceType) throws ValidateRowException, ReadDriverException, ExpansionFileWriteException{
487
                validateRow(row,sourceType);
488

    
489
                int calculatedIndex = doAddRow(row, sourceType);
490
                Command command = new AddRowCommand(this, row, calculatedIndex,
491
                                sourceType);
492
                command.setDescription(descrip);
493
                if (complex) {
494
                        commands.add(command);
495
                } else {
496
                        cr.pushCommand(command);
497
                }
498

    
499
                return calculatedIndex;
500
        }
501

    
502
        /**
503
         * DOCUMENT ME!
504
         * @throws EditionCommandException
505
         *
506
         * @throws DriverIOException
507
         *             DOCUMENT ME!
508
         * @throws IOException
509
         *             DOCUMENT ME!
510
         */
511
        public void undo() throws EditionCommandException{
512
                // seleccion.clear();
513
                if (cr.moreUndoCommands()) {
514
                        cr.undoCommand();
515
                }
516
        }
517

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

    
534
        /*
535
         * (non-Javadoc)
536
         *
537
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
538
         */
539
        public void removeRow(int index, String descrip, int sourceType) throws ReadDriverException, ExpansionFileReadException {
540

    
541
                int calculatedIndex = getCalculatedIndex(index);
542
                Command command = new RemoveRowCommand(this, calculatedIndex,
543
                                sourceType);
544
                command.setDescription(descrip);
545
                if (complex) {
546
                        commands.add(command);
547
                } else {
548
                        cr.pushCommand(command);
549
                }
550
                doRemoveRow(calculatedIndex, sourceType);
551

    
552
        }
553

    
554
        /*
555
         * (non-Javadoc)
556
         *
557
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#modifyRow(int,
558
         *      com.iver.cit.gvsig.fmap.core.IRow)
559
         */
560
        public int modifyRow(int index, IRow row, String descrip, int sourceType) throws ValidateRowException, ExpansionFileWriteException, ReadDriverException, ExpansionFileReadException {
561
                validateRow(row,sourceType);
562
                int calculatedIndex = getCalculatedIndex(index);
563
                int pos = doModifyRow(calculatedIndex, row, sourceType);
564
                Command command = new ModifyRowCommand(this, calculatedIndex, pos, row,
565
                                sourceType);
566
                command.setDescription(descrip);
567
                if (complex) {
568
                        commands.add(command);
569
                } else {
570
                        cr.pushCommand(command);
571
                }
572

    
573
                return pos;
574
        }
575

    
576
        /**
577
         * DOCUMENT ME!
578
         */
579
        public void compact() {
580
                expansionFile.compact(relations);
581
        }
582

    
583
        /**
584
         * DOCUMENT ME!
585
         */
586
        public void startComplexRow() {
587
                complex = true;
588
                commands = new CommandCollection();
589
        }
590

    
591
        /**
592
         * DOCUMENT ME!
593
         *
594
         * @throws IOException
595
         *             DOCUMENT ME!
596
         * @throws DriverIOException
597
         *             DOCUMENT ME!
598
         */
599
        public void endComplexRow(String description) {
600
                commands.setDescription(description);
601
                cr.pushCommand(commands);
602
                complex = false;
603
                for (int j = 0; j < editionListeners.size(); j++) {
604
                        for (int i = 0; i < fieldEvents.size(); i++) {
605
                                IEditionListener listener = (IEditionListener) editionListeners
606
                                        .get(j);
607
                                listener.afterFieldEditEvent((AfterFieldEditEvent)fieldEvents.get(i));
608
                        }
609
                        for (int i = 0; i < rowEvents.size(); i++) {
610
                                IEditionListener listener = (IEditionListener) editionListeners
611
                                                .get(j);
612
                                listener.afterRowEditEvent(null,(AfterRowEditEvent)rowEvents.get(i));
613
                        }
614
                }
615
                fieldEvents.clear();
616
                rowEvents.clear();
617
        }
618

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

    
639
                if (previousExpansionFileIndex == -1) {
640
                        DefaultRowEdited edRow = null;
641
                        try {
642
                                edRow = new DefaultRowEdited(new DefaultRow(ods
643
                                                        .getRow(geometryIndex)),
644
                                                        IRowEdited.STATUS_ORIGINAL, geometryIndex);
645
                        } catch (ReadDriverException e) {
646
                                throw new EditionCommandException(writer.getName(),e);
647
                        }
648
                        boolean cancel=true;
649
                        try {
650
                                cancel = fireBeforeModifyRow(edRow, geometryIndex,
651
                                                sourceType);
652
                        } catch (ReadDriverException e) {
653
                                throw new EditionCommandException(writer.getName(),e);
654
                        }
655
                        if (cancel)
656
                                return;
657
                        // Se elimina de las relaciones y del fichero de expansi?n
658
                        relations.remove(new Integer(geometryIndex));
659
                        expansionFile.deleteLastRow();
660
                } else {
661
                        boolean cancel=true;
662
                        try {
663
                                cancel = fireBeforeModifyRow(expansionFile
664
                                                .getRow(previousExpansionFileIndex), geometryIndex,
665
                                                sourceType);
666
                        } catch (ExpansionFileReadException e) {
667
                                throw new EditionCommandException(writer.getName(),e);
668
                        } catch (ReadDriverException e) {
669
                                throw new EditionCommandException(writer.getName(),e);
670
                        }
671
                        if (cancel)
672
                                return;
673
                        // Se actualiza la relaci?n de ?ndices
674
                        relations.put(new Integer(geometryIndex), new Integer(
675
                                        previousExpansionFileIndex));
676
                }
677
                //fireAfterModifyRow(geometryIndex, sourceType);
678
        }
679

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

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

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

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

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

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

    
784
                calculatedIndex = (int) ods.getRowCount() + numAdd;
785

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

    
795
        /**
796
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
797
         * en el fichero original
798
         *
799
         * @param index
800
         *            DOCUMENT ME!
801
         */
802
        public void undoRemoveRow(int index, int sourceType) throws EditionCommandException {
803
                delRows.set(index, false);
804
                String fid;
805
                try {
806
                        fid = getRow(index).getID();
807

    
808
                boolean cancel = fireBeforeRowAdded(sourceType,fid);
809
                if (cancel){
810
                        delRows.set(index,true);
811
                        return;
812
                }
813
                } catch (ExpansionFileReadException e) {
814
                        throw new EditionCommandException(getOriginalDriver().getName(),e);
815
                } catch (ReadDriverException e) {
816
                        throw new EditionCommandException(getOriginalDriver().getName(),e);
817
                }
818
                fireAfterRowAdded(null,index, sourceType);
819
        }
820

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

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

    
858
                                try {
859

    
860
                                        ds = new SelectableDataSource(LayerFactory
861
                                                        .getDataSourceFactory().createRandomDataSource(
862
                                                                        name, DataSourceFactory.AUTOMATIC_OPENING));
863
                                        ds.start();
864
                                        ds.setSelectionSupport(ods.getSelectionSupport());
865

    
866
                                } catch (NoSuchTableException e) {
867
                                        throw new RuntimeException(e);
868
                                } catch (DriverLoadException e) {
869
                                        throw new ReadDriverException(name,e);
870
                                }
871
                        }
872

    
873
                        return ds;
874
                }
875
                return ods;
876
        }
877

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

    
887

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

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

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

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

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

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

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

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

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

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

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

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

    
1037

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

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

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

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

    
1105
                /*
1106
                 * (non-Javadoc)
1107
                 *
1108
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1109
                 */
1110
                public long getRowCount() throws ReadDriverException {
1111
                        return (int) (ods.getRowCount() + numAdd)
1112
                                        - delRows.cardinality();// -
1113
                        // expansionFile.getInvalidRows().cardinality();
1114
                }
1115

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

    
1133
//                        return ods.getFieldType(i);
1134
                }
1135

    
1136
                public int getFieldWidth(int fieldId) throws ReadDriverException {
1137
//                        int i=0;
1138
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1139
//                                InternalField fld = (InternalField) iter.next();
1140
////                                if (fld.getFieldIndex() == i)
1141
////                                        return fld.getFieldDesc().getFieldLength();
1142
//                                if (i == fieldId)
1143
//                                        return fld.getFieldDesc().getFieldLength();
1144
//                                i++;
1145
//
1146
//                        }
1147
//
1148
//                        return ods.getFieldWidth(i);
1149
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1150
                        return aux.getFieldLength();
1151

    
1152
                }
1153

    
1154
                public void reload() throws ReloadDriverException {
1155
                        ods.reload();
1156

    
1157
                }
1158
        }
1159

    
1160
        public CommandRecord getCommandRecord() {
1161
                return cr;
1162
        }
1163

    
1164
        protected void fireAfterRemoveRow(int index, int sourceType) {
1165
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1166
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1167
                if (complex){
1168
                        rowEvents.add(event);
1169
                        return;
1170
                }
1171
                for (int i = 0; i < editionListeners.size(); i++) {
1172
                        IEditionListener listener = (IEditionListener) editionListeners
1173
                                        .get(i);
1174
                        listener.afterRowEditEvent(null, event);
1175
                }
1176

    
1177
        }
1178

    
1179
        protected boolean fireBeforeRemoveRow(int index, int sourceType) throws ReadDriverException {
1180
                Cancel cancel = new Cancel();
1181
                String fid=null;
1182
                IRow row=null;
1183
                try {
1184
                        row=getRow(getInversedIndex(index));
1185
                        fid = row.getID();
1186
                } catch (ExpansionFileReadException e) {
1187
                        throw new ReadDriverException(getOriginalDriver().getName(),e);
1188
                }
1189
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, fid,
1190
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1191
                for (int i = 0; i < editionListeners.size(); i++) {
1192
                        IEditionListener listener = (IEditionListener) editionListeners
1193
                                        .get(i);
1194
                        listener.beforeRowEditEvent(row, event);
1195
                        if (cancel.isCanceled())
1196
                                return true;
1197
                }
1198
                return false;
1199
        }
1200

    
1201
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1202
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1203
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1204
                if (complex){
1205
                        rowEvents.add(event);
1206
                        return;
1207
                }
1208
                for (int i = 0; i < editionListeners.size(); i++) {
1209
                        IEditionListener listener = (IEditionListener) editionListeners
1210
                                        .get(i);
1211
                        listener.afterRowEditEvent(feat, event);
1212
                }
1213
        }
1214

    
1215
        protected void fireAfterFieldAdded(FieldDescription field) {
1216
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1217
                                EditionEvent.CHANGE_TYPE_ADD);
1218
                if (complex) {
1219
                        fieldEvents.add(event);
1220
                        return;
1221
                }
1222
                for (int i = 0; i < editionListeners.size(); i++) {
1223
                        IEditionListener listener = (IEditionListener) editionListeners
1224
                                        .get(i);
1225
                        listener.afterFieldEditEvent(event);
1226

    
1227
                }
1228
        }
1229

    
1230
        protected void fireAfterFieldRemoved(FieldDescription field) {
1231
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1232
                                EditionEvent.CHANGE_TYPE_DELETE);
1233
                if (complex) {
1234
                        fieldEvents.add(event);
1235
                        return;
1236
                }
1237
                for (int i = 0; i < editionListeners.size(); i++) {
1238
                        IEditionListener listener = (IEditionListener) editionListeners
1239
                                        .get(i);
1240
                        listener.afterFieldEditEvent(event);
1241
                }
1242
        }
1243

    
1244
        protected void fireAfterFieldModified(FieldDescription field) {
1245
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1246
                                EditionEvent.CHANGE_TYPE_MODIFY);
1247
                if (complex) {
1248
                        fieldEvents.add(event);
1249
                        return;
1250
                }
1251
                for (int i = 0; i < editionListeners.size(); i++) {
1252
                        IEditionListener listener = (IEditionListener) editionListeners
1253
                                        .get(i);
1254
                        listener.afterFieldEditEvent(event);
1255
                }
1256
        }
1257

    
1258

    
1259
        protected boolean fireBeforeRowAdded(int sourceType,String newFID) throws ReadDriverException{
1260
                Cancel cancel = new Cancel();
1261
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, newFID,
1262
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1263
                for (int i = 0; i < editionListeners.size(); i++) {
1264
                        IEditionListener listener = (IEditionListener) editionListeners
1265
                                        .get(i);
1266
                        listener.beforeRowEditEvent(null, event);
1267
                        if (cancel.isCanceled())
1268
                                return true;
1269
                }
1270
                return false;
1271
        }
1272

    
1273
        protected boolean fireBeforeFieldAdded(FieldDescription field) {
1274
                Cancel cancel = new Cancel();
1275
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1276
                EditionEvent.CHANGE_TYPE_ADD, cancel);
1277
                for (int i = 0; i < editionListeners.size(); i++) {
1278
                        IEditionListener listener = (IEditionListener) editionListeners
1279
                        .get(i);
1280
                        listener.beforeFieldEditEvent(event);
1281
                        if (cancel.isCanceled())
1282
                                return true;
1283
                }
1284
                return false;
1285
        }
1286

    
1287
        protected boolean fireBeforeRemoveField(FieldDescription field){
1288
                Cancel cancel = new Cancel();
1289
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1290
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1291
                for (int i = 0; i < editionListeners.size(); i++) {
1292
                        IEditionListener listener = (IEditionListener) editionListeners
1293
                        .get(i);
1294
                        listener.beforeFieldEditEvent(event);
1295
                        if (cancel.isCanceled())
1296
                                return true;
1297
                }
1298
                return false;
1299
        }
1300

    
1301

    
1302
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) throws ReadDriverException {
1303
                Cancel cancel = new Cancel();
1304
                String fid=null;
1305
                try {
1306
                        fid = getRow(getInversedIndex(index)).getID();
1307
                } catch (ExpansionFileReadException e) {
1308
                        throw new ReadDriverException(getOriginalDriver().getName(),e);
1309
                }
1310
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, fid,
1311
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1312
                for (int i = 0; i < editionListeners.size(); i++) {
1313
                        IEditionListener listener = (IEditionListener) editionListeners
1314
                                        .get(i);
1315
                        listener.beforeRowEditEvent(feat, event);
1316
                        if (cancel.isCanceled())
1317
                                return true;
1318
                }
1319
                return false;
1320
        }
1321

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

    
1335
        }
1336

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

    
1346
        }
1347

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

    
1357
        }
1358

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

    
1368
        }
1369

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

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

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

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

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

    
1406

    
1407
        }
1408

    
1409
        public void validateRow(IRow row,int sourceType) throws ValidateRowException  {
1410
                for (int i = 0; i < rules.size(); i++) {
1411
                        IRule rule = (IRule) rules.get(i);
1412
                        boolean bAux = rule.validate(row,sourceType);
1413
                        if (bAux == false) {
1414
                                ValidateRowException ex = new ValidateRowException(writer.getName(),null);
1415
                                // TODO: Lanzar una RuleException con datos como el registro
1416
                                // que no cumple, la regla que no lo ha cumplido, etc.
1417
                                throw ex;
1418
                        }
1419
                }
1420
        }
1421

    
1422
        public ArrayList getRules() {
1423
                return rules;
1424
        }
1425

    
1426
        public void setRules(ArrayList rules) {
1427
                this.rules = rules;
1428
        }
1429

    
1430
        private void clean() throws ReadDriverException {
1431
                try {
1432
                        expansionFile.close();
1433
                } catch (CloseExpansionFileException e) {
1434
                        throw new ReadDriverException(getRecordset().getDriver().getName(),e);
1435
                }
1436
                relations.clear();
1437
                numAdd = 0;
1438
                delRows.clear();
1439
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1440
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1441
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1442
                // reload completo.
1443
                initalizeFields(ods);
1444

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

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

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

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

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

    
1518
        public void removeField(String fieldName) throws WriteDriverException, ReadDriverException {
1519

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

    
1532
        }
1533

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

    
1543
                return null;
1544
        }
1545

    
1546
        public void undoRemoveField(InternalField field) throws EditionCommandException {
1547
                // field.setDeleted(false);
1548
//                field.setFieldIndex(actualFields.size());
1549
                actualFields.put(field.getFieldId(), field);
1550
                try {
1551
                        fieldsChanged();
1552
                } catch (ReadDriverException e) {
1553
                        throw new EditionCommandException(writer.getName(),e);
1554
                }
1555
                fireAfterFieldAdded(field.getFieldDesc());
1556
        }
1557

    
1558
        public void doRemoveField(InternalField field) throws ReadDriverException {
1559
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1560
                if (cancel) return;
1561
                actualFields.remove(field.getFieldId());
1562
                fieldsChanged();
1563
                fireAfterFieldRemoved(field.getFieldDesc());
1564
        }
1565

    
1566
        public void renameField(String antName, String newName) throws ReadDriverException{
1567

    
1568
                InternalField fld = findFieldByName(antName);
1569
                Command command = new RenameFieldCommand(this, fld, newName);
1570
                if (complex) {
1571
                        commands.add(command);
1572
                } else {
1573
                        cr.pushCommand(command);
1574
                }
1575
                doRenameField(fld, newName);
1576

    
1577
        }
1578

    
1579
        public void undoRenameField(InternalField field, String antName) throws EditionCommandException{
1580
                field.getFieldDesc().setFieldAlias(antName);
1581
                try {
1582
                        fieldsChanged();
1583
                } catch (ReadDriverException e) {
1584
                        throw new EditionCommandException(writer.getName(),e);
1585
                }
1586
                fireAfterFieldModified(field.getFieldDesc());
1587

    
1588
        }
1589

    
1590
        public void doRenameField(InternalField field, String newName) throws ReadDriverException{
1591
                field.getFieldDesc().setFieldAlias(newName);
1592
                fieldsChanged();
1593
                fireAfterFieldModified(field.getFieldDesc());
1594

    
1595
        }
1596

    
1597

    
1598
        public void addField(FieldDescription field) throws ReadDriverException {
1599

    
1600
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1601
                Command command = new AddFieldCommand(this, fld);
1602
                if (complex) {
1603
                        commands.add(command);
1604
                } else {
1605
                        cr.pushCommand(command);
1606
                }
1607
                listFields.add(fld);
1608
                doAddField(fld);
1609

    
1610
        }
1611

    
1612
        public void undoAddField(InternalField field) throws EditionCommandException  {
1613
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1614
                if (cancel)
1615
                        return;
1616

    
1617
                // field.setDeleted(true);
1618
                actualFields.remove(field.getFieldId());
1619
                try {
1620
                        fieldsChanged();
1621
                } catch (ReadDriverException e) {
1622
                        throw new EditionCommandException(writer.getName(),e);
1623
                }
1624
                fireAfterFieldRemoved(field.getFieldDesc());
1625

    
1626
        }
1627

    
1628
        public int doAddField(InternalField field) throws ReadDriverException {
1629
                boolean cancel;
1630
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1631
                if (cancel)
1632
                        return -1;
1633

    
1634
                // field.setDeleted(false);
1635
//                field.setFieldIndex(actualFields.size());
1636
                actualFields.put(field.getFieldId(), field);
1637
                fieldsChanged();
1638
                fireAfterFieldAdded(field.getFieldDesc());
1639
//                return field.getFieldIndex();
1640
                return field.getFieldId().intValue();
1641
        }
1642

    
1643
        public Driver getOriginalDriver()
1644
        {
1645
                return ods.getDriver();
1646
        }
1647

    
1648
        /**
1649
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1650
         * to be created next time it is needed
1651
         */
1652
        public void cleanSelectableDatasource() {
1653
                ds = null;
1654
        }
1655

    
1656
        public FieldDescription[] getFieldsDescription() {
1657
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1658
        }
1659
        public String getNewFID() {
1660
                return "fid-" + (new UID()).toString();
1661
        }
1662

    
1663
//        private InternalField getInternalFieldByIndex(int fieldId)
1664
//        {
1665
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1666
//                        InternalField fld = (InternalField) iter.next();
1667
//                        if (fld.getFieldIndex() == fieldId)
1668
//                                return fld;
1669
//                }
1670
//                return null;
1671
//        }
1672

    
1673
}