Statistics
| Revision:

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

History | View | Annotate | Download (49.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.driver.exceptions.ReadDriverException;
13
import com.hardcode.gdbms.driver.exceptions.ReloadDriverException;
14
import com.hardcode.gdbms.driver.exceptions.WriteDriverException;
15
import com.hardcode.gdbms.engine.data.DataSourceFactory;
16
import com.hardcode.gdbms.engine.data.NoSuchTableException;
17
import com.hardcode.gdbms.engine.data.driver.AlphanumericDBDriver;
18
import com.hardcode.gdbms.engine.data.driver.DriverException;
19
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
20
import com.hardcode.gdbms.engine.data.edition.DataWare;
21
import com.hardcode.gdbms.engine.values.Value;
22
import com.iver.cit.gvsig.exceptions.commands.EditionCommandException;
23
import com.iver.cit.gvsig.exceptions.expansionfile.CloseExpansionFileException;
24
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
25
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileWriteException;
26
import com.iver.cit.gvsig.exceptions.layers.CancelEditingLayerException;
27
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
28
import com.iver.cit.gvsig.exceptions.layers.StopEditionLayerException;
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 (ExpansionFileReadException e) {
400
                        throw new StopWriterVisitorException(writer.getName(),e);
401
                } catch (StartWriterVisitorException e) {
402
                        throw new StopWriterVisitorException(writer.getName(),e);
403
                } catch (VisitorException e) {
404
                        throw new StopWriterVisitorException(writer.getName(),e);
405
                }
406

    
407
        }
408

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

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

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

    
462

    
463

    
464
        }
465

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

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

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

    
501
                return calculatedIndex;
502
        }
503

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

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

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

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

    
554
        }
555

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

    
575
                return pos;
576
        }
577

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

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

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

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

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

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

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

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

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

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

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

    
779
                calculatedIndex = (int) ods.getRowCount() + numAdd;
780

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

    
790
        /**
791
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
792
         * en el fichero original
793
         *
794
         * @param index
795
         *            DOCUMENT ME!
796
         */
797
        public void undoRemoveRow(int index, int sourceType) throws EditionCommandException {
798
                boolean cancel;
799
                try {
800
                        cancel = fireBeforeRowAdded(sourceType);
801
                } catch (ReadDriverException e) {
802
                        throw new EditionCommandException(writer.getName(),e);
803
                }
804
                if (cancel)
805
                        return;
806
                delRows.set(index, false);
807
                fireAfterRowAdded(null,index, sourceType);
808
        }
809

    
810
        /**
811
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
812
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar la
813
         * relaci?n del mapa de relaciones
814
         *
815
         * @param index
816
         *            ?ndice de la geometr?a que se a?adi?
817
         * @throws DriverIOException
818
         * @throws IOException
819
         */
820
        public void undoAddRow(int calculatedIndex, int sourceType)
821
                        throws EditionCommandException {
822
                boolean cancel = fireBeforeRemoveRow(calculatedIndex, sourceType);
823
                if (cancel)
824
                        return;
825
                expansionFile.deleteLastRow();
826
                relations.remove(new Integer(calculatedIndex));
827
                numAdd--;
828
                fireAfterRemoveRow(calculatedIndex, sourceType);
829
        }
830

    
831
        /*
832
         * (non-Javadoc)
833
         *
834
         * @see com.iver.cit.gvsig.fmap.layers.VectorialAdapter#getRecordset()
835
         */
836
        public SelectableDataSource getRecordset() throws ReadDriverException  {
837
                if (isEditing) {
838
                        if (ds == null) {
839
                                String name = LayerFactory.getDataSourceFactory()
840
                                                .addDataSource(editingDriver);
841

    
842
                                try {
843

    
844
                                        ds = new SelectableDataSource(LayerFactory
845
                                                        .getDataSourceFactory().createRandomDataSource(
846
                                                                        name, DataSourceFactory.MANUAL_OPENING));
847
                                        ds.start();
848
                                        ds.setSelectionSupport(ods.getSelectionSupport());
849

    
850
                                } catch (NoSuchTableException e) {
851
                                        throw new RuntimeException(e);
852
                                } catch (DriverLoadException e) {
853
                                        throw new ReadDriverException(name,e);
854
                                }
855
                        }
856

    
857
                        return ds;
858
                }
859
                return ods;
860
        }
861

    
862
        /**
863
         * Return always the original recordset (even when is editing,
864
         * nor the getRecorset() method)
865
         *
866
         * */
