Statistics
| Revision:

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

History | View | Annotate | Download (48.5 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.engine.data.DataSourceFactory;
14
import com.hardcode.gdbms.engine.data.NoSuchTableException;
15
import com.hardcode.gdbms.engine.data.driver.AlphanumericDBDriver;
16
import com.hardcode.gdbms.engine.data.driver.DriverException;
17
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
18
import com.hardcode.gdbms.engine.data.edition.DataWare;
19
import com.hardcode.gdbms.engine.values.Value;
20
import com.iver.cit.gvsig.fmap.core.DefaultRow;
21
import com.iver.cit.gvsig.fmap.core.IRow;
22
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
23
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
24
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
25
import com.iver.cit.gvsig.fmap.drivers.TableDefinition;
26
import com.iver.cit.gvsig.fmap.edition.commands.AddFieldCommand;
27
import com.iver.cit.gvsig.fmap.edition.commands.AddRowCommand;
28
import com.iver.cit.gvsig.fmap.edition.commands.Command;
29
import com.iver.cit.gvsig.fmap.edition.commands.CommandCollection;
30
import com.iver.cit.gvsig.fmap.edition.commands.CommandRecord;
31
import com.iver.cit.gvsig.fmap.edition.commands.MemoryCommandRecord;
32
import com.iver.cit.gvsig.fmap.edition.commands.ModifyRowCommand;
33
import com.iver.cit.gvsig.fmap.edition.commands.RemoveFieldCommand;
34
import com.iver.cit.gvsig.fmap.edition.commands.RemoveRowCommand;
35
import com.iver.cit.gvsig.fmap.edition.commands.RenameFieldCommand;
36
import com.iver.cit.gvsig.fmap.edition.fieldmanagers.AbstractFieldManager;
37
import com.iver.cit.gvsig.fmap.edition.rules.IRule;
38
import com.iver.cit.gvsig.fmap.layers.FBitSet;
39
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
40
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
41
import com.iver.cit.gvsig.fmap.operations.Cancel;
42

    
43
/**
44
 * DOCUMENT ME!
45
 *
46
 * @author Vicente Caballero Navarro
47
 */
48
public class EditableAdapter implements IEditableSource, IWriteable {
49
        protected boolean isEditing = false;
50

    
51
        private SelectableDataSource ds = null;
52

    
53
        protected FBitSet delRows = new FBitSet();
54

    
55
        private CommandRecord cr;
56

    
57
        protected IWriter writer;
58

    
59
        /**
60
         * Flag que indica que hay que tomar las siguientes operaciones como una
61
         * operaci?n at?mica
62
         */
63
        private boolean complex = false;
64

    
65
        private CommandCollection commands = null;
66

    
67
        protected ArrayList listFields = new ArrayList();
68

    
69
        protected ArrayList listInternalFields = new ArrayList();
70

    
71
        protected boolean bFieldsHasBeenChanged = false;
72

    
73
        /**
74
         * La clave ser? el fieldId. Para buscar si un value de una row ha de ser
75
         * rellenado con defaultValue o con lo que venga del expansion file,
76
         * miraremos si existe en este hash. Si existe, usamos el value del
77
         * expansion file. Si no existe, usamos el defaultValue del campo busc?ndolo
78
         * en la lista internalFields. Por cierto, en listInternalFields NO se
79
         * borran campos. Solo se van a?adiendo nuevos actualFields.
80
         */
81
        protected TreeMap actualFields; // la clave ser? el fieldId.
82

    
83
        protected ArrayList fastAccessFields = new ArrayList();
84

    
85
        protected class MyFieldManager extends AbstractFieldManager {
86

    
87
                public boolean alterTable() throws EditionException {
88
                        return getFieldManager().alterTable();
89
                }
90

    
91
                public void addField(FieldDescription fieldDesc) {
92
                        super.addField(fieldDesc);
93
                }
94

    
95
                public FieldDescription removeField(String fieldName) {
96
                        // TODO Auto-generated method stub
97
                        return super.removeField(fieldName);
98
                }
99

    
100
                public void renameField(String antName, String newName) {
101
                        // TODO Auto-generated method stub
102
                        super.renameField(antName, newName);
103
                }
104

    
105
        }
106

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

    
122
        /*
123
         * Fichero en el que se guardan las nuevas geometr?as, producto de adiciones
124
         * o de modificaciones
125
         */
126
        protected ExpansionFile expansionFile;
127

    
128
        protected int numAdd = 0;
129

    
130
        private ObjectDriver editingDriver = new myObjectDriver();
131

    
132
        private SelectableDataSource ods;
133

    
134
        private ArrayList editionListeners = new ArrayList();
135

    
136
        private ArrayList rules = new ArrayList();
137

    
138
        protected int actualIndexFields;
139

    
140
        protected boolean isFullExtentDirty = false;
141

    
142
        private ArrayList fieldEvents=new ArrayList();
143
        private ArrayList rowEvents=new ArrayList();
144

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

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

    
168

    
169
        }
170

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

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

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

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

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

    
243
                fireStartEditionEvent(sourceType);
244
        }
