Statistics
| Revision:

svn-gvsig-desktop / branches / pilotoDWG / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / DefaultEditableFeatureSource.java @ 1595

History | View | Annotate | Download (14.9 KB)

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

    
3
import java.awt.Image;
4
import java.awt.geom.Rectangle2D;
5
import java.io.IOException;
6
import java.util.BitSet;
7
import java.util.HashMap;
8
import java.util.List;
9

    
10
import com.iver.cit.gvsig.fmap.core.IGeometry;
11
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
12
import com.iver.cit.gvsig.fmap.layers.FBitSet;
13
import com.vividsolutions.jts.geom.Envelope;
14
import com.vividsolutions.jts.index.quadtree.Quadtree;
15

    
16

    
17
/**
18
 * DOCUMENT ME!
19
 *
20
 * @author Vicente Caballero Navarro
21
 */
22
public class DefaultEditableFeatureSource implements EditableFeatureSource {
23
        private ExpansionFile expansionFile;
24
        private OriginalFeatureAdapter ofa;
25
        private BitSet delgeometries = new BitSet();
26
        private HashMap relations = new HashMap();
27
        private int numAdd = 0;
28
        private Quadtree index;
29
        private Image selectionImage;
30
        private CommandRecord cr;
31
        private FBitSet fbitset;
32
        private boolean complex=false;
33
        private CommandCollection commands=null;
34
        /**
35
         * Crea un nuevo AbstractEditableFeatureSource.
36
         *
37
         * @param ef DOCUMENT ME!
38
         * @param ofa DOCUMENT ME!
39
         */
40
        public DefaultEditableFeatureSource(ExpansionFile ef,
41
                OriginalFeatureAdapter ofa,FBitSet bitset) {
42
                expansionFile = ef;
43
                this.ofa = ofa;
44
                this.cr= new MemoryCommandRecord();
45
                fbitset=bitset;
46
        }
47

    
48
        /**
49
         * M?todo invocado cuando se comienza la edici?n, para poner en marcha las
50
         * estructuras de datos necesarias para la misma, notificar al servidor en
51
         * protocolos en los que sea necesario, ...
52
         *
53
         * @throws EditionException
54
         * @throws IOException
55
         * @throws DriverIOException
56
         */
57
        public void startEdition() throws EditionException {
58
                ofa.startEdition();
59
                index = new Quadtree();
60

    
61
                        try {
62
                                for (int i = 0; i < getGeometryCount(); i++) {
63
                                        IGeometry g = getGeometry(i);
64
                                        Rectangle2D r = g.getBounds2D();
65
                                        Envelope e = new Envelope(r.getX(), r.getX() + r.getWidth(),
66
                                                        r.getY(), r.getY() + r.getHeight());
67
                                        index.insert(e, new Integer(i));
68
                                }
69
                        } catch (DriverIOException e) {
70
                                throw new EditionException(e);
71
                        } catch (IOException e) {
72
                                throw new EditionException(e);
73
                        }
74
                System.err.println("Se han metido en el ?ndice " +
75
                        index.queryAll().size() + " geometr?as");
76
        }
77

    
78
        /**
79
         * Invocado cuando termina la edici?n. En funci?n de la clase concreta que
80
         * implemente este m?todo se generar? el fichero con los resultados de la
81
         * edici?n, se realizar? una transacci?n a la base de datos, etc.
82
         *
83
         * @throws EditionException
84
         */
85
        public void stopEdition() throws EditionException {
86
                ofa.stopEdition();
87
        }
88

    
89
        /**
90
         * Devuelve el n?mero de geometrias que hay actualmente en edici?n.
91
         *
92
         * @return N?mero de geometr?as.
93
         *
94
         * @throws DriverIOException
95
         */
96
        public int getGeometryCount() throws DriverIOException {
97
                return ofa.getGeometryCount() + numAdd; //expansionFile.getGeometryCount() - relations.size();
98
        }
99

    
100
        /**
101
         * Si el ?ndice se corresponde a una geometria de las originales de la capa
102
         * en edici?n y no ha sido modificada ni eliminada devuelve la geometria
103
         * original. Si ha sido modificada debera de buscar en el fichero de
104
         * expansi?n y si ha sido eliminada debera devolver null
105
         *
106
         * @param index ?ndice de la geometr?a.
107
         *
108
         * @return Geometr?a.
109
         *
110
         * @throws IOException
111
         * @throws DriverIOException
112
         */
113
        public synchronized IGeometry getGeometry(int index)
114
                throws IOException, DriverIOException {
115
                Integer integer = new Integer(index);
116

    
117
                if (!relations.containsKey(integer)) {
118
                        if (delgeometries.get(index)) {
119
                                return null;
120
                        } else {
121
                                return ofa.getGeometry(index);
122
                        }
123
                } else {
124
                        int num = ((Integer) relations.get(integer)).intValue();
125

    
126
                        return expansionFile.getGeometry(num);
127
                }
128
        }
129

    
130
        /**
131
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
132
         * en una tabla asociada.
133
         *
134
         * @param g geometr?a a guardar.
135
         *
136
         * @throws DriverIOException
137
         * @throws IOException
138
         */
139
        public void addGeometry(IGeometry g) throws DriverIOException, IOException {
140
                int virtualIndex=doAddGeometry(g);
141
                if (complex){
142
                        commands.add(new AddGeometryCommand(this,g,virtualIndex));
143
                }else{
144
                        cr.pushCommand(new AddGeometryCommand(this,g,virtualIndex));
145
                }
146
        }
147

    
148
        /**
149
         * Elimina una geometria. Si es una geometr?a original de la capa en
150
         * edici?n se marca como eliminada (haya sido modificada o no). Si es una
151
         * geometr?a a?adida posteriormente se invalida en el fichero de
152
         * expansi?n, para que una futura compactaci?n termine con ella.
153
         *
154
         * @param index ?ndice de la geometr?a.
155
         *
156
         * @throws DriverIOException
157
         * @throws IOException
158
         */
159
        public void removeGeometry(int index) throws DriverIOException, IOException {
160
                if (complex){
161
                        commands.add(new RemoveGeometryCommand(this,index));
162
                }else{
163
                        cr.pushCommand(new RemoveGeometryCommand(this,index));
164
                }
165
                doRemoveGeometry(index);
166
        }
167

    
168
        /**
169
         * Si se intenta modificar una geometr?a original de la capa en edici?n se
170
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
171
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
172
         * fichero de expansi?n (por ser nueva o original pero modificada) se
173
         * invoca el m?todo modifyGeometry y se actualiza el ?ndice de la
174
         * geometria en el fichero.
175
         *
176
         * @param index DOCUMENT ME!
177
         * @param g DOCUMENT ME!
178
         *
179
         * @throws IOException
180
         * @throws DriverIOException
181
         */
182
        public void modifyGeometry(int index, IGeometry g)
183
                throws IOException, DriverIOException {
184
                int pos=doModifyGeometry(index,g);
185
                if (complex){
186
                        commands.add(new ModifyGeometryCommand(this,index,pos,g));
187
                }else{
188
                        cr.pushCommand(new ModifyGeometryCommand(this,index,pos,g));
189
                }
190
        }
191

    
192
        /**
193
         * DOCUMENT ME!
194
         *
195
         * @return DOCUMENT ME!
196
         */
197
        public OriginalFeatureAdapter getOriginalFeatureAdapter() {
198
                return ofa;
199
        }
200

    
201
        /**
202
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#compact()
203
         */
204
        public void compact() {
205
                expansionFile.compact(relations);
206
        }
207

    
208
        /**
209
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#getGeometriesIndexes(com.vividsolutions.jts.geom.Envelope)
210
         */
211
        public int[] getGeometriesIndexes(Rectangle2D r) {
212
                Envelope e = new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
213
                                r.getY() + r.getHeight());
214
                List l = index.query(e);
215
                int[] indexes = new int[l.size()];
216

    
217
                for (int index = 0; index < l.size(); index++) {
218
                        Integer i = (Integer) l.get(index);
219
                        indexes[index] = i.intValue();
220
                }
221

    
222
                return indexes;
223
        }
