Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / EditableAdapter.java @ 35160

History | View | Annotate | Download (50.4 KB)

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

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

    
12
import javax.swing.SwingUtilities;
13

    
14
import org.apache.log4j.Logger;
15

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

    
63
/**
64
 * DOCUMENT ME!
65
 *
66
 * @author Vicente Caballero Navarro
67
 */
68
public class EditableAdapter implements IEditableSource, IWriteable {
69
        private static Logger logger = Logger.getLogger(EditableAdapter.class.getName());
70

    
71
        protected boolean isEditing = false;
72

    
73
        private SelectableDataSource ds = null;
74

    
75
        protected FBitSet delRows = new FBitSet();
76

    
77
        private CommandRecord cr;
78

    
79
        protected IWriter writer;
80

    
81
        /**
82
         * Flag que indica que hay que tomar las siguientes operaciones como una
83
         * operaci?n at?mica
84
         */
85
        private boolean complex = false;
86

    
87
        private CommandCollection commands = null;
88

    
89
        protected ArrayList listFields = new ArrayList();
90

    
91
        protected ArrayList listInternalFields = new ArrayList();
92

    
93
        protected boolean bFieldsHasBeenChanged = false;
94

    
95
        /**
96
         * La clave ser? el fieldId. Para buscar si un value de una row ha de ser
97
         * rellenado con defaultValue o con lo que venga del expansion file,
98
         * miraremos si existe en este hash. Si existe, usamos el value del
99
         * expansion file. Si no existe, usamos el defaultValue del campo busc?ndolo
100
         * en la lista internalFields. Por cierto, en listInternalFields NO se
101
         * borran campos. Solo se van a?adiendo nuevos actualFields.
102
         */
103
        protected TreeMap actualFields; // la clave ser? el fieldId.
104

    
105
        protected ArrayList fastAccessFields = new ArrayList();
106

    
107
        protected class MyFieldManager extends AbstractFieldManager {
108

    
109
                public boolean alterTable() throws WriteDriverException {
110
                        return getFieldManager().alterTable();
111
                }
112

    
113
                public void addField(FieldDescription fieldDesc) {
114
                        super.addField(fieldDesc);
115
                }
116

    
117
                public FieldDescription removeField(String fieldName) {
118
                        // TODO Auto-generated method stub
119
                        return super.removeField(fieldName);
120
                }
121

    
122
                public void renameField(String antName, String newName) {
123
                        // TODO Auto-generated method stub
124
                        super.renameField(antName, newName);
125
                }
126

    
127
        }
128

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

    
144
        /*
145
         * Fichero en el que se guardan las nuevas geometr?as, producto de adiciones
146
         * o de modificaciones
147
         */
148
        protected ExpansionFile expansionFile;
149

    
150
        protected int numAdd = 0;
151

    
152
        private ObjectDriver editingDriver = new myObjectDriver();
153

    
154
        private SelectableDataSource ods;
155

    
156
        private ArrayList editionListeners = new ArrayList();
157

    
158
        private ArrayList rules = new ArrayList();
159

    
160
        protected int actualIndexFields;
161

    
162
        protected boolean isFullExtentDirty = false;
163

    
164
        private ArrayList fieldEvents=new ArrayList();
165
        private ArrayList rowEvents=new ArrayList();
166

    
167
        /**
168
         * Crea un nuevo EditableAdapter.
169
         */
170
        public EditableAdapter() {
171
                expansionFile = new MemoryExpansionFile(this);
172
                cr = new MemoryCommandRecord();
173
        }
174

    
175
        /**
176
         * DOCUMENT ME!
177
         *
178
         * @param ds
179
         *            DOCUMENT ME!
180
         * @throws DriverException
181
         */
182
        public void setOriginalDataSource(SelectableDataSource ds) throws ReadDriverException {
183
                this.ods = ds;
184
                initalizeFields(ds);
185
                Driver drv = ods.getDriver();
186
                if (drv instanceof IWriteable) {
187
                        setWriter(((IWriteable) drv).getWriter());
188
                }
189

    
190

    
191
        }
192

    
193
        /**
194
         * @param ds
195
         * @throws ReadDriverException
196
         * @throws DriverException
197
         */
198
        private void initalizeFields(SelectableDataSource ds) throws ReadDriverException {
199
                FieldDescription[] fields = ds.getFieldsDescription();
200
                listInternalFields.clear();
201
                actualIndexFields = 0;
202
                actualFields = new TreeMap();
203
//                fastAccessFields = new ArrayList();
204
                for (int i=0; i < fields.length; i++)
205
                {
206
                        fields[i].setFieldAlias(fields[i].getFieldName());
207
                        InternalField field = new InternalField(fields[i], InternalField.ORIGINAL, new Integer(i));
208
                        listFields.add(field);
209
                        // field.setFieldIndex(i);
210
                        actualFields.put(field.getFieldId(), field);
211
//                        fastAccessFields.add(fields[i]);
212
                        System.out.println("INITIALIZEFIELDS: FIELD " + field.getFieldDesc().getFieldAlias());
213
                }
214
                        fieldsChanged();
215
                        bFieldsHasBeenChanged = false;
216
        }
217

    
218
        private TreeMap deepCloneInternalFields(TreeMap col)
219
        {
220
                TreeMap clonedFields = new TreeMap();
221
                for (Iterator iter = col.values().iterator(); iter.hasNext();) {
222
                        InternalField fld = (InternalField) iter.next();
223
                        InternalField clonedField = fld.cloneInternalField();
224
                        clonedFields.put(clonedField.getFieldId(), clonedField);
225
                }
226

    
227
                return clonedFields;
228
        }
229
        private void fieldsChanged() throws ReadDriverException {
230
                fastAccessFields= new ArrayList();
231
                int index = 0;
232
                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
233
                        InternalField fld = (InternalField) iter.next();
234
                        fastAccessFields.add(fld.getFieldDesc());
235
                        fld.setFieldIndex(index++);
236
                }
237

    
238
                listInternalFields.add(deepCloneInternalFields(actualFields));
239
                actualIndexFields = listInternalFields.size()-1;
240
                ds = null;
241
                getRecordset().mapExternalFields();
242
                bFieldsHasBeenChanged = true;
243
        }