867
        public SelectableDataSource getOriginalRecordset(){
868
                return ods;
869
        }
870

    
871

    
872
        /**
873
         * DOCUMENT ME!
874
         *
875
         * @return
876
         * @throws ReadDriverException
877
         */
878
        public FBitSet getSelection() throws ReadDriverException {
879
                /*
880
                 * try { return getRecordset().getSelection(); } catch
881
                 * (DriverLoadException e) { // TODO Auto-generated catch block
882
                 * e.printStackTrace(); } return null;
883
                 */
884
                return getRecordset().getSelection();
885
        }
886

    
887
        public void setSelection(FBitSet selection) throws ReadDriverException {
888
                /*
889
                 * try { getRecordset().setSelection(selection); } catch
890
                 * (DriverLoadException e) { // TODO Auto-generated catch block
891
                 * e.printStackTrace(); }
892
                 */
893
                getRecordset().setSelection(selection);
894
        }
895

    
896
        /**
897
         * DOCUMENT ME!
898
         *
899
         * @return DOCUMENT ME!
900
         */
901
        public boolean isEditing() {
902
                return isEditing;
903
        }
904

    
905
        public int getInversedIndex(long rowIndex) {
906
                int intervalNotDeleted = 0;
907
                int antDeleted = -1;
908
                int idPedido = (int) rowIndex;
909
                int numNotDeleted = 0;
910
                int numBorradosAnt = 0;
911

    
912
                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
913
                                .nextSetBit(i + 1)) {
914
                        intervalNotDeleted = i - antDeleted - 1;
915
                        numNotDeleted += intervalNotDeleted;
916
                        if (i > idPedido) {
917
                                numNotDeleted = numNotDeleted + (i - idPedido);
918
                                break;
919
                        }
920
                        numBorradosAnt++;
921
                        antDeleted = i;
922
                }
923
                numNotDeleted = idPedido - numBorradosAnt;
924
                // System.out.println("Piden Viejo : "+ rowIndex + " y devuelvo como
925
                // nuevo " + (numNotDeleted));
926
                return numNotDeleted;
927
        }
928

    
929
        /**
930
         * DOCUMENT ME!
931
         *
932
         * @param rowIndex
933
         *            DOCUMENT ME!
934
         *
935
         * @return DOCUMENT ME!
936
         */