224

    
225
        /**
226
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#setImage(java.awt.Image)
227
         */
228
        public void setImage(Image i) {
229
                selectionImage = i;
230
        }
231

    
232
        /**
233
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#getImage()
234
         */
235
        public Image getImage() {
236
                return selectionImage;
237
        }
238

    
239
        /**
240
         * Se elimina del final del fichero de expansi?n poniendo el puntero de
241
         * escritura apuntando al final de la pen?ltima geometr?a. Deber? quitar
242
         * la relaci?n del mapa de relaciones
243
         *
244
         * @param index ?ndice de la geometr?a que se a?adi?
245
         * @throws IOException
246
         * @throws DriverIOException
247
         */
248
        public void undoAddGeometry(int index) throws DriverIOException, IOException {
249
                //doRemoveGeometry(index);
250
                IGeometry g=getGeometry(index);
251
                Rectangle2D r=g.getBounds2D();
252
                this.index.remove(new Envelope(r.getX(), r.getX() + r.getWidth(),
253
                                r.getY(), r.getY() + r.getHeight()), new Integer(index));
254
                 
255
        expansionFile.deleteLastGeometry();
256
        relations.remove(new Integer(index));
257
        numAdd--;
258
                
259
        }
260

    
261
        /**
262
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
263
         * en el fichero original
264
         *
265
         * @param index DOCUMENT ME!
266
         * @throws DriverIOException
267
         * @throws IOException
268
         */