245

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

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

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

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

    
317
                writer.preProcess();
318

    
319
                try {
320

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

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

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

    
349
                        }
350

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

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

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

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

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

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

    
408
        }
409

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

    
429
        /*
430
         * (non-Javadoc)
431
         *
432
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getRow(int)
433
         */
434
        public IRowEdited getRow(int index) throws DriverIOException, IOException {
435
                int calculatedIndex = getCalculatedIndex(index);
436
                Integer integer = new Integer(calculatedIndex);
437
                DefaultRowEdited edRow = null;
438
                // Si no est? en el fichero de expansi?n
439
                if (!relations.containsKey(integer)) {
440
                        try {
441
                                /*
442
                                 * edRow = new DefaultRowEdited(new
443
                                 * DefaultRow(ods.getRow(calculatedIndex), "" + index),
444
                                 * DefaultRowEdited.STATUS_ORIGINAL, index);
445
                                 */
446
                                DefaultRow auxR = new DefaultRow(ods.getRow(calculatedIndex));
447
                                edRow = new DefaultRowEdited(auxR,
448
                                                DefaultRowEdited.STATUS_ORIGINAL, index);
449
                                return createExternalRow(edRow, 0);
450
//                                edRow = new DefaultRowEdited(new DefaultRow(ods
451
//                                                .getRow(calculatedIndex)),
452
//                                                DefaultRowEdited.STATUS_ORIGINAL, index);
453
                        } catch (DriverException e) {
454
                                throw new DriverIOException(e);
455
                        }
456
                } else {
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 = expansionFile.getRow(num);
462
                        // ?Habr?a que hacer aqu? setID(index + "")?
463
                        edRow = new DefaultRowEdited(rowFromExpansion.getLinkedRow()
464
                                        .cloneRow(), rowFromExpansion.getStatus(), index);
465
                        return edRow;
466
                }
467

    
468

    
469

    
470
        }
471

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

    
490
        }
491
        public String getNewFID() {
492
                return "fid-" + (new UID()).toString();
493
        }
494
        /*
495
         * (non-Javadoc)
496
         *
497
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#addRow(com.iver.cit.gvsig.fmap.core.IRow,
498
         *      java.lang.String)
499
         */
500
        public int addRow(IRow row, String descrip, int sourceType)
501
                        throws DriverIOException, IOException {
502

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

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

    
520
                return calculatedIndex;
521
        }
522

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

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

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

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

    
572
        }
573

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

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

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

    
601
                return pos;
602
        }
603

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

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

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

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

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

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

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

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

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

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

    
782
        /**
783
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
784
         * en la tabla relations.
785
         *
786
         * @param feat
787
         *            geometr?a a guardar.
788
         *
789
         * @return calculatedIndex
790
         *
791
         * @throws DriverIOException
792
         * @throws IOException
793
         */
