Statistics
| Revision:

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

History | View | Annotate | Download (14.2 KB)

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

    
3
import com.iver.cit.gvsig.fmap.core.IGeometry;
4
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
5
import com.iver.cit.gvsig.fmap.layers.FBitSet;
6
import com.iver.cit.gvsig.fmap.layers.SelectionSupport;
7

    
8
import com.vividsolutions.jts.geom.Envelope;
9
import com.vividsolutions.jts.index.quadtree.Quadtree;
10

    
11
import java.awt.Image;
12
import java.awt.geom.Rectangle2D;
13

    
14
import java.io.IOException;
15

    
16
import java.util.BitSet;
17
import java.util.HashMap;
18
import java.util.List;
19

    
20

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

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

    
60
                index = new Quadtree();
61

    
62
                try {
63
                        for (int i = 0; i < getGeometryCount(); i++) {
64
                                IGeometry g = getGeometry(i);
65
                                Rectangle2D r = g.getBounds2D();
66
                                Envelope e = new Envelope(r.getX(), r.getX() + r.getWidth(),
67
                                                r.getY(), r.getY() + r.getHeight());
68
                                index.insert(e, new Integer(i));
69
                        }
70
                } catch (DriverIOException e) {
71
                        e.printStackTrace();
72
                } catch (IOException e) {
73
                        e.printStackTrace();
74
                }
75

    
76
                System.err.println("Se han metido en el ?ndice " +
77
                        index.queryAll().size() + " geometr?as");
78
        }
79

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

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

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

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

    
128
                        return expansionFile.getGeometry(num);
129
                }
130
        }
131

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

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

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

    
183
        /**
184
         * DOCUMENT ME!
185
         *
186
         * @return DOCUMENT ME!
187
         */
188
        public OriginalFeatureAdapter getOriginalFeatureAdapter() {
189
                return ofa;
190
        }
191

    
192
        /**
193
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#compact()
194
         */
195
        public void compact() {
196
                expansionFile.compact(relations);
197
        }
198

    
199
        /**
200
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#getGeometriesIndexes(com.vividsolutions.jts.geom.Envelope)
201
         */
202
        public int[] getGeometriesIndexes(Rectangle2D r) {
203
                Envelope e = new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
204
                                r.getY() + r.getHeight());
205
                List l = index.query(e);
206
                int[] indexes = new int[l.size()];
207

    
208
                for (int index = 0; index < l.size(); index++) {
209
                        Integer i = (Integer) l.get(index);
210
                        indexes[index] = i.intValue();
211
                }
212

    
213
                return indexes;
214
        }
215

    
216
        /**
217
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#setImage(java.awt.Image)
218
         */
219
        public void setImage(Image i) {
220
                selectionImage = i;
221
        }
222

    
223
        /**
224
         * @see com.iver.cit.gvsig.fmap.edition.EditableFeatureSource#getImage()
225
         */
226
        public Image getImage() {
227
                return selectionImage;
228
        }
229

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

    
252
        /**
253
         * Se desmarca como invalidada en el fichero de expansion o como eliminada
254
         * en el fichero original
255
         *
256
         * @param index DOCUMENT ME!
257
         */
258
        public void undoRemoveGeometry(int index) {
259
                expansionFile.validateGeometry(((Integer)relations.get(new Integer(index))).intValue());
260
                delgeometries.set(index,false);
261
                IGeometry g=null;
262
                try {
263
                        g = getGeometry(index);
264
                } catch (IOException e) {
265
                        e.printStackTrace();
266
                } catch (DriverIOException e) {
267
                        e.printStackTrace();
268
                }
269
                Rectangle2D r = g.getBounds2D();
270
                this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
271
                                r.getY() + r.getHeight()), new Integer(index));
272
        }
273

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

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

    
354
                Rectangle2D r = g.getBounds2D();
355
                index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
356
                                r.getY() + r.getHeight()), new Integer(virtualIndex));
357

    
358
                //                System.err.println(this.index.size());
359
                return virtualIndex;
360
        }
361

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

    
376
                IGeometry g = null;
377

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

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

    
414
                IGeometry gAnt = null;
415

    
416
                if (!relations.containsKey(integer)) {
417
                        int expansionIndex = expansionFile.addGeometry(g);
418
                        relations.put(integer, new Integer(expansionIndex));
419

    
420
                        //Se actualiza el ?ndice espacial
421
                        gAnt = ofa.getGeometry(index);
422

    
423
                        Rectangle2D rAnt = gAnt.getBounds2D();
424
                        Rectangle2D r = g.getBounds2D();
425
                        this.index.remove(new Envelope(rAnt.getX(),
426
                                        rAnt.getX() + rAnt.getWidth(), rAnt.getY(),
427
                                        rAnt.getY() + rAnt.getHeight()), new Integer(index));
428
                        this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(),
429
                                        r.getY(), r.getY() + r.getHeight()), new Integer(index));
430
                        pos=expansionIndex;
431
                } else {
432
                        int num = ((Integer) relations.get(integer)).intValue();
433
                        pos=num;
434
                        gAnt = expansionFile.getGeometry(num);
435
                        num = expansionFile.modifyGeometry(num, g);
436
                        relations.put(integer, new Integer(num));
437

    
438
                        //Se modifica el ?ndice espacial
439
                        Rectangle2D rAnt = gAnt.getBounds2D();
440
                        Rectangle2D r = g.getBounds2D();
441
                        this.index.remove(new Envelope(rAnt.getX(),
442
                                        rAnt.getX() + rAnt.getWidth(), rAnt.getY(),
443
                                        rAnt.getY() + rAnt.getHeight()), new Integer(index));
444
                        this.index.insert(new Envelope(r.getX(), r.getX() + r.getWidth(),
445
                                        r.getY(), r.getY() + r.getHeight()), new Integer(index));
446
                
447
                }
448

    
449
                //                System.err.println(this.index.size());
450
                return pos;
451
        }
452

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

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

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