244

    
245
        /**
246
         * DOCUMENT ME!
247
         * @throws StartEditionLayerException
248
         * @throws StartWriterVisitorException
249
         *
250
         * @throws EditionException
251
         *             DOCUMENT ME!
252
         */
253
        public void startEdition(int sourceType) throws StartWriterVisitorException {
254
                isEditing = true;
255

    
256
                fireStartEditionEvent(sourceType);
257
        }
258

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

    
281
        public void saveEdits(IWriter writer, int sourceType)
282
                        throws StopWriterVisitorException {
283

    
284
                Throwable true_cause = null;
285
                // TODO: ARREGLAR ESTO PARA QUE CUANDO HA HABIDO CAMBIOS
286
                // EN LOS CAMPOS, PODAMOS CAMBIAR LO QUE TOQUE (A SER POSIBLE
287
                // SIN TENER QUE REESCRIBIR TODA LA TABLA CON POSTGIS)
288
                if (bFieldsHasBeenChanged)
289
                {
290
                        // Para cada campo de los originales, miramos si no est? en
291
                        // los actuales. Si no est?, le decimos al fieldManager
292
                        // que lo borre. Si est?, pero le hemos cambiado el nombre
293
                        // le pedimos al fieldManager que le cambie el nombre.
294
                        // Luego recorremos los campos actuales para ver cuales
295
                        // son nuevos, y los a?adimos.
296

    
297
                        TreeMap ancientFields = (TreeMap) listInternalFields
298
                                        .get(0);
299
                        Collection aux = ancientFields.values();
300
                        Iterator it = aux.iterator();
301
                        while (it.hasNext()) {
302
                                InternalField fld = (InternalField) it.next();
303
                                if (actualFields.containsKey(fld.getFieldId())) {
304
                                        // Es un original
305
                                        String f1 = fld.getFieldDesc().getFieldName();
306
                                        String f2 = ((InternalField)actualFields.get(fld.getFieldId())).getFieldDesc().getFieldAlias();
307
                                        if (f1.compareTo(f2) != 0){
308
                                                getFieldManager().renameField(f1, f2);
309
                                        }
310
                                }
311
                                else {        // No est?, hay que borrarlo
312
                                        getFieldManager().removeField(fld.getFieldDesc().getFieldAlias());
313
                                }
314
                        }
315
                        Collection aux2= actualFields.values();
316
                        Iterator it2 = aux2.iterator();
317
                        while (it2.hasNext()) {
318
                                InternalField fld = (InternalField) it2.next();
319
                                if (!ancientFields.containsKey(fld.getFieldId())) {
320
                                        // Es uno a?adido
321
                                        getFieldManager().addField(fld.getFieldDesc());
322
                                }
323
                        }
324
                }
325
                
326
                ITableDefinition tab_def = null;
327
                
328
                try {
329
                        tab_def = writer.getTableDefinition();
330
                        writer.preProcess();
331
                        // Procesamos primero los borrados.
332
                        // Cuando se genere un tema nuevo, no se les debe hacer caso
333
                        // a estos registros
334

    
335
                        int rowCount = getRowCount();
336
                        if (writer.isWriteAll()){
337
                                for (int i = 0; i < rowCount; i++) {
338
                                        IRowEdited row=getRow(i);
339
//                                        IRowEdited rowEdited = new DefaultRowEdited(row.getLinkedRow()
340
//                                                        .cloneRow(), row.getStatus(), i);
341
                                        if (row != null) {
342
                                                writer.process(row);
343
                                        }
344
                                }
345
                        } else {
346
                                for (int i = delRows.nextSetBit(0); i >= 0; i = delRows
347
                                        .nextSetBit(i + 1)) {
348
                                        int calculatedIndex = i;
349
                                        Integer integer = new Integer(calculatedIndex);
350
                                        // Si no est? en el fichero de expansi?n, es de los originales
351
                                        // y hay que borrarlo
352
                                        DefaultRowEdited edRow = null;
353
                                        if (!relations.containsKey(integer)) {
354
                                                edRow = new DefaultRowEdited(new DefaultRow(ods
355
                                                                .getRow(calculatedIndex)),
356
                                                                IRowEdited.STATUS_DELETED, calculatedIndex);
357
                                                writer.process(edRow);
358
                                        }
359
                                }
360
                                // Escribimos solo aquellos registros que han cambiado
361
                                for (int i = 0; i < rowCount; i++) {
362
                                        int calculatedIndex = getCalculatedIndex(i);
363
                                        Integer integer = new Integer(calculatedIndex);
364
                                        DefaultRowEdited edRow = null;
365
                                        // Si est? en el fichero de expansi?n hay que modificar
366
                                        if (relations.containsKey(integer)) {
367
                                                int num = ((Integer) relations.get(integer)).intValue();
368
                                                // ExpansionFile ya entrega el registro formateado como debe
369
                                                IRowEdited rowFromExpansion = expansionFile.getRow(num);
370
                                                // ?Habr?a que hacer aqu? setID(index + "")?
371
                                                edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
372
                                                                .cloneRow(), rowFromExpansion.getStatus(), i);
373
                                                writer.process(edRow);
374
                                        }
375
                                }
376
                        }
377
                        writer.postProcess();
378
                        writer.getTableDefinition().setFieldsDesc(getRecordset().getFieldsDescription());
379
                        ods.reload();
380
                        ds = null;
381
                        clean();
382
                } catch (ReadDriverException e) {
383
                        repairConnectionIfNeeded(tab_def);
384
                        true_cause = e.getCause();
385
                        throw new StopWriterVisitorException(writer.getName(), true_cause == null ? e : true_cause);
386
                } catch (StartWriterVisitorException e) {
387
                        repairConnectionIfNeeded(tab_def);
388
                        true_cause = e.getCause();
389
                        throw new StopWriterVisitorException(writer.getName(), true_cause == null ? e : true_cause);
390
                } catch (VisitorException e) {
391
                        repairConnectionIfNeeded(tab_def);
392
                        true_cause = e.getCause();
393
                        throw new StopWriterVisitorException(writer.getName(), true_cause == null ? e : true_cause);
394
                }