794
        public int doAddRow(IRow feat, int sourceType) throws DriverIOException,
795
                        IOException {
796

    
797
                boolean cancel = fireBeforeRowAdded(sourceType,feat.getID());
798
                if (cancel)
799
                        return -1;
800
                // A?ade la geometr?a
801
                // int virtualIndex = 0;
802
                int calculatedIndex = -1;
803

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

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

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

    
841
                fireAfterRowAdded(null,index, sourceType);
842
        }
843

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

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

    
877
                                try {
878

    
879
                                        /*
880
                                        ds = new SelectableDataSource(LayerFactory
881
                                                        .getDataSourceFactory().createRandomDataSource(
882
                                                                        name, DataSourceFactory.MANUAL_OPENING));
883
                                        */
884
                                        // CHEMA: AUTOMATIC DATA SOURCE
885
                                        ds = new SelectableDataSource(LayerFactory
886
                                                        .getDataSourceFactory().createRandomDataSource(
887
                                                                        name, DataSourceFactory.AUTOMATIC_OPENING));
888
                                        ds.start();
889
                                        ds.setSelectionSupport(ods.getSelectionSupport());
890

    
891
                                } catch (NoSuchTableException e) {
892
                                        throw new RuntimeException(e);
893
                                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
894
                                        throw new RuntimeException(e);
895
                                }
896
                        }
897

    
898
                        return ds;
899
                } else {
900
                        return ods;
901
                }
902
        }
903

    
904
        /**
905
         * Return always the original recordset (even when is editing,
906
         * nor the getRecorset() method)
907
         *
908
         * */
909
        public SelectableDataSource getOriginalRecordset(){
910
                return ods;
911
        }
912

    
913

    
914
        /**
915
         * DOCUMENT ME!
916
         *
917
         * @return
918
         */
919
        public FBitSet getSelection() {
920
                /*
921
                 * try { return getRecordset().getSelection(); } catch
922
                 * (DriverLoadException e) { // TODO Auto-generated catch block
923
                 * e.printStackTrace(); } return null;
924
                 */
925
                return getRecordset().getSelection();
926
        }
927

    
928
        public void setSelection(FBitSet selection) {
929
                /*
930
                 * try { getRecordset().setSelection(selection); } catch
931
                 * (DriverLoadException e) { // TODO Auto-generated catch block
932
                 * e.printStackTrace(); }
933
                 */
934
                getRecordset().setSelection(selection);
935
        }
936

    
937
        /**
938
         * DOCUMENT ME!
939
         *
940
         * @return DOCUMENT ME!
941
         */
942
        public boolean isEditing() {
943
                return isEditing;
944
        }
945

    
946
        public int getInversedIndex(long rowIndex) {
947
                int intervalNotDeleted = 0;
948
                int antDeleted = -1;
949
                int idPedido = (int) rowIndex;
950
                int numNotDeleted = 0;
951
                int numBorradosAnt = 0;
952

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

    
970
        /**
971
         * DOCUMENT ME!
972
         *
973
         * @param rowIndex
974
         *            DOCUMENT ME!
975
         *
976
         * @return DOCUMENT ME!
977
         */
978
        public int getCalculatedIndex(long rowIndex) {
979
                int numNotDeleted = 0;
980
                int intervalNotDeleted = 0;
981
                int antDeleted = -1;
982
                int calculatedIndex;
983
                int idPedido = (int) rowIndex;
984
                int numBorradosAnt = 0;
985

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

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

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

    
1034
                /*
1035
                 * (non-Javadoc)
1036
                 *
1037
                 * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
1038
                 */
1039
                public void setDataSourceFactory(DataSourceFactory dsf) {
1040
                        ods.setDataSourceFactory(dsf);
1041
                }
1042

    
1043
                /*
1044
                 * (non-Javadoc)
1045
                 *
1046
                 * @see com.hardcode.driverManager.Driver#getName()
1047
                 */
1048
                public String getName() {
1049
                        return ods.getName();
1050
                }
1051

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

    
1063

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

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

    
1105
                /*
1106
                 * (non-Javadoc)
1107
                 *
1108
                 * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
1109
                 */
1110
                public int getFieldCount() throws DriverException {
1111
                        return fastAccessFields.size();
1112
                }
1113

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

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

    
1150
                        return 0;
1151
                }
1152

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

    
1170
//                        return ods.getFieldType(i);
1171
                }