937
        public int getCalculatedIndex(long rowIndex) {
938
                int numNotDeleted = 0;
939
                int intervalNotDeleted = 0;
940
                int antDeleted = -1;
941
                int calculatedIndex;
942
                int idPedido = (int) rowIndex;
943
                int numBorradosAnt = 0;
944

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

    
961
        /**
962
         * DOCUMENT ME!
963
         *
964
         * @author Vicente Caballero Navarro
965
         */
966
        private class myObjectDriver implements ObjectDriver {
967
                /*
968
                 * (non-Javadoc)
969
                 *
970
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
971
                 */
972
                public int[] getPrimaryKeys() throws ReadDriverException {
973
                        return ods.getPrimaryKeys();
974
                        // int[] pk=new int[1];
975
                        /*
976
                         * for (int i=0;i<getRowCount();i++){ pk[i]=i; }
977
                         */
978
                        // pk[0]=1;
979
                        // return pk;
980
                }
981

    
982
                /*
983
                 * (non-Javadoc)
984
                 *
985
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
986
                 */
987
                public void write(DataWare dataWare) throws ReadDriverException, WriteDriverException {
988
                        DataWare dataWareOrig = ods
989
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
990
                        dataWareOrig.commitTrans();
991
                }
992

    
993
                /*
994
                 * (non-Javadoc)
995
                 *
996
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
997
                 */
998
                public void setDataSourceFactory(DataSourceFactory dsf) {
999
                        ods.setDataSourceFactory(dsf);
1000
                }
1001

    
1002
                /*
1003
                 * (non-Javadoc)
1004
                 *
1005
                 * @see com.hardcode.driverManager.Driver#getName()
1006
                 */
1007
                public String getName() {
1008
                        return ods.getName();
1009
                }
1010

    
1011
                /*
1012
                 * (non-Javadoc)
1013
                 *
1014
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
1015
                 *      int)
1016
                 */
1017
                public Value getFieldValue(long rowIndex, int fieldId) throws ReadDriverException {
1018
                        // Si no est? en el fichero de expansi?n
1019
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
1020

    
1021

    
1022
                        try {
1023
                                IRow row = getRow((int)rowIndex);
1024
                                return row.getAttribute(fieldId);
1025
//                                if (!relations.containsKey(integer)) {
1026
//                                        return ods.getFieldValue(rowIndex, fieldId);
1027
//                                } else {
1028
//                                        int num = ((Integer) relations.get(integer)).intValue();
1029
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
1030
//                                                        .getRow(num);
1031
//
1032
//                                        if (feat == null) {
1033
//                                                return null;
1034
//                                        }
1035
//
1036
//                                        return feat.getAttribute(fieldId);
1037
//                                }
1038
//                        } catch (DriverException e) {
1039
//                                e.printStackTrace();
1040
//                                throw new DriverException(e);
1041
                        } catch (ExpansionFileReadException e) {
1042
                                throw new ReadDriverException(getRecordset().getDriver().getName(),e);
1043
                        }
1044

    
1045
                        /**
1046
                         * try { if (!relations.containsKey(integer)) { // Si ha sido
1047
                         * eliminada if (delRows.get(integer.intValue())) { return null; }
1048
                         * else { return ods.getFieldValue(rowIndex, fieldId); }} else { int
1049
                         * num = ((Integer) relations.get(integer)).intValue();
1050
                         * DefaultRowEdited feat = (DefaultRowEdited)
1051
                         * expansionFile.getRow(num); if (feat==null)return null; return
1052
                         * feat.getAttribute(fieldId); }} catch (DriverException e) {
1053
                         * e.printStackTrace(); throw new DriverException(e); } catch
1054
                         * (IOException e) { e.printStackTrace(); throw new
1055
                         * DriverException(e); }
1056
                         */
1057
                }
1058

    
1059
                /*
1060
                 * (non-Javadoc)
1061
                 *
1062
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1063
                 */
1064
                public int getFieldCount() throws ReadDriverException {
1065
                        return fastAccessFields.size();
1066
                }
1067

    
1068
                /*
1069
                 * (non-Javadoc)
1070
                 *
1071
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
1072
                 */
1073
                public String getFieldName(int fieldId) throws ReadDriverException {
1074
//                        int i=0;
1075
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1076
//                                InternalField fld = (InternalField) iter.next();
1077
//                                if (i == fieldId)
1078
//                                        return fld.getFieldDesc().getFieldAlias();
1079
//                                i++;
1080
//
1081
//                        }
1082
//                        throw new DriverException("FieldId " + fieldId + " not found ");
1083
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1084
                        return aux.getFieldAlias();
1085
                        // return null;
1086
                        // return ods.getFieldName(fieldId);
1087
                }
1088

    
1089
                /*
1090
                 * (non-Javadoc)
1091
                 *
1092
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1093
                 */
1094
                public long getRowCount() throws ReadDriverException {
1095
                        return (int) (ods.getRowCount() + numAdd)
1096
                                        - delRows.cardinality();// -
1097
                        // expansionFile.getInvalidRows().cardinality();
1098
                }
1099

    
1100
                /*
1101
                 * (non-Javadoc)
1102
                 *
1103
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
1104
                 */
1105
                public int getFieldType(int fieldId) throws ReadDriverException {
1106
//                        int i=0;
1107
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1108
//                                InternalField fld = (InternalField) iter.next();
1109
//                                if (i == fieldId)
1110
//                                        return fld.getFieldDesc().getFieldType();
1111
//                                i++;
1112
//
1113
//                        }
1114
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1115
                        return aux.getFieldType();
1116

    
1117
//                        return ods.getFieldType(i);
1118
                }
1119

    
1120
                public int getFieldWidth(int fieldId) throws ReadDriverException {
1121
//                        int i=0;
1122
//                        for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1123
//                                InternalField fld = (InternalField) iter.next();
1124
////                                if (fld.getFieldIndex() == i)
1125
////                                        return fld.getFieldDesc().getFieldLength();
1126
//                                if (i == fieldId)
1127
//                                        return fld.getFieldDesc().getFieldLength();
1128
//                                i++;
1129
//
1130
//                        }
1131
//
1132
//                        return ods.getFieldWidth(i);
1133
                        FieldDescription aux = (FieldDescription) fastAccessFields.get(fieldId);
1134
                        return aux.getFieldLength();
1135

    
1136
                }
1137

    
1138
                public void reload() throws ReloadDriverException {
1139
                        ods.reload();
1140

    
1141
                }
1142
        }
1143

    
1144
        public CommandRecord getCommandRecord() {
1145
                return cr;
1146
        }
1147

    
1148
        protected void fireAfterRemoveRow(int index, int sourceType) {
1149
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1150
                                EditionEvent.CHANGE_TYPE_DELETE, sourceType);
1151
                if (complex){
1152
                        rowEvents.add(event);
1153
                        return;
1154
                }
1155
                for (int i = 0; i < editionListeners.size(); i++) {
1156
                        IEditionListener listener = (IEditionListener) editionListeners
1157
                                        .get(i);
1158
                        listener.afterRowEditEvent(null, event);
1159
                }
1160

    
1161
        }