395

    
396
        }
397

    
398
        private void repairConnectionIfNeeded(ITableDefinition tdef) {
399
                
400
                if (tdef instanceof DBLayerDefinition) {
401
                        DBLayerDefinition dbl = (DBLayerDefinition) tdef;
402
                        if (dbl.getConnection() instanceof ConnectionJDBC) {
403
                                ConnectionJDBC conn = (ConnectionJDBC) dbl.getConnection();
404
                                try {
405
                                        conn.getConnection().rollback();
406
                                } catch (SQLException e) {
407
                                        logger.error("Unable to rollback connection after write error: " + e.getMessage());
408
                                }
409
                        }
410
                }
411
                
412
        }
413

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

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

    
452
                                return createExternalRow(edRow, 0);
453
//                                edRow = new DefaultRowEdited(new DefaultRow(ods
454
//                                                .getRow(calculatedIndex)),
455
//                                                DefaultRowEdited.STATUS_ORIGINAL, index);
456
                }
457
                int num = ((Integer) relations.get(integer)).intValue();
458

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

    
468

    
469

    
470
        }
471

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

    
488
        /*
489
         * (non-Javadoc)
490
         *
491
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
492
         *      java.lang.String)
493
         */
494
        public int addRow(IRow row, String descrip, int sourceType) throws ValidateRowException, ReadDriverException, ExpansionFileWriteException{
495
                validateRow(row,sourceType);
496

    
497
                int calculatedIndex = doAddRow(row, sourceType);
498
                Command command = new AddRowCommand(this, row, calculatedIndex,
499
                                sourceType);
500
                command.setDescription(descrip);
501
                if (complex) {
502
                        commands.add(command);
503
                } else {
504
                        cr.pushCommand(command);
505
                }
506

    
507
                return calculatedIndex;
508
        }