1172

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

    
1189
                }
1190

    
1191
                public void reload() throws IOException, DriverException {
1192
                        ods.reload();
1193

    
1194
                }
1195
        }
1196

    
1197
        public CommandRecord getCommandRecord() {
1198
                return cr;
1199
        }
1200

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

    
1214
        }
1215

    
1216
        protected boolean fireBeforeRemoveRow(int index, int sourceType) {
1217
                Cancel cancel = new Cancel();
1218
                String fid=null;
1219
                IRow row=null;
1220
                try {
1221
                        row=getRow(index);
1222
                        fid = row.getID();
1223
                } catch (DriverIOException e) {
1224
                        e.printStackTrace();
1225
                } catch (IOException e) {
1226
                        e.printStackTrace();
1227
                }
1228
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, fid,
1229
                                EditionEvent.CHANGE_TYPE_DELETE, cancel, sourceType);
1230
                for (int i = 0; i < editionListeners.size(); i++) {
1231
                        IEditionListener listener = (IEditionListener) editionListeners
1232
                                        .get(i);
1233
                        listener.beforeRowEditEvent(row, event);
1234
                        if (cancel.isCanceled())
1235
                                return true;
1236
                }
1237
                return false;
1238
        }
1239

    
1240
        protected void fireAfterRowAdded(IRow feat,int calculatedIndex, int sourceType) {
1241
                AfterRowEditEvent event = new AfterRowEditEvent(this, calculatedIndex,
1242
                                EditionEvent.CHANGE_TYPE_ADD, sourceType);
1243
                if (complex){
1244
                        rowEvents.add(event);
1245
                        return;
1246
                }
1247
                for (int i = 0; i < editionListeners.size(); i++) {
1248
                        IEditionListener listener = (IEditionListener) editionListeners
1249
                                        .get(i);
1250
                        listener.afterRowEditEvent(feat, event);
1251
                }
1252
        }
1253

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

    
1266
                }
1267
        }
1268

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

    
1283
        protected void fireAfterFieldModified(FieldDescription field) {
1284
                AfterFieldEditEvent event = new AfterFieldEditEvent(this,field,
1285
                                EditionEvent.CHANGE_TYPE_MODIFY);
1286
                if (complex) {
1287
                        fieldEvents.add(event);
1288
                        return;
1289
                }
1290
                for (int i = 0; i < editionListeners.size(); i++) {
1291
                        IEditionListener listener = (IEditionListener) editionListeners
1292
                                        .get(i);
1293
                        listener.afterFieldEditEvent(event);
1294
                }
1295
        }
1296

    
1297

    
1298
        protected boolean fireBeforeRowAdded(int sourceType,String newFID)
1299
                        throws DriverIOException, IOException {
1300
                Cancel cancel = new Cancel();
1301
                BeforeRowEditEvent event;
1302
                event = new BeforeRowEditEvent(this, newFID,
1303
                                EditionEvent.CHANGE_TYPE_ADD, cancel, sourceType);
1304
                for (int i = 0; i < editionListeners.size(); i++) {
1305
                        IEditionListener listener = (IEditionListener) editionListeners
1306
                                        .get(i);
1307
                        listener.beforeRowEditEvent(null, event);
1308
                        if (cancel.isCanceled())
1309
                                return true;
1310
                }
1311
                return false;
1312
        }
