Statistics
| Revision:

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

History | View | Annotate | Download (50.1 KB)

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

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

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

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

    
65
        private SelectableDataSource ds = null;
66

    
67
        protected FBitSet delRows = new FBitSet();
68

    
69
        private CommandRecord cr;
70

    
71
        protected IWriter writer;
72

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

    
79
        private CommandCollection commands = null;
80

    
81
        protected ArrayList listFields = new ArrayList();
82

    
83
        protected ArrayList listInternalFields = new ArrayList();
84

    
85
        protected boolean bFieldsHasBeenChanged = false;
86

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

    
97
        protected ArrayList fastAccessFields = new ArrayList();
98

    
99
        protected class MyFieldManager extends AbstractFieldManager {
100

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

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

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

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

    
119
        }
120

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

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

    
142
        protected int numAdd = 0;
143

    
144
        private ObjectDriver editingDriver = new myObjectDriver();
145

    
146
        private SelectableDataSource ods;
147

    
148
        private ArrayList editionListeners = new ArrayList();
149

    
150
        private ArrayList rules = new ArrayList();
151

    
152
        protected int actualIndexFields;
153

    
154
        protected boolean isFullExtentDirty = false;
155

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

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

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

    
182

    
183
        }
184

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

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

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

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

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

    
247
                fireStartEditionEvent(sourceType);
248
        }
249

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

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

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

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

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

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

    
350
                        }
351

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

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

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

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

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

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

    
408
        }
409

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

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

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

    
463

    
464

    
465
        }
466

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

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

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

    
502
                return calculatedIndex;
503
        }
504

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

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

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

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

    
555
        }
556

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

    
576
                return pos;
577
        }
578

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

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

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

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

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

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

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

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

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

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

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

    
787
                calculatedIndex = (int) ods.getRowCount() + numAdd;
788

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

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

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

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

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

    
861
                                try {
862

    
863
                                        ds = new SelectableDataSource(LayerFactory
864
                                                        .getDataSourceFactory().createRandomDataSource(
865
                                                                        name, DataSourceFactory.MANUAL_OPENING));
866
                                        ds.start();
867
                                        ds.setSelectionSupport(ods.getSelectionSupport());
868

    
869
                                } catch (NoSuchTableException e) {
870
                                        throw new RuntimeException(e);
871
                                } catch (DriverLoadException e) {
872
                                        throw new ReadDriverException(name,e);
873
                                }
874
                        }
875

    
876
                        return ds;
877
                }
878
                return ods;
879
        }
880

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

    
890

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

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

    
915
        /**
916
         * DOCUMENT ME!
917
         *
918
         * @return DOCUMENT ME!
919
         */
920
        public boolean isEditing() {
921
                return isEditing;
922
        }
923

    
924
        public int getInversedIndex(long rowIndex) {
925
                int intervalNotDeleted = 0;
926
                int antDeleted = -1;
927
                int idPedido = (int) rowIndex;
928
                int numNotDeleted = 0;
929
                int numBorradosAnt = 0;
930

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

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

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

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

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

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

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

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

    
1040

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

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

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

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

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

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

    
1136
//                        return ods.getFieldType(i);
1137
                }
1138

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

    
1155
                }
1156

    
1157
                public void reload() throws ReloadDriverException {
1158
                        ods.reload();
1159

    
1160
                }
1161
        }
1162

    
1163
        public CommandRecord getCommandRecord() {
1164
                return cr;
1165
        }
1166

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

    
1180
        }
1181

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

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

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

    
1228
                }
1229
        }
1230

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

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

    
1259

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

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

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

    
1302

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

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

    
1336
        }
1337

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

    
1347
        }
1348

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

    
1358
        }
1359

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

    
1369
        }
1370

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

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

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

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

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

    
1407

    
1408
        }
1409

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

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

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

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

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

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

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

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

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

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

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

    
1533
        }
1534

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

    
1544
                return null;
1545
        }
1546

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

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

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

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

    
1578
        }
1579

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

    
1589
        }
1590

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

    
1596
        }
1597

    
1598

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

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

    
1611
        }
1612

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

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

    
1627
        }
1628

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

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

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

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

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

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

    
1674
}