509

    
510
        /**
511
         * DOCUMENT ME!
512
         * @throws EditionCommandException
513
         *
514
         * @throws DriverIOException
515
         *             DOCUMENT ME!
516
         * @throws IOException
517
         *             DOCUMENT ME!
518
         */
519
        public void undo() throws EditionCommandException{
520
                // seleccion.clear();
521
                if (cr.moreUndoCommands()) {
522
                        cr.undoCommand();
523
                }
524
        }
525

    
526
        /**
527
         * DOCUMENT ME!
528
         * @throws EditionCommandException
529
         *
530
         * @throws DriverIOException
531
         *             DOCUMENT ME!
532
         * @throws IOException
533
         *             DOCUMENT ME!
534
         */
535
        public void redo() throws EditionCommandException {
536
                // seleccion.clear();
537
                if (cr.moreRedoCommands()) {
538
                        cr.redoCommand();
539
                }
540
        }
541

    
542
        /*
543
         * (non-Javadoc)
544
         *
545
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#removeRow(int)
546
         */
547
        public void removeRow(int index, String descrip, int sourceType) throws ReadDriverException, ExpansionFileReadException {
548

    
549
                int calculatedIndex = getCalculatedIndex(index);
550
                Command command = new RemoveRowCommand(this, calculatedIndex,
551
                                sourceType);
552
                command.setDescription(descrip);
553
                if (complex) {
554
                        commands.add(command);
555
                } else {
556
                        cr.pushCommand(command);
557
                }
558
                doRemoveRow(calculatedIndex, sourceType);
559

    
560
        }
561

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

    
581
                return pos;
582
        }
583

    
584
        /**
585
         * DOCUMENT ME!
586
         */
587
        public void compact() {
588
                expansionFile.compact(relations);
589
        }
590

    
591
        /**
592
         * DOCUMENT ME!
593
         */
594
        public void startComplexRow() {
595
                complex = true;
596
                commands = new CommandCollection();
597
        }
598

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

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

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

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

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

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

    
757
                        /*
758
                         * Se modifica la geometr?a y nos guardamos el ?ndice dentro del
759
                         * fichero de expansi?n en el que se encuentra la geometr?a
760
                         * modificada
761
                         */
762
                        num = expansionFile.modifyRow(num, feat, actualIndexFields);
763

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

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

    
795
                calculatedIndex = (int) ods.getRowCount() + numAdd;
796

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

    
806
        /**
807
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
808
         * en el fichero original
809
         *
810
         * @param index
811
         *            DOCUMENT ME!
812
         */
813
        public void undoRemoveRow(int index, int sourceType) throws EditionCommandException {
814
                delRows.set(index, false);
815
                String fid;
816
                try {
817
                        fid = getRow(index).getID();
818

    
819
                boolean cancel = fireBeforeRowAdded(sourceType,fid);
820
                if (cancel){
821
                        delRows.set(index,true);
822
                        return;
823
                }
824
                } catch (ExpansionFileReadException e) {
825
                        throw new EditionCommandException(getOriginalDriver().getName(),e);
826
                } catch (ReadDriverException e) {
827
                        throw new EditionCommandException(getOriginalDriver().getName(),e);
828
                }
829
                fireAfterRowAdded(null,index, sourceType);
830
        }