1313

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

    
1329
        protected boolean fireBeforeRemoveField(FieldDescription field)
1330
        throws EditionException {
1331
                Cancel cancel = new Cancel();
1332
                BeforeFieldEditEvent event = new BeforeFieldEditEvent(this, field,
1333
                EditionEvent.CHANGE_TYPE_DELETE, cancel);
1334
                for (int i = 0; i < editionListeners.size(); i++) {
1335
                        IEditionListener listener = (IEditionListener) editionListeners
1336
                        .get(i);
1337
                        listener.beforeFieldEditEvent(event);
1338
                        if (cancel.isCanceled())
1339
                                return true;
1340
                }
1341
                return false;
1342
        }
1343

    
1344

    
1345
        protected boolean fireBeforeModifyRow(IRow feat, int index, int sourceType) {
1346
                Cancel cancel = new Cancel();
1347
                String fid=null;
1348
                try {
1349
                        fid = getRow(index).getID();
1350
                } catch (DriverIOException e) {
1351
                        e.printStackTrace();
1352
                } catch (IOException e) {
1353
                        e.printStackTrace();
1354
                }
1355
                BeforeRowEditEvent event = new BeforeRowEditEvent(this, fid,
1356
                                EditionEvent.CHANGE_TYPE_MODIFY, cancel, sourceType);
1357
                for (int i = 0; i < editionListeners.size(); i++) {
1358
                        IEditionListener listener = (IEditionListener) editionListeners
1359
                                        .get(i);
1360
                        listener.beforeRowEditEvent(feat, event);
1361
                        if (cancel.isCanceled())
1362
                                return true;
1363
                }
1364
                return false;
1365
        }
1366

    
1367
        protected void fireAfterModifyRow(int index, int sourceType) {
1368
                AfterRowEditEvent event = new AfterRowEditEvent(this, index,
1369
                                EditionEvent.CHANGE_TYPE_MODIFY, sourceType);
1370
                if (complex){
1371
                        rowEvents.add(event);
1372
                        return;
1373
                }
1374
                for (int i = 0; i < editionListeners.size(); i++) {
1375
                        IEditionListener listener = (IEditionListener) editionListeners
1376
                                        .get(i);
1377
                        listener.afterRowEditEvent(null, event);
1378
                }
1379

    
1380
        }
1381

    
1382
        protected void fireStartEditionEvent(int sourceType) {
1383
                EditionEvent ev = new EditionEvent(this, EditionEvent.START_EDITION,
1384
                                sourceType);
1385
                for (int i = 0; i < editionListeners.size(); i++) {
1386
                        IEditionListener listener = (IEditionListener) editionListeners
1387
                                        .get(i);
1388
                        listener.processEvent(ev);
1389
                }
1390

    
1391
        }
1392

    
1393
        protected void fireStopEditionEvent(int sourceType) {
1394
                EditionEvent ev = new EditionEvent(this, EditionEvent.STOP_EDITION,
1395
                                sourceType);
1396
                for (int i = 0; i < editionListeners.size(); i++) {
1397
                        IEditionListener listener = (IEditionListener) editionListeners
1398
                                        .get(i);
1399
                        listener.processEvent(ev);
1400
                }
1401

    
1402
        }
1403

    
1404
        protected void fireCancelEditionEvent(int sourceType) {
1405
                EditionEvent ev = new EditionEvent(this, EditionEvent.CANCEL_EDITION,
1406
                                sourceType);
1407
                for (int i = 0; i < editionListeners.size(); i++) {
1408
                        IEditionListener listener = (IEditionListener) editionListeners
1409
                                        .get(i);
1410
                        listener.processEvent(ev);
1411
                }
1412

    
1413
        }
1414

    
1415
        public void addEditionListener(IEditionListener listener) {
1416
                if (!editionListeners.contains(listener))
1417
                        editionListeners.add(listener);
1418
        }