269
        public void undoRemoveGeometry(int index) throws IOException, DriverIOException {
270
                if (relations.containsKey(new Integer(index))){
271
                expansionFile.validateGeometry(((Integer)relations.get(new Integer(index))).intValue());
272
                }else{
273
                        delgeometries.set(index,false);
274
                }
275
                IGeometry g=null;
276
                        g = getGeometry(index);
277
                Rectangle2D r = g.getBounds2D();
278
                this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
279
                                r.getY() + r.getHeight()), new Integer(index));
280
                
281
        }
282

    
283
        /**
284
         * Actualiza en el mapa de ?ndices, la posici?n en la que estaba la
285
         * geometr?a antes de ser modificada. Se marca como v?lida, en caso de que
286
         * fuera una modificaci?n de una geometr?a que estuviese en el fichero de
287
         * expansi?n antes de ser modificada y se pone el puntero de escritura del
288
         * expansion file a justo despues de la penultima geometr?a
289
         *
290
         * @param geometryIndex ?ndice de la geometr?a que se quiere deshacer su
291
         *                   movimiento
292
         * @param previousExpansionFileIndex ?ndice que ten?a antes la geometr?a en
293
         *                   el expansionFile. Si vale -1 quiere decir que es una
294
         *                   modificaci?n de una geometr?a original y por tanto no hay que
295
         *                   actualizar el mapa de indices sino eliminar su entrada.
296
         * @throws DriverIOException
297
         * @throws IOException
298
         */
299
        public void undoModifyGeometry(int geometryIndex,
300
                int previousExpansionFileIndex) throws IOException, DriverIOException {
301
                if (previousExpansionFileIndex==-1){
302
                        //eliminar geometr?a del expansion file.
303
                        //expansionFile.invalidateGeometry(geometryIndex);
304
                        IGeometry g=null;
305
                                g = getGeometry(geometryIndex);
306
                        Rectangle2D r=g.getBounds2D();
307
                        this.index.remove(new Envelope(r.getX(), r.getX() + r.getWidth(),
308
                                        r.getY(), r.getY() + r.getHeight()), new Integer(geometryIndex));
309
                         
310
                expansionFile.deleteLastGeometry();
311
                relations.remove(new Integer(geometryIndex));
312
                numAdd--;
313
                }else{
314
                        IGeometry g=null;
315
                                g = getGeometry(geometryIndex);
316
                        Rectangle2D r=g.getBounds2D();
317
                        this.index.remove(new Envelope(r.getX(), r.getX() + r.getWidth(),
318
                                        r.getY(), r.getY() + r.getHeight()), new Integer(geometryIndex));
319
                        
320
                        Integer integer=new Integer(geometryIndex);
321
                        relations.put(new Integer(geometryIndex),new Integer(previousExpansionFileIndex));
322
                        expansionFile.validateGeometry(previousExpansionFileIndex);
323
                                g = getGeometry(geometryIndex);
324
                        r=g.getBounds2D();
325
                        this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(),
326
                                        r.getY(), r.getY() + r.getHeight()), new Integer(geometryIndex));
327
                
328
                }
329
                
330
        }
331

    
332
        /**
333
         * A?ade una geometria al fichero de expansi?n y guarda la correspondencia
334
         * en una tabla asociada.
335
         *
336
         * @param g geometr?a a guardar.
337
         *
338
         * @throws DriverIOException
339
         * @throws IOException
340
         */
341
        public int doAddGeometry(IGeometry g) throws DriverIOException, IOException {
342
                int virtualIndex = ofa.getGeometryCount() + numAdd;
343
                int pos = expansionFile.addGeometry(g);
344
                relations.put(new Integer(virtualIndex), new Integer(pos));
345
                numAdd++;
346

    
347
                Rectangle2D r = g.getBounds2D();
348
                index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
349
                                r.getY() + r.getHeight()), new Integer(virtualIndex));
350

    
351
                //                System.err.println(this.index.size());
352
                return virtualIndex;
353
        }
354

    
355
        /**
356
         * Elimina una geometria. Si es una geometr?a original de la capa en
357
         * edici?n se marca como eliminada (haya sido modificada o no). Si es una
358
         * geometr?a a?adida posteriormente se invalida en el fichero de
359
         * expansi?n, para que una futura compactaci?n termine con ella.
360
         *
361
         * @param index ?ndice de la geometr?a.
362
         *
363
         * @throws DriverIOException
364
         * @throws IOException
365
         */