1162

    
1163
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1164
                Cancel cancel = new Cancel();
1165
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, index,
1166
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1167
                for (int i = 0; i < editionListeners.size(); i++) {
1168
                        IEditionListener listener = (IEditionListener) editionListeners
1169
                                        .get(i);
1170
                        listener.beforeRowEditEvent(null, event);
1171
                        if (cancel.isCanceled())
1172
                                return true;
1173
                }
1174
                return false;
1175
        }
1176

    
1177
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1178
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1179
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1180
                if (complex){
1181
                        rowEvents.add(event);
1182
                        return;
1183
                }
1184
                for (int i = 0; i < editionListeners.size(); i++) {
1185
                        IEditionListener listener = (IEditionListener) editionListeners
1186
                                        .get(i);
1187
                        listener.afterRowEditEvent(feat, event);
1188
                }
1189
        }
1190

    
1191
        protected void fireAfterFieldAdded(FieldDescription field) {
1192
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1193
                                EditionEvent.CHANGE_TYPE_ADD);
1194
                if (complex) {
1195
                        fieldEvents.add(event);
1196
                        return;
1197
                }
1198
                for (int i = 0; i < editionListeners.size(); i++) {
1199
                        IEditionListener listener = (IEditionListener) editionListeners
1200
                                        .get(i);
1201
                        listener.afterFieldEditEvent(event);
1202

    
1203
                }
1204
        }
1205

    
1206
        protected void fireAfterFieldRemoved(FieldDescription field) {
1207
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1208
                                EditionEvent.CHANGE_TYPE_DELETE);
1209
                if (complex) {
1210
                        fieldEvents.add(event);
1211
                        return;
1212
                }
1213
                for (int i = 0; i < editionListeners.size(); i++) {
1214
                        IEditionListener listener = (IEditionListener) editionListeners
1215
                                        .get(i);
1216
                        listener.afterFieldEditEvent(event);
1217
                }
1218
        }
1219

    
1220
        protected void fireAfterFieldModified(FieldDescription field) {
1221
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1222
                                EditionEvent.CHANGE_TYPE_MODIFY);
1223
                if (complex) {
1224
                        fieldEvents.add(event);
1225
                        return;
1226
                }
1227
                for (int i = 0; i < editionListeners.size(); i++) {
1228
                        IEditionListener listener = (IEditionListener) editionListeners
1229
                                        .get(i);
1230
                        listener.afterFieldEditEvent(event);
1231
                }
1232
        }
1233

    
1234

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

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

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

    
1277

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

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

    
1305
        }
1306

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

    
1316
        }
1317

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

    
1327
        }
1328

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

    
1338
        }
1339

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

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

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

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

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

    
1376

    
1377
        }
1378

    
1379
        public void validateRow(IRow row,int sourceType) throws ValidateRowException  {
1380
                for (int i = 0; i < rules.size(); i++) {
1381
                        IRule rule = (IRule) rules.get(i);
1382
                        boolean bAux = rule.validate(row,sourceType);
1383
                        if (bAux == false) {
1384
                                ValidateRowException ex = new ValidateRowException(writer.getName(),null);
1385
                                // TODO: Lanzar una RuleException con datos como el registro
1386
                                // que no cumple, la regla que no lo ha cumplido, etc.
1387
                                throw ex;
1388
                        }
1389
                }
1390
        }
1391

    
1392
        public ArrayList getRules() {
1393
                return rules;
1394
        }
1395

    
1396
        public void setRules(ArrayList rules) {
1397
                this.rules = rules;
1398
        }
1399

    
1400
        private void clean() throws ReadDriverException {
1401
                try {
1402
                        expansionFile.close();
1403
                } catch (CloseExpansionFileException e) {
1404
                        throw new ReadDriverException(getRecordset().getDriver().getName(),e);
1405
                }
1406
                relations.clear();
1407
                numAdd = 0;
1408
                delRows.clear();
1409
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1410
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1411
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1412
                // reload completo.
1413
                initalizeFields(ods);
1414

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

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

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

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

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

    
1488
        public void removeField(String fieldName) throws WriteDriverException, ReadDriverException {
1489

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

    
1502
        }
1503

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

    
1513
                return null;
1514
        }