1419

    
1420
        public void removeEditionListener(IEditionListener listener) {
1421
                editionListeners.remove(listener);
1422
        }
1423

    
1424
        public IWriter getWriter() {
1425
                return writer;
1426
        }
1427

    
1428
        protected void setWriter(IWriter writer) {
1429
                this.writer = writer;
1430

    
1431
        }
1432
        /*
1433
         * azabala: esto funciona para todos los drivers gdbms
1434
         * salvo para MySQL, que necesita que el ITableDefinition
1435
         * contenga el nombre de la tabla (y por tanto requiere
1436
         * DBLayerDefinition-en realidad hace falta DBTableDefinition)
1437
         * TODO REVISAR LA ARQUITECTURA DE ESTO
1438
         *
1439
         * */
1440
        public ITableDefinition getTableDefinition() throws DriverLoadException,
1441
                        DriverException {
1442
                Driver originalDriver = getOriginalDriver();
1443
//                if(! (originalDriver instanceof AlphanumericDBDriver)){
1444
                        TableDefinition tableDef = new TableDefinition();
1445
                        tableDef.setFieldsDesc(getRecordset().getFieldsDescription());
1446
                        tableDef.setName(getRecordset().getSourceInfo().name);
1447
                        return tableDef;
1448
//                }else{
1449
//                        AlphanumericDBDriver dbDriver = (AlphanumericDBDriver)originalDriver;
1450
//                        return dbDriver.getTableDefinition();
1451
//
1452
//                }
1453

    
1454

    
1455
        }
1456

    
1457
        public void validateRow(IRow row,int sourceType) throws EditionException {
1458
                for (int i = 0; i < rules.size(); i++) {
1459
                        IRule rule = (IRule) rules.get(i);
1460
                        boolean bAux = rule.validate(row,sourceType);
1461
                        if (bAux == false) {
1462
                                EditionException ex = new EditionException(
1463
                                                "NOT follow the rule: " + rule.getDescription());
1464
                                // TODO: Lanzar una RuleException con datos como el registro
1465
                                // que no cumple, la regla que no lo ha cumplido, etc.
1466
                                throw ex;
1467
                        }
1468
                }
1469
        }
1470

    
1471
        public ArrayList getRules() {
1472
                return rules;
1473
        }
1474

    
1475
        public void setRules(ArrayList rules) {
1476
                this.rules = rules;
1477
        }
1478

    
1479
        private void clean() throws IOException, DriverException {
1480
                expansionFile.close();
1481
                relations.clear();
1482
                numAdd = 0;
1483
                delRows.clear();
1484
                // TODO: Es muy probable que necesitemos un reload de los datasources, al
1485
                // igual que lo tenemos en las capas. Por ahora, basta con retocar
1486
                // listInternalFields, pero casi seguro que lo correcto ser?a hacer un
1487
                // reload completo.
1488
                initalizeFields(ods);
1489

    
1490
//                listInternalFields.clear();
1491
//                listInternalFields.add(actualFields);
1492
        }
1493

    
1494
        /*
1495
         * (non-Javadoc)
1496
         *
1497
         * @see com.iver.cit.gvsig.fmap.edition.IEditableSource#getFieldManager()
1498
         */
1499
        public IFieldManager getFieldManager() {
1500
                if (ods.getDriver() instanceof IWriteable)
1501
                {
1502
                        IWriter writer = ((IWriteable)ods.getDriver()).getWriter();
1503
                        if ((writer != null) && (writer instanceof IFieldManager))
1504
                        {
1505
                                IFieldManager fldManager = (IFieldManager) writer;
1506
                                return fldManager;
1507
                        }
1508
                }
1509
                return null;
1510
        }