366
        public void doRemoveGeometry(int index) throws DriverIOException, IOException {
367
                Integer integer = new Integer(index);
368

    
369
                IGeometry g = null;
370

    
371
                if (!relations.containsKey(integer)) {
372
                        delgeometries.set(index, true);
373
                        g = ofa.getGeometry(index);
374
                } else {
375
                        int num = ((Integer) relations.get(integer)).intValue();
376
                        g = expansionFile.getGeometry(num);
377
                        expansionFile.invalidateGeometry(num);
378
                }
379
                 if (g != null){
380
                Rectangle2D r = g.getBounds2D();
381
                this.index.remove(new Envelope(r.getX(), r.getX() + r.getWidth(),
382
                                r.getY(), r.getY() + r.getHeight()), new Integer(index));
383
                 }
384
                //                System.err.println(this.index.size());
385
                
386
        }
387

    
388
        /**
389
         * Si se intenta modificar una geometr?a original de la capa en edici?n se
390
         * a?ade al fichero de expansi?n y se registra la posici?n en la que se
391
         * a?adi?. Si se intenta modificar una geometria que se encuentra en el
392
         * fichero de expansi?n (por ser nueva o original pero modificada) se
393
         * invoca el m?todo modifyGeometry y se actualiza el ?ndice de la
394
         * geometria en el fichero.
395
         *
396
         * @param index DOCUMENT ME!
397
         * @param g DOCUMENT ME!
398
         *
399
         * @throws IOException
400
         * @throws DriverIOException
401
         */
402
        public int doModifyGeometry(int index, IGeometry g)
403
                throws IOException, DriverIOException {
404
                int pos=0;
405
                Integer integer = new Integer(index);
406

    
407
                IGeometry gAnt = null;
408

    
409
                if (!relations.containsKey(integer)) {
410
                        int expansionIndex = expansionFile.addGeometry(g);
411
                        relations.put(integer, new Integer(expansionIndex));
412

    
413
                        //Se actualiza el ?ndice espacial
414
                        gAnt = ofa.getGeometry(index);
415

    
416
                        Rectangle2D rAnt = gAnt.getBounds2D();
417
                        Rectangle2D r = g.getBounds2D();
418
                        this.index.remove(new Envelope(rAnt.getX(),
419
                                        rAnt.getX() + rAnt.getWidth(), rAnt.getY(),
420
                                        rAnt.getY() + rAnt.getHeight()), new Integer(index));
421
                        this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(),
422
                                        r.getY(), r.getY() + r.getHeight()), new Integer(index));
423
                        pos=expansionIndex;
424
                } else {
425
                        int num = ((Integer) relations.get(integer)).intValue();
426
                        pos=num;
427
                        gAnt = expansionFile.getGeometry(num);
428
                        num = expansionFile.modifyGeometry(num, g);
429
                        relations.put(integer, new Integer(num));
430

    
431
                        //Se modifica el ?ndice espacial
432
                        Rectangle2D rAnt = gAnt.getBounds2D();
433
                        Rectangle2D r = g.getBounds2D();
434
                        this.index.remove(new Envelope(rAnt.getX(),
435
                                        rAnt.getX() + rAnt.getWidth(), rAnt.getY(),
436
                                        rAnt.getY() + rAnt.getHeight()), new Integer(index));
437
                        this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(),
438
                                        r.getY(), r.getY() + r.getHeight()), new Integer(index));
439
                
440
                }
441

    
442
                //                System.err.println(this.index.size());
443
                return pos;
444
        }
445

    
446
        /**
447
         * @throws IOException
448
         * @throws DriverIOException
449
         * @throws IOException
450
         * @throws DriverIOException
451
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#undo()
452
         */
453
        public void undo() throws DriverIOException, IOException{
454
                fbitset.clear();
455
                if (moreUndoCommands())
456
                cr.undoCommand();
457
        }
458
        /**
459
         * @throws IOException
460
         * @throws DriverIOException
461
         * @throws IOException
462
         * @throws DriverIOException
463
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#redo()
464
         */
465
        public void redo() throws DriverIOException, IOException{
466
                fbitset.clear();
467
                if (moreRedoCommands())
468
                cr.redoCommand();
469
        }
470
        
471

    
472
        /**
473
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#moreUndoCommands()
474
         */
475
        public boolean moreUndoCommands() {
476
                return cr.moreUndoCommands();
477
        }
478

    
479
        /**
480
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#moreRedoCommands()
481
         */
482
        public boolean moreRedoCommands() {
483
                return cr.moreRedoCommands();
484
        }
485

    
486
        /**
487
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#startComplexGeometry()
488
         */
489
        public void startComplexGeometry() {
490
                complex=true;
491
                commands=new CommandCollection();
492
        }
493

    
494
        /**
495
         * @throws DriverIOException
496
         * @throws IOException
497
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#endComplexGeometry()
498
         */
499
        public void endComplexGeometry() throws IOException, DriverIOException {
500
                cr.pushCommand(commands);
501
                complex=false;
502
        }
503
        
504
}