1515

    
1516
        public void undoRemoveField(InternalField field) throws EditionCommandException {
1517
                // field.setDeleted(false);
1518
//                field.setFieldIndex(actualFields.size());
1519
                actualFields.put(field.getFieldId(), field);
1520
                try {
1521
                        fieldsChanged();
1522
                } catch (ReadDriverException e) {
1523
                        throw new EditionCommandException(writer.getName(),e);
1524
                }
1525
                fireAfterFieldAdded(field.getFieldDesc());
1526
        }
1527

    
1528
        public void doRemoveField(InternalField field) throws ReadDriverException {
1529
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1530
                if (cancel) return;
1531
                actualFields.remove(field.getFieldId());
1532
                fieldsChanged();
1533
                fireAfterFieldRemoved(field.getFieldDesc());
1534
        }
1535

    
1536
        public void renameField(String antName, String newName) throws ReadDriverException{
1537

    
1538
                InternalField fld = findFieldByName(antName);
1539
                Command command = new RenameFieldCommand(this, fld, newName);
1540
                if (complex) {
1541
                        commands.add(command);
1542
                } else {
1543
                        cr.pushCommand(command);
1544
                }
1545
                doRenameField(fld, newName);
1546

    
1547
        }
1548

    
1549
        public void undoRenameField(InternalField field, String antName) throws EditionCommandException{
1550
                field.getFieldDesc().setFieldAlias(antName);
1551
                try {
1552
                        fieldsChanged();
1553
                } catch (ReadDriverException e) {
1554
                        throw new EditionCommandException(writer.getName(),e);
1555
                }
1556
                fireAfterFieldModified(field.getFieldDesc());
1557

    
1558
        }
1559

    
1560
        public void doRenameField(InternalField field, String newName) throws ReadDriverException{
1561
                field.getFieldDesc().setFieldAlias(newName);
1562
                fieldsChanged();
1563
                fireAfterFieldModified(field.getFieldDesc());
1564

    
1565
        }
1566

    
1567

    
1568
        public void addField(FieldDescription field) throws ReadDriverException {
1569

    
1570
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1571
                Command command = new AddFieldCommand(this, fld);
1572
                if (complex) {
1573
                        commands.add(command);
1574
                } else {
1575
                        cr.pushCommand(command);
1576
                }
1577
                listFields.add(fld);
1578
                doAddField(fld);
1579

    
1580
        }
1581

    
1582
        public void undoAddField(InternalField field) throws EditionCommandException  {
1583
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1584
                if (cancel)
1585
                        return;
1586

    
1587
                // field.setDeleted(true);
1588
                actualFields.remove(field.getFieldId());
1589
                try {
1590
                        fieldsChanged();
1591
                } catch (ReadDriverException e) {
1592
                        throw new EditionCommandException(writer.getName(),e);
1593
                }
1594
                fireAfterFieldRemoved(field.getFieldDesc());
1595

    
1596
        }
1597

    
1598
        public int doAddField(InternalField field) throws ReadDriverException {
1599
                boolean cancel;
1600
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1601
                if (cancel)
1602
                        return -1;
1603

    
1604
                // field.setDeleted(false);
1605
//                field.setFieldIndex(actualFields.size());
1606
                actualFields.put(field.getFieldId(), field);
1607
                fieldsChanged();
1608
                fireAfterFieldAdded(field.getFieldDesc());
1609
//                return field.getFieldIndex();
1610
                return field.getFieldId().intValue();
1611
        }
1612

    
1613
        public Driver getOriginalDriver()
1614
        {
1615
                return ods.getDriver();
1616
        }
1617

    
1618
        /**
1619
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1620
         * to be created next time it is needed
1621
         */
1622
        public void cleanSelectableDatasource() {
1623
                ds = null;
1624
        }
1625

    
1626
        public FieldDescription[] getFieldsDescription() {
1627
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1628
        }
1629
        public int getNewIndex() throws ReadDriverException {
1630
                int index=(int)ods.getRowCount() + numAdd;
1631
                return index;
1632
        }
1633

    
1634
//        private InternalField getInternalFieldByIndex(int fieldId)
1635
//        {
1636
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1637
//                        InternalField fld = (InternalField) iter.next();
1638
//                        if (fld.getFieldIndex() == fieldId)
1639
//                                return fld;
1640
//                }
1641
//                return null;
1642
//        }
1643

    
1644
}