1511

    
1512
        /**
1513
         * Tiene en cuenta los campos actuales para formatear una row con ellos. Le
1514
         * pasamos los campos que hab?a en el momento en que se cre? esa row.
1515
         *
1516
         * @param edRow
1517
         * @param indexInternalFields
1518
         * @return
1519
         */
1520
        public IRowEdited createExternalRow(IRowEdited edRow,
1521
                        int indexInternalFields) {
1522

    
1523
                // para acelerar
1524
                if (bFieldsHasBeenChanged == false)
1525
                        return edRow;
1526

    
1527
                Value[] att = edRow.getAttributes();
1528
                TreeMap ancientFields = (TreeMap) listInternalFields
1529
                                .get(indexInternalFields);
1530
                Value[] newAtt = new Value[actualFields.size()];
1531
                Collection aux = actualFields.values();
1532
                Iterator it = aux.iterator();
1533
                int i = 0;
1534
                Value val = null;
1535
                while (it.hasNext()) {
1536
                        // Para cada campo de los actuales, miramos si ya estaba cuando
1537
                        // el registro estaba guardado.
1538
                        // Si estaba, cogemos el valor de ese campo en el registro
1539
                        // guardado. Si no estaba, ha sido a?adido despu?s y ponemos
1540
                        // su valor por defecto.
1541
                        // Nota importante: fieldIndex es el ?ndice del campo cuando
1542
                        // se guard?. NO es el ?ndice actual dentro de actualFields.
1543
                        // Se usa SOLO para recuperar el valor de los atributos
1544
                        // antiguos. Por eso no nos preocupamos de mantener actuallizados
1545
                        // el resto de campos cuando se borra o a?ade un nuevo campo.
1546
                        InternalField fld = (InternalField) it.next();
1547
                        // System.err.println("fld = " + fld.getFieldDesc().getFieldAlias() +  " id=" + fld.getFieldId());
1548
                        if (ancientFields.containsKey(fld.getFieldId())) {
1549
                                InternalField ancientField = (InternalField) ancientFields
1550
                                                .get(fld.getFieldId());
1551
                                val = att[ancientField.getFieldIndex()];
1552
                                // val = att[ancientField.getFieldId().intValue()];
1553
                                // System.out.println("fld: " + fld.getFieldDesc().getFieldAlias() + " ancient:" + " val" + val);
1554
                        } else
1555
                                val = fld.getFieldDesc().getDefaultValue();
1556
                        newAtt[i++] = val;
1557
                }
1558
                IRowEdited newRow = (IRowEdited) edRow.cloneRow();
1559
                newRow.setAttributes(newAtt);
1560
                return newRow;
1561
        }
1562

    
1563
        public void removeField(String fieldName) throws EditionException {
1564

    
1565
                InternalField fld = findFieldByName(fieldName);
1566
                if (fld == null)
1567
                        throw new EditionException("Field " + fieldName + " not found when removing field");
1568
                Command command = new RemoveFieldCommand(this, fld);
1569
                if (complex) {
1570
                        commands.add(command);
1571
                } else {
1572
                        cr.pushCommand(command);
1573
                }
1574
                doRemoveField(fld);
1575

    
1576
        }
1577

    
1578
        private InternalField findFieldByName(String fieldName) {
1579
                Collection aux = actualFields.values();
1580
                Iterator it = aux.iterator();
1581
                while (it.hasNext()) {
1582
                        InternalField fld = (InternalField) it.next();
1583
                        if (fld.getFieldDesc().getFieldAlias().compareToIgnoreCase(fieldName) == 0)
1584
                                return fld;
1585
                }
1586

    
1587
                return null;
1588
        }
1589

    
1590
        public void undoRemoveField(InternalField field) throws EditionException {
1591
                // field.setDeleted(false);
1592
//                field.setFieldIndex(actualFields.size());
1593
                actualFields.put(field.getFieldId(), field);
1594
                fieldsChanged();
1595
                fireAfterFieldAdded(field.getFieldDesc());
1596
        }