831

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

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

    
869
                                try {
870

    
871
                                        ds = new SelectableDataSource(LayerFactory
872
                                                        .getDataSourceFactory().createRandomDataSource(
873
                                                                        name, DataSourceFactory.AUTOMATIC_OPENING));
874
                                        ds.start();
875
                                        ds.setSelectionSupport(ods.getSelectionSupport());
876

    
877
                                } catch (NoSuchTableException e) {
878
                                        throw new RuntimeException(e);
879
                                } catch (DriverLoadException e) {
880
                                        throw new ReadDriverException(name,e);
881
                                }
882
                        }
883

    
884
                        return ds;
885
                }
886
                return ods;
887
        }
888

    
889
        /**
890
         * Return always the original recordset (even when is editing,
891
         * nor the getRecorset() method)
892
         *
893
         * */
894
        public SelectableDataSource getOriginalRecordset(){
895
                return ods;
896
        }
897

    
898

    
899
        /**
900
         * DOCUMENT ME!
901
         *
902
         * @return
903
         * @throws ReadDriverException
904
         */
905
        public FBitSet getSelection() throws ReadDriverException {
906
                /*
907
                 * try { return getRecordset().getSelection(); } catch
908
                 * (DriverLoadException e) { // TODO Auto-generated catch block
909
                 * e.printStackTrace(); } return null;
910
                 */
911
                return getRecordset().getSelection();
912
        }
913

    
914
        public void setSelection(FBitSet selection) throws ReadDriverException {
915
                /*
916
                 * try { getRecordset().setSelection(selection); } catch
917
                 * (DriverLoadException e) { // TODO Auto-generated catch block
918
                 * e.printStackTrace(); }
919
                 */
920
                getRecordset().setSelection(selection);
921
        }
922

    
923
        /**
924
         * DOCUMENT ME!
925
         *
926
         * @return DOCUMENT ME!
927
         */
928
        public boolean isEditing() {
929
                return isEditing;
930
        }
931

    
932
        public int getInversedIndex(long rowIndex) {
933
                int intervalNotDeleted = 0;
934
                int antDeleted = -1;
935
                int idPedido = (int) rowIndex;
936
                int numNotDeleted = 0;
937
                int numBorradosAnt = 0;
938

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

    
956
        /**
957
         * DOCUMENT ME!
958
         *
959
         * @param rowIndex
960
         *            DOCUMENT ME!
961
         *
962
         * @return DOCUMENT ME!
963
         */
964
        public int getCalculatedIndex(long rowIndex) {
965
                int numNotDeleted = 0;
966
                int intervalNotDeleted = 0;
967
                int antDeleted = -1;
968
                int calculatedIndex;
969
                int idPedido = (int) rowIndex;
970
                int numBorradosAnt = 0;
971

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

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

    
1009
                /*
1010
                 * (non-Javadoc)
1011
                 *
1012
                 * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
1013
                 */
1014
                public void write(DataWare dataWare) throws ReadDriverException, WriteDriverException {
1015
                        DataWare dataWareOrig = ods
1016
                                        .getDataWare(DataSourceFactory.DATA_WARE_DIRECT_MODE);
1017
                        dataWareOrig.commitTrans();
1018
                }
1019

    
1020
                /*
1021
                 * (non-Javadoc)
1022
                 *
1023
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
1024
                 */
1025
                public void setDataSourceFactory(DataSourceFactory dsf) {
1026
                        ods.setDataSourceFactory(dsf);
1027
                }
1028

    
1029
                /*
1030
                 * (non-Javadoc)
1031
                 *
1032
                 * @see com.hardcode.driverManager.Driver#getName()
1033
                 */
1034
                public String getName() {
1035
                        return ods.getName();
1036
                }
1037

    
1038
                /*
1039
                 * (non-Javadoc)
1040
                 *
1041
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
1042
                 *      int)
1043
                 */
1044
                public Value getFieldValue(long rowIndex, int fieldId) throws ReadDriverException {
1045
                        // Si no est? en el fichero de expansi?n
1046
                        // Integer integer = new Integer(getCalculatedIndex(rowIndex));
1047

    
1048

    
1049
                        try {
1050
                                IRow row = getRow((int)rowIndex);
1051
                                return row.getAttribute(fieldId);
1052
//                                if (!relations.containsKey(integer)) {
1053
//                                        return ods.getFieldValue(rowIndex, fieldId);
1054
//                                } else {
1055
//                                        int num = ((Integer) relations.get(integer)).intValue();
1056
//                                        DefaultRowEdited feat = (DefaultRowEdited) expansionFile
1057
//                                                        .getRow(num);
1058
//
1059
//                                        if (feat == null) {
1060
//                                                return null;
1061
//                                        }
1062
//
1063
//                                        return feat.getAttribute(fieldId);
1064
//                                }
1065
//                        } catch (DriverException e) {
1066
//                                e.printStackTrace();
1067
//                                throw new DriverException(e);
1068
                        } catch (ExpansionFileReadException e) {
1069
                                throw new ReadDriverException(getRecordset().getDriver().getName(),e);
1070
                        }
1071

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

    
1086
                /*
1087
                 * (non-Javadoc)
1088
                 *
1089
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1090
                 */
1091
                public int getFieldCount() throws ReadDriverException {
1092
                        return fastAccessFields.size();
1093
                }
1094

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

    
1116
                /*
1117
                 * (non-Javadoc)
1118
                 *
1119
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
1120
                 */
1121
                public long getRowCount() throws ReadDriverException {
1122
                        return (int) (ods.getRowCount() + numAdd)
1123
                                        - delRows.cardinality();// -
1124
                        // expansionFile.getInvalidRows().cardinality();
1125
                }
1126

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

    
1144
//                        return ods.getFieldType(i);
1145
                }
1146

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

    
1163
                }
1164

    
1165
                public void reload() throws ReloadDriverException {
1166
                        ods.reload();
1167

    
1168
                }
1169
        }