1597

    
1598
        public void doRemoveField(InternalField field) throws EditionException {
1599
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1600
                if (cancel) return;
1601
                actualFields.remove(field.getFieldId());
1602
                fieldsChanged();
1603
                fireAfterFieldRemoved(field.getFieldDesc());
1604
        }
1605

    
1606
        public void renameField(String antName, String newName) throws EditionException {
1607

    
1608
                InternalField fld = findFieldByName(antName);
1609
                Command command = new RenameFieldCommand(this, fld, newName);
1610
                if (complex) {
1611
                        commands.add(command);
1612
                } else {
1613
                        cr.pushCommand(command);
1614
                }
1615
                doRenameField(fld, newName);
1616

    
1617
        }
1618

    
1619
        public void undoRenameField(InternalField field, String antName) throws EditionException  {
1620
                field.getFieldDesc().setFieldAlias(antName);
1621
                fieldsChanged();
1622
                fireAfterFieldModified(field.getFieldDesc());
1623

    
1624
        }
1625

    
1626
        public void doRenameField(InternalField field, String newName) throws EditionException  {
1627
                field.getFieldDesc().setFieldAlias(newName);
1628
                fieldsChanged();
1629
                fireAfterFieldModified(field.getFieldDesc());
1630

    
1631
        }
1632

    
1633

    
1634
        public void addField(FieldDescription field) throws EditionException {
1635

    
1636
                InternalField fld = new InternalField(field, InternalField.ADDED, new Integer(listFields.size()));
1637
                Command command = new AddFieldCommand(this, fld);
1638
                if (complex) {
1639
                        commands.add(command);
1640
                } else {
1641
                        cr.pushCommand(command);
1642
                }
1643
                listFields.add(fld);
1644
                doAddField(fld);
1645

    
1646
        }
1647

    
1648
        public void undoAddField(InternalField field) throws EditionException {
1649
                boolean cancel = fireBeforeRemoveField(field.getFieldDesc());
1650
                if (cancel)
1651
                        return;
1652

    
1653
                // field.setDeleted(true);
1654
                actualFields.remove(field.getFieldId());
1655
                fieldsChanged();
1656
                fireAfterFieldRemoved(field.getFieldDesc());
1657

    
1658
        }
1659

    
1660
        public int doAddField(InternalField field) throws EditionException {
1661
                boolean cancel;
1662
                cancel = fireBeforeFieldAdded(field.getFieldDesc());
1663
                if (cancel)
1664
                        return -1;
1665

    
1666
                // field.setDeleted(false);
1667
//                field.setFieldIndex(actualFields.size());
1668
                actualFields.put(field.getFieldId(), field);
1669
                fieldsChanged();
1670
                fireAfterFieldAdded(field.getFieldDesc());
1671
//                return field.getFieldIndex();
1672
                return field.getFieldId().intValue();
1673
        }
1674

    
1675
        public Driver getOriginalDriver()
1676
        {
1677
                return ods.getDriver();
1678
        }
1679

    
1680
        /**
1681
         * Use it to be sure the recordset will have the right fields. It forces a new SelectableDataSource
1682
         * to be created next time it is needed
1683
         */
1684
        public void cleanSelectableDatasource() {
1685
                ds = null;
1686
        }
1687

    
1688
        public FieldDescription[] getFieldsDescription() {
1689
                return (FieldDescription[]) fastAccessFields.toArray(new FieldDescription[0]);
1690
        }
1691

    
1692

    
1693
//        private InternalField getInternalFieldByIndex(int fieldId)
1694
//        {
1695
//                for (Iterator iter = actualFields.values().iterator(); iter.hasNext();) {
1696
//                        InternalField fld = (InternalField) iter.next();
1697
//                        if (fld.getFieldIndex() == fieldId)
1698
//                                return fld;
1699
//                }
1700
//                return null;
1701
//        }
1702

    
1703
}