1170

    
1171
        public CommandRecord getCommandRecord() {
1172
                return cr;
1173
        }
1174

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

    
1188
        }
1189

    
1190
        protected boolean fireBeforeRemoveRow(int index, int sourceType) throws ReadDriverException {
1191
                Cancel cancel = new Cancel();
1192
                String fid=null;
1193
                IRow row=null;
1194
                try {
1195
                        row=getRow(getInversedIndex(index));
1196
                        fid = row.getID();
1197
                } catch (ExpansionFileReadException e) {
1198
                        throw new ReadDriverException(getOriginalDriver().getName(),e);
1199
                }
1200
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, fid,
1201
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1202
                for (int i = 0; i < editionListeners.size(); i++) {
1203
                        IEditionListener listener = (IEditionListener) editionListeners
1204
                                        .get(i);
1205
                        listener.beforeRowEditEvent(row, event);
1206
                        if (cancel.isCanceled())
1207
                                return true;
1208
                }
1209
                return false;
1210
        }
1211

    
1212
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1213
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1214
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1215
                if (complex){
1216
                        rowEvents.add(event);
1217
                        return;
1218
                }
1219
                for (int i = 0; i < editionListeners.size(); i++) {
1220
                        IEditionListener listener = (IEditionListener) editionListeners
1221
                                        .get(i);
1222
                        listener.afterRowEditEvent(feat, event);
1223
                }
1224
        }
1225

    
1226
        protected void fireAfterFieldAdded(FieldDescription field) {
1227
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1228
                                EditionEvent.CHANGE_TYPE_ADD);
1229
                if (complex) {
1230
                        fieldEvents.add(event);
1231
                        return;
1232
                }
1233
                for (int i = 0; i < editionListeners.size(); i++) {
1234
                        IEditionListener listener = (IEditionListener) editionListeners
1235
                                        .get(i);
1236
                        listener.afterFieldEditEvent(event);
1237

    
1238
                }
1239
        }
1240

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

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

    
1269

    
1270
        protected boolean fireBeforeRowAdded(int sourceType,String newFID) throws ReadDriverException{
1271
                Cancel cancel = new Cancel();
1272
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, newFID,
1273
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1274
                for (int i = 0; i < editionListeners.size(); i++) {
1275
                        IEditionListener listener = (IEditionListener) editionListeners
1276
                                        .get(i);
1277
                        listener.beforeRowEditEvent(null, event);
1278
                        if (cancel.isCanceled())
1279
                                return true;
1280
                }
1281
                return false;
1282
        }
1283

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

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

    
1312

    
1313
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) throws ReadDriverException {
1314
                Cancel cancel = new Cancel();
1315
                String fid=null;
1316
                try {
1317
                        fid = getRow(getInversedIndex(index)).getID();
1318
                } catch (ExpansionFileReadException e) {
1319
                        throw new ReadDriverException(getOriginalDriver().getName(),e);
1320
                }
1321
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, fid,
1322
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1323
                for (int i = 0; i < editionListeners.size(); i++) {
1324
                        IEditionListener listener = (IEditionListener) editionListeners
1325
                                        .get(i);
1326
                        listener.beforeRowEditEvent(feat, event);
1327
                        if (cancel.isCanceled())
1328
                                return true;
1329
                }
1330
                return false;
1331
        }
1332

    
1333
        protected void fireAfterModifyRow(int index, int sourceType) {
1334
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1335
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1336
                if (complex){
1337
                        rowEvents.add(event);
1338
                        return;
1339
                }
1340
                for (int i = 0; i < editionListeners.size(); i++) {
1341
                        IEditionListener listener = (IEditionListener) editionListeners
1342
                                        .get(i);
1343
                        listener.afterRowEditEvent(null, event);
1344
                }
1345

    
1346
        }
1347

    
1348
        protected void fireStartEditionEvent(int sourceType) {
1349
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_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 fireStopEditionEvent(int sourceType) {
1360
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_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
        protected void fireCancelEditionEvent(int sourceType) {
1371
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1372
                                sourceType);
1373
                for (int i = 0; i < editionListeners.size(); i++) {
1374
                        IEditionListener listener = (IEditionListener) editionListeners
1375
                                        .get(i);
1376
                        listener.processEvent(ev);
1377
                }
1378

    
1379
        }
1380

    
1381
        public void addEditionListener(IEditionListener listener) {
1382
                if (!editionListeners.contains(listener))
1383
                        editionListeners.add(listener);
1384
        }
1385

    
1386
        public void removeEditionListener(IEditionListener listener) {
1387
                editionListeners.remove(listener);
1388
        }
1389

    
1390
        public IWriter getWriter() {
1391
                return writer;
1392
        }
1393

    
1394
        protected void setWriter(IWriter writer) {
1395
                this.writer = writer;
1396

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

    
1417

    
1418
        }
1419

    
1420
        public void validateRow(IRow row,int sourceType) throws ValidateRowException  {
1421
                for (int i = 0; i < rules.size(); i++) {
1422
                        IRule rule = (IRule) rules.get(i);
1423
                        boolean bAux = rule.validate(row,sourceType);
1424
                        if (bAux == false) {
1425
                                ValidateRowException ex = new ValidateRowException(writer.getName(),null);
1426
                                // TODO: Lanzar una RuleException con datos como el registro
1427
                                // que no cumple, la regla que no lo ha cumplido, etc.
1428
                                throw ex;
1429
                        }
1430
                }
1431
        }
1432

    
1433
        public ArrayList getRules() {
1434
                return rules;
1435
        }
1436

    
1437
        public void setRules(ArrayList rules) {
1438
                this.rules = rules;
1439
        }
1440

    
1441
        private void clean() throws ReadDriverException {
1442
                try {
1443
                        expansionFile.close();
1444
                } catch (CloseExpansionFileException e) {
1445
                        throw new ReadDriverException(getRecordset().getDriver().getName(),e);
1446
                }
1447
                relations.clear();
1448
                numAdd = 0;
1449
                delRows.clear();
1450
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1451
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1452
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1453
                // reload completo.
1454
                initalizeFields(ods);
1455

    
1456
//                listInternalFields.clear();
1457
//                listInternalFields.add(actualFields);
1458
        }
1459

    
1460
        /*
1461
         * (non-Javadoc)
1462
         *
1463
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1464
         */
1465
        public IFieldManager getFieldManager() {
1466
                if (ods.getDriver() instanceof IWriteable)
1467
                {
1468
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1469
                        if ((writer != null) && (writer instanceof IFieldManager))
1470
                        {
1471
                                IFieldManager fldManager = (IFieldManager) writer;
1472
                                return fldManager;
1473
                        }
1474
                }
1475
                return null;
1476
        }
1477

    
1478
        /**
1479
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1480
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1481
         *
1482
         * @param edRow
1483
         * @param indexInternalFields
1484
         * @return
1485
         */
1486
        public IRowEdited createExternalRow(IRowEdited edRow,
1487
                        int indexInternalFields) {
1488

    
1489
                // para acelerar
1490
                if (bFieldsHasBeenChanged == false)
1491
                        return edRow;
1492

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

    
1529
        public void removeField(String fieldName) throws WriteDriverException, ReadDriverException {
1530

    
1531
                InternalField fld = findFieldByName(fieldName);
1532
                if (fld == null)
1533
                        throw new WriteDriverException(getRecordset().getDriver().getName(),null);
1534
                //throw new WriteDriverException("Field " + fieldName + " not found when removing field");
1535
                Command command = new RemoveFieldCommand(this, fld);
1536
                if (complex) {
1537
                        commands.add(command);
1538
                } else {
1539
                        cr.pushCommand(command);
1540
                }
1541
                doRemoveField(fld);
1542

    
1543
        }
1544

    
1545
        private InternalField findFieldByName(String fieldName) {
1546
                Collection aux = actualFields.values();
1547
                Iterator it = aux.iterator();
1548
                while (it.hasNext()) {
1549
                        InternalField fld = (InternalField) it.next();
1550
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1551
                                return fld;
1552
                }
1553

    
1554
                return null;
1555
        }
1556

    
1557
        public void undoRemoveField(InternalField field) throws EditionCommandException {
1558
                // field.setDeleted(false);
1559
//                field.setFieldIndex(actualFields.size());
1560
                actualFields.put(field.getFieldId(), field);
1561
                try {
1562
                        fieldsChanged();
1563
                } catch (ReadDriverException e) {
1564
                        throw new EditionCommandException(writer.getName(),e);
1565
                }
1566
                fireAfterFieldAdded(field.getFieldDesc());
1567
        }
1568

    
1569
        public void doRemoveField(InternalField field) throws ReadDriverException {
1570
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1571
                if (cancel) return;
1572
                actualFields.remove(field.getFieldId());
1573
                fieldsChanged();
1574
                fireAfterFieldRemoved(field.getFieldDesc());
1575
        }
1576

    
1577
        public void renameField(String antName, String newName) throws ReadDriverException{
1578

    
1579
                InternalField fld = findFieldByName(antName);
1580
                Command command = new RenameFieldCommand(this, fld, newName);
1581
                if (complex) {
1582
                        commands.add(command);
1583
                } else {
1584
                        cr.pushCommand(command);
1585
                }
1586
                doRenameField(fld, newName);
1587

    
1588
        }
1589

    
1590
        public void undoRenameField(InternalField field, String antName) throws EditionCommandException{
1591
                field.getFieldDesc().setFieldAlias(antName);
1592
                try {
1593
                        fieldsChanged();
1594
                } catch (ReadDriverException e) {
1595
                        throw new EditionCommandException(writer.getName(),e);
1596
                }
1597
                fireAfterFieldModified(field.getFieldDesc());
1598

    
1599
        }
1600

    
1601
        public void doRenameField(InternalField field, String newName) throws ReadDriverException{
1602
                field.getFieldDesc().setFieldAlias(newName);
1603
                fieldsChanged();
1604
                fireAfterFieldModified(field.getFieldDesc());
1605

    
1606
        }
1607

    
1608

    
1609
        public void addField(FieldDescription field) throws ReadDriverException {
1610

    
1611
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1612
                Command command = new AddFieldCommand(this, fld);
1613
                if (complex) {
1614
                        commands.add(command);
1615
                } else {
1616
                        cr.pushCommand(command);
1617
                }
1618
                listFields.add(fld);
1619
                doAddField(fld);
1620

    
1621
        }
1622

    
1623
        public void undoAddField(InternalField field) throws EditionCommandException  {
1624
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1625
                if (cancel)
1626
                        return;
1627

    
1628
                // field.setDeleted(true);
1629
                actualFields.remove(field.getFieldId());
1630
                try {
1631
                        fieldsChanged();
1632
                } catch (ReadDriverException e) {
1633
                        throw new EditionCommandException(writer.getName(),e);
1634
                }
1635
                fireAfterFieldRemoved(field.getFieldDesc());
1636

    
1637
        }
1638

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

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

    
1654
        public Driver getOriginalDriver()
1655
        {
1656
                return ods.getDriver();
1657
        }
1658

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

    
1667
        public FieldDescription[] getFieldsDescription() {
1668
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1669
        }
1670
        public String getNewFID() {
1671
                return "fid-" + (new UID()).toString();
1672
        }
1673

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

    
1684
}
1685

    
1686
// [eiel-gestion-excepciones]