Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_data / src / org / gvsig / fmap / data / feature / AbstractFeatureStore.java @ 23303

History | View | Annotate | Download (27.6 KB)

1
package org.gvsig.fmap.data.feature;
2

    
3
import java.lang.ref.Reference;
4
import java.util.ArrayList;
5
import java.util.Iterator;
6
import java.util.List;
7

    
8
import org.gvsig.fmap.data.CloseException;
9
import org.gvsig.fmap.data.DataCollection;
10
import org.gvsig.fmap.data.DataException;
11
import org.gvsig.fmap.data.DataManager;
12
import org.gvsig.fmap.data.DataStoreParameters;
13
import org.gvsig.fmap.data.InitializeException;
14
import org.gvsig.fmap.data.OpenException;
15
import org.gvsig.fmap.data.ReadException;
16
import org.gvsig.fmap.data.Resource;
17
import org.gvsig.fmap.data.ResourceNotification;
18
import org.gvsig.fmap.data.WriteException;
19
import org.gvsig.fmap.data.commands.Command;
20
import org.gvsig.fmap.data.commands.CommandsRecord;
21
import org.gvsig.fmap.data.commands.implementation.FeatureCommandsRecord;
22
import org.gvsig.fmap.data.feature.expansionadapter.ExpansionAdapter;
23
import org.gvsig.fmap.data.feature.expansionadapter.MemoryExpansionAdapter;
24
import org.gvsig.fmap.data.feature.expressionevaluator.AttributeValueEvaluator;
25
import org.gvsig.fmap.data.index.IndexException;
26
import org.gvsig.fmap.data.index.IndexStore;
27
import org.gvsig.fmap.data.index.spatial.PersistentSpatialIndex;
28
import org.gvsig.fmap.data.index.spatial.SpatialIndex;
29
import org.gvsig.fmap.data.index.spatial.SpatialIndexFactory;
30
import org.gvsig.fmap.data.index.spatial.SpatialIndexParameters;
31
import org.gvsig.fmap.data.operation.DataStoreOperationContext;
32
import org.gvsig.fmap.data.operation.DataStoreOperationException;
33
import org.gvsig.fmap.data.operation.DataStoreOperationNotSupportedException;
34
import org.gvsig.fmap.geom.Geometry;
35
import org.gvsig.fmap.geom.primitive.Envelope;
36
import org.gvsig.tools.exception.BaseException;
37
import org.gvsig.tools.observer.ComplexNotification;
38
import org.gvsig.tools.observer.DefaultObservable;
39
import org.gvsig.tools.observer.Observable;
40
import org.gvsig.tools.observer.Observer;
41

    
42
import com.iver.utiles.XMLEntity;
43
import com.iver.utiles.XMLException;
44

    
45

    
46
public abstract class AbstractFeatureStore implements FeatureStore {
47
        protected DataStoreParameters parameters = null;
48
        protected DataCollection selection;
49
        protected CommandsRecord commands;
50
        protected boolean alterMode = false;
51
//        protected ComplexObservable observable=new ComplexObservable();
52
        protected DataCollection locked;
53
        protected DefaultObservable observable=new DefaultObservable();
54
        protected FeatureManager featureManager;
55
        protected SpatialManager spatialManager;
56
        protected AttributeManager attributeManager;
57
        protected ArrayList resouceObservers = new ArrayList();
58
        protected FeatureType defaultFeatureType = null;
59
        protected Observer selectionObserver = null;
60
        protected IndexStore indexStore = null;
61

    
62

    
63
        public void init(DataStoreParameters parameters) throws InitializeException {
64
                if (this.parameters != null) {
65
                        throw new InitializeException("initialized two times", this
66
                                        .getName());
67
                }
68
                this.parameters = parameters;
69
        }
70

    
71
        public void init(DataStoreParameters parameters,Resource resource) throws InitializeException {
72
                if (this.parameters != null) {
73
                        throw new InitializeException("initialized two times", this
74
                                        .getName());
75
                }
76
                this.parameters = parameters;
77
                this.observeResource(resource);
78
        }
79

    
80
        public void setXMLEntity(XMLEntity xmlEntity) throws XMLException {
81
                DataManager manager = DataManager.getManager();
82

    
83
                XMLEntity paramsXML = xmlEntity.firstChild("type", "parameters");
84

    
85
                if (paramsXML == null) {
86
                        throw new XMLInitializeException("parameters not found", this
87
                                        .getName());
88
                }
89
                try {
90
                DataStoreParameters params = manager
91
                                        .createDataStoreParameters(paramsXML);
92
                this.init(params);
93
                } catch (InitializeException e) {
94
                        throw new XMLInitializeException("inititalize", e);
95
                }
96
                //TODO Selection and Lock persistence
97

    
98
        }
99

    
100
        public XMLEntity getXMLEntity() {
101
                XMLEntity xml = new XMLEntity();
102
                XMLEntity paramsXML = this.parameters.getXMLEntity();
103
                xml.putProperty("dataStoreName", this.getName());
104
                paramsXML.putProperty("type", "parameters");
105

    
106
                xml.addChild(paramsXML);
107

    
108
                //TODO Selection and Lock persistence... IndexParams???
109

    
110
                return xml;
111
        }
112

    
113

    
114

    
115

    
116
        protected final void observeResource(Resource resource){
117
                ResourceChangedObserver observer=new ResourceChangedObserver(this);
118
                resource.addObserver(observer);
119
                this.resouceObservers.add(observer);
120
        }
121

    
122
        protected final void clearResourceObservers() {
123
                this.resouceObservers.clear();
124
        }
125

    
126
        protected void initSpatialManager(){
127
                spatialManager=new SpatialManager();
128
        }
129

    
130
        protected void initAttributeManager() {
131
                ExpansionAdapter expansionAttributeAdapter=new MemoryExpansionAdapter();
132
                attributeManager=new AttributeManager(expansionAttributeAdapter,getDefaultFeatureType());
133

    
134
        }
135

    
136
        protected void initExpansionManager() {
137
                ExpansionAdapter expansionFeatureAdapter=new MemoryExpansionAdapter();
138
                featureManager=new FeatureManager(expansionFeatureAdapter);
139
        }
140

    
141
        public DataCollection getDataCollection() throws ReadException {
142
                return getDataCollection(this.getDefaultFeatureType(), null, null);
143
        }
144

    
145

    
146
        public DataCollection getDataCollection(String[] fields, String filter,
147
                        String order) throws ReadException {
148
                try {
149
                        return getDataCollection(this.getDefaultFeatureType().getSubFeatureType(fields), filter, order);
150
                } catch (DataException e) {
151
                        throw new ReadException(this.getName(), e);
152
                }
153
        }
154

    
155
        public void getDataCollection(Observer observer) {
156
                getDataCollection(this.getDefaultFeatureType(), null, null,observer);
157
        }
158

    
159
        public final void setSelection(DataCollection selection)
160
                        throws DataException {
161
                if (selection.equals(this.selection)) {
162
                        return;
163
                }
164
                if (!selection.isFromStore(this)){
165
                        throw new DataException("selection not form this store");
166
                }
167
                doSetSelection(selection);
168
                this.notifySelectionChange();
169
        }
170

    
171
        protected void doSetSelection(DataCollection selection) {
172
                this.unsetSelectionObserver();
173
                if (this.getSelection().getClass().isInstance(selection)) {
174
                        this.selection = selection;
175
                } else {
176
                        this.selection = null;
177
                        this.getSelection().addAll(selection);
178
                }
179
                this.setSelectionObserver();
180
        }
181

    
182
        protected void setSelectionObserver(){
183
                if (this.selection instanceof Observable) {
184
                        Observable obSelection = (Observable) this.selection;
185
                        if (this.selectionObserver == null){
186
                                this.selectionObserver=new SelectionObserver(this);
187
                        }
188
                        obSelection.addObserver(this.selectionObserver);
189
                }
190
        }
191

    
192
        protected void unsetSelectionObserver() {
193
                if (this.selection instanceof Observable) {
194
                        Observable obSelection = (Observable) this.selection;
195
                        obSelection.deleteObserver(this.selectionObserver);
196
                }
197
        }
198

    
199
        public DataCollection createSelection() {
200

    
201
                MemoryFeatureCollection selection = new MemoryFeatureCollection(this);
202
                return selection;
203
        }
204

    
205
        public DataCollection getSelection() {
206
                if( selection == null ){
207
                        this.selection = createSelection();
208
                        this.setSelectionObserver();
209
                }
210
                return selection;
211
        }
212

    
213
        public DataCollection createLocked() {
214
                MemoryFeatureCollection locked = new MemoryFeatureCollection(this);
215
                return locked;
216
        }
217

    
218
        public DataCollection getLocked() {
219
                if( locked == null ){
220
                        locked = createLocked();
221
                }
222
                return locked;
223
        }
224

    
225
        public final void setLocked(DataCollection locked) {
226
                this.observable.notifyObservers(this,
227
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_LOCKEDCHANGE)
228
                        );
229
                doLocked(locked);
230
                this.observable.notifyObservers(this,
231
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_LOCKEDCHANGE)
232
                        );
233

    
234
        }
235
        protected void doLocked(DataCollection locked) {
236
                this.locked = locked;
237

    
238
        }
239

    
240
        public boolean isLocked(FeatureID id) {
241
        return locked.contains(id);
242
    }
243

    
244
    public final boolean lock(FeatureID id) {
245
            this.observable.notifyObservers(this,
246
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_LOCKEDCHANGE)
247
                        );
248
                doLock(id);
249
            this.observable.notifyObservers(this,
250
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_LOCKEDCHANGE)
251
                        );
252
                return true;
253
    }
254

    
255

    
256
        protected void doLock(FeatureID id) {
257
                locked.add(id);
258
        }
259

    
260
        public final void startEditing() throws ReadException {
261
                if (!this.isEditable()) {
262
                        throw new ReadException("AbstractFeatureStore",
263
                                        new UnsupportedOperationException("Not editable"));
264
                }
265
                this.observable.notifyObservers(this,
266
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_STARTEDITING)
267
                        );
268
                doStartEditing();
269
                this.observable.notifyObservers(this,
270
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_STARTEDITING)
271
                        );
272

    
273
        }
274

    
275

    
276
        protected void doStartEditing() {
277
//                commands.clear();
278
                initExpansionManager();
279
                initSpatialManager();
280
                initAttributeManager();
281
                commands = new FeatureCommandsRecord(featureManager, spatialManager, attributeManager);
282

    
283

    
284
                alterMode = true;
285
        }
286

    
287
        public final void delete(FeatureAttributeDescriptor attributeDescriptor) {
288
                //FIXME Comporobar que el attribute viene del Fype de este store
289
                if( !alterMode ) {
290
                        throw new RuntimeException("alterMode is false");
291
                }
292
                this.observable.notifyObservers(this,
293
                                new DefaultAttributeStoreNotification(this,DefaultAttributeStoreNotification.BEFORE_DELETE_ATTRIBUTE,attributeDescriptor)
294
                        );
295
                doDelete(attributeDescriptor);
296
                this.observable.notifyObservers(this,
297
                                new DefaultAttributeStoreNotification(this,DefaultAttributeStoreNotification.AFTER_DELETE_ATTRIBUTE,attributeDescriptor)
298
                        );
299

    
300

    
301
        }
302

    
303
        protected void doDelete(FeatureAttributeDescriptor attributeDescriptor) {
304
                commands.delete(attributeDescriptor);
305

    
306
        }
307

    
308
        public final void insert(FeatureAttributeDescriptor attributeDescriptor) throws DataException {
309
                if( !alterMode ) {
310
                        throw new DataException("alterMode is false");
311
                }
312
                if (!((AttributeDescriptor)attributeDescriptor).isNew()){
313
                        throw new DataException("attribute is not new");
314
                }
315
                this.observable.notifyObservers(this,
316
                                new DefaultAttributeStoreNotification(this,DefaultAttributeStoreNotification.BEFORE_INSERT_ATTRIBUTE,attributeDescriptor)
317
                        );
318
                doInsert(attributeDescriptor);
319
                this.observable.notifyObservers(this,
320
                                new DefaultAttributeStoreNotification(this,DefaultFeatureStoreNotification.AFTER_INSERT,attributeDescriptor)
321
                        );
322

    
323
        }
324

    
325
        protected void doInsert(FeatureAttributeDescriptor attributeDescriptor) {
326
                ((AttributeDescriptor)attributeDescriptor).stopEditing();
327
                commands.insert(attributeDescriptor);
328
        }
329

    
330
        public final void update(FeatureAttributeDescriptor attributeDescriptor) {
331
                //FIXME Comporobar que el attribute viene del Fype de este store
332
                if( !alterMode ) {
333
                        throw new RuntimeException("alterMode is false");
334
                }
335
                this.observable.notifyObservers(this,
336
                                new DefaultAttributeStoreNotification(this,DefaultAttributeStoreNotification.BEFORE_UPDATE_ATTRIBUTE,attributeDescriptor)
337
                        );
338
                doUpdate(attributeDescriptor);
339
                this.observable.notifyObservers(this,
340
                                new DefaultAttributeStoreNotification(this,DefaultAttributeStoreNotification.AFTER_UPDATE_ATTRIBUTE,attributeDescriptor)
341
                        );
342
        }
343

    
344

    
345
        protected void doUpdate(FeatureAttributeDescriptor attributeDescriptor) {
346
                commands.update(((AttributeDescriptor)attributeDescriptor).getNewAttributeDescriptor(),attributeDescriptor);
347
                ((AttributeDescriptor)attributeDescriptor).stopEditing();
348
        }
349

    
350
        public final void delete(Feature feature) {
351
                if( !alterMode ) {
352
                        throw new RuntimeException("alterMode is false");
353
                }
354
                this.observable.notifyObservers(this,
355
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_DELETE,feature)
356
                        );
357
                doDelete(feature);
358
                this.observable.notifyObservers(this,
359
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_DELETE,feature)
360
                        );
361

    
362

    
363
        }
364

    
365
        protected void doDelete(Feature feature) {
366
                commands.delete(feature);
367
        }
368

    
369
        public final void insert(Feature feature) {
370
                if( !alterMode ) {
371
                        throw new RuntimeException("alterMode is false");
372
                }
373
                // FIXME: Comprobar que la feature es de este store
374
                feature.validateModification(this);
375
                this.observable.notifyObservers(this,
376
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_INSERT,feature)
377
                        );
378
        doInsert(feature);
379
                this.observable.notifyObservers(this,
380
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_INSERT,feature)
381
                        );
382

    
383
        }
384

    
385
        protected void doInsert(Feature feature) {
386
                commands.insert(((AbstractFeature)feature).getNewFeature());
387
        }
388

    
389
        public final void update(Feature feature) {
390
                if( !alterMode ) {
391
                        throw new RuntimeException("alterMode is false");
392
                }
393
                //        FIXME: Comprobar que la feature es de este store
394
                feature.validateModification(this);
395
                this.observable.notifyObservers(this,
396
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_UPDATE,feature)
397
                        );
398
                doUpdate(feature);
399
                this.observable.notifyObservers(this,
400
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_UPDATE,feature)
401
                        );
402
        }
403

    
404
        protected void doUpdate(Feature feature) {
405
                feature.validateModification(this);
406
                AbstractFeature oldFeature = (AbstractFeature)feature;
407
                Feature newFeature=oldFeature.getNewFeature();
408
                oldFeature.stopEditing();
409
                commands.update(newFeature,oldFeature);
410
        }
411

    
412
        public final void redo() {
413
                if( !alterMode ) {
414
                        throw new RuntimeException("alterMode is false");
415
                }
416
                Command redo = commands.getNextRedoCommand();
417
                this.observable.notifyObservers(this,
418
                        new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_REDO,redo)
419
                );
420

    
421
                doRedo();
422

    
423
                this.observable.notifyObservers(this,
424
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_REDO,redo)
425
                        );
426

    
427
        }
428

    
429

    
430
        protected void doRedo() {
431
                commands.redo();
432
        }
433

    
434
        public final void undo() {
435
                if( !alterMode ) {
436
                        throw new RuntimeException("alterMode is false");
437
                }
438
                Command undo = commands.getNextUndoCommand();
439
                this.observable.notifyObservers(this,
440
                        new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_UNDO,undo)
441
                );
442
                doUndo();
443

    
444
                this.observable.notifyObservers(this,
445
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_UNDO,undo)
446
                        );
447

    
448
        }
449

    
450
        protected void doUndo() {
451
                commands.undo();
452

    
453
        }
454

    
455
        public CommandsRecord getCommandsRecord() {
456
                if( !alterMode ) {
457
                        throw new RuntimeException("alterMode is false");
458
                }
459
                return commands;
460
        }
461

    
462
        protected void doCancelEditing(){
463
                commands.clear();
464
        }
465

    
466
        public final void cancelEditing() {
467
                if( !alterMode ) {
468
                        throw new RuntimeException("alterMode is false");
469
                }
470
                this.observable.notifyObservers(this,
471
                        new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_CANCELEDITING)
472
                );
473

    
474
                doCancelEditing();
475
                alterMode = false;
476
                this.observable.notifyObservers(this,
477
                        new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_CANCELEDITING)
478
                );
479

    
480
        }
481

    
482
        public final void finishEditing() throws WriteException, ReadException{
483
                if( !alterMode ) {
484
                        //FIXME: OJO arreglar esta excepci?n!!!
485
                        throw new RuntimeException("alterMode is false");
486
                }
487

    
488
                this.observable.notifyObservers(this,
489
                        new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_FINISHEDITING)
490
                );
491

    
492
                this.validateEndEditing();
493

    
494
                doFinishEdition();
495

    
496

    
497
                commands.clear();
498
                featureManager=null;
499
                spatialManager=null;
500
                attributeManager=null;
501
                commands = null;
502

    
503
                alterMode = false;
504

    
505
                this.observable.notifyObservers(this,
506
                        new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_FINISHEDITING)
507
                );
508

    
509
        }
510

    
511
        protected abstract void doFinishEdition() throws WriteException, ReadException ;
512

    
513

    
514
        public Iterator getChilds() {
515
                return null;
516
        }
517

    
518
        public void beginComplexNotification() {
519
                this.observable.beginComplexNotification(new ComplexNotification());
520

    
521
        }
522

    
523
        public void endComplexNotification() {
524
                this.observable.endComplexNotification(this);
525

    
526
        }
527

    
528
        public void addObserver(Observer o) {
529
                this.observable.addObserver(o);
530

    
531
        }
532

    
533
        public void addObserver(Reference ref) {
534
                this.observable.addObserver(ref);
535
        }
536

    
537
        public void deleteObserver(Observer o) {
538
                this.observable.deleteObserver(o);
539
        }
540

    
541
        public void deleteObserver(Reference ref) {
542
                this.observable.deleteObserver(ref);
543
        }
544

    
545
        public void deleteObservers() {
546
                this.observable.deleteObservers();
547

    
548
        }
549

    
550
        public boolean isEditing() {
551
                return alterMode;
552
        }
553

    
554
        protected void validateEndEditing() throws ReadException{
555
                FeatureCollection collection = (FeatureCollection)this.getDataCollection();
556
                Iterator iter = collection.iterator();
557
                while (iter.hasNext()){
558
                        ((Feature)iter.next()).validateEnd(this);
559
                }
560

    
561
        }
562

    
563
        public void disableNotifications() {
564
                this.observable.diableNotifications();
565

    
566
        }
567

    
568
        public void enableNotifications() {
569
                this.observable.enableNotifications();
570
        }
571

    
572

    
573

    
574
        public void getDataCollection(String[] fields, String filter, String order,
575
                        Observer observer) throws DataException {
576

    
577
                this.getDataCollection(this.getDefaultFeatureType().getSubFeatureType(fields), filter, order, observer);
578
        }
579

    
580
        public void getDataCollection(FeatureType type, String filter, String order,Observer observer) {
581
            LoadInBackGround task = new LoadInBackGround(this,type,filter,order,observer);
582
            Thread thread = new Thread(task);
583
            thread.run();
584
    }
585
         private class LoadInBackGround implements Runnable{
586

    
587
                    private FeatureStore store;
588
                    private FeatureType type;
589
                    private String filter;
590
                    private String order;
591

    
592
                    private Observer observer;
593

    
594
                        public DataCollection collection = null;
595
                    public LoadInBackGround(FeatureStore store,FeatureType type, String filter, String order,Observer observer){
596
                            this.store = store;
597
                            this.type = type;
598
                            this.filter = filter;
599
                            this.order = order;
600
                            this.observer = observer;
601

    
602
                    }
603

    
604
                        public void run() {
605
                                try{
606
                                        collection = getDataCollection(type, filter, order);
607
                                } catch (Exception e) {
608
                                        this.observer.update(this.store, new DefaultFeatureStoreNotification(
609
                                                                        this.store,
610
                                                                        FeatureStoreNotification.LOAD_FINISHED,
611
                                                                        e)
612
                                                        );
613
                                }
614
                                this.observer.update(
615
                                                this.store, new DefaultFeatureStoreNotification(
616
                                                                        this.store,
617
                                                                        FeatureStoreNotification.LOAD_FINISHED,
618
                                                                        collection)
619
                                                );
620

    
621
                        }
622

    
623

    
624
            }
625
         public Feature createFeature(FeatureType type, boolean defaultValues) throws InitializeException {
626
                 Feature feature;
627
                 try {
628
                         feature = new CreatedFeature(type,defaultValues);
629
                 } catch (ReadException e) {
630
                         throw new InitializeException(this.getName(),e);
631
                 }
632
                 return feature;
633
         }
634

    
635
         public Feature createDefaultFeature(boolean defaultValues) throws InitializeException{
636
                 return this.createFeature(this.getDefaultFeatureType(),defaultValues);
637
         }
638

    
639
        public DataStoreParameters getParameters() {
640
                return parameters;
641
        }
642

    
643
        protected abstract void doOpen() throws OpenException;
644

    
645
        protected abstract void doClose() throws CloseException;
646

    
647
        protected void doDispose() throws CloseException{
648
                this.parameters = null;
649
                if (this.selection != null){
650
                        this.selection.dispose();
651
                        this.selection = null;
652
                }
653
                this.commands = null;
654
                if (this.locked != null){
655
                        this.locked.dispose();
656
                        this.locked = null;
657
                }
658
                this.observable=null;
659
                this.featureManager = null;
660
                this.spatialManager = null;
661
                this.attributeManager = null;
662
                this.clearResourceObservers();
663
                this.resouceObservers = null;
664
        }
665

    
666
        public final void open() throws OpenException {
667
                this.observable.notifyObservers(this,
668
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_OPEN)
669
                );
670
                doOpen();
671
                this.observable.notifyObservers(this,
672
                                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_OPEN)
673
                );
674

    
675
        }
676

    
677
        public final void close() throws CloseException {
678
                this.observable.notifyObservers(this,
679
                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_CLOSE)
680
            );
681
                doClose();
682
        this.observable.notifyObservers(this,
683
                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.AFTER_CLOSE)
684
            );
685

    
686
        }
687

    
688
        public final void dispose() throws CloseException{
689
                this.observable.notifyObservers(this,
690
                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.BEFORE_DISPOSE)
691
            );
692
        doDispose();
693
        }
694

    
695
        protected abstract void doRefresh() throws OpenException,InitializeException;
696

    
697
        public final void refresh() throws OpenException,InitializeException{
698
        doRefresh();
699
        }
700

    
701
        public void notifyResourceChange(){
702
        this.observable.notifyObservers(this,
703
                new DefaultFeatureStoreNotification(this,DefaultFeatureStoreNotification.RESOURCE_CHANGED)
704
            );
705

    
706
        }
707

    
708
        private class ResourceChangedObserver implements Observer{
709

    
710
                private AbstractFeatureStore theStore;
711

    
712
                public ResourceChangedObserver(AbstractFeatureStore theStore){
713
                        this.theStore = theStore;
714
                }
715

    
716
                /* (non-Javadoc)
717
                 * @see org.gvsig.tools.observer.Observer#update(org.gvsig.util.observer.Observable, java.lang.Object)
718
                 */
719
                public void update(Observable observable, Object notification) {
720
                        if (!(notification instanceof ResourceNotification)){
721
                                return;
722
                        }
723
                        if (((ResourceNotification)notification).getStore() == this.theStore){
724
                                return;
725
                        }
726

    
727
                        if (((ResourceNotification)notification).getType().equals(ResourceNotification.CHANGED)){
728
                                this.theStore.notifyResourceChange();
729
                        }
730
                }
731

    
732
        }
733

    
734
        /* (non-Javadoc)
735
         * @see org.gvsig.fmap.data.feature.FeatureStore#getDefaultFeatureType()
736
         */
737
        public FeatureType getDefaultFeatureType() {
738
                if (isEditing()){
739
//                    Aqu? hay que construir un FeatureType con los cambios que se hayan hecho en la edici?n.
740
                    return attributeManager.getFeatureType();
741
            }
742
        return defaultFeatureType;
743
        }
744

    
745
        public Feature getFeatureByID(FeatureID id) throws ReadException {
746
                return this.getFeatureByID(id, null);
747
        }
748

    
749
        public Object invokeOperation(int code, DataStoreOperationContext context)
750
                        throws DataStoreOperationException,
751
                        DataStoreOperationNotSupportedException {
752

    
753
                DataManager manager = DataManager.getManager();
754
                return manager.invokeDataStoreOperation(this, code, context);
755
        }
756

    
757
        public Object invokeOperation(String name, DataStoreOperationContext context)
758
                        throws DataStoreOperationException,
759
                        DataStoreOperationNotSupportedException {
760
                DataManager manager = DataManager.getManager();
761
                return manager.invokeDataStoreOperation(this, name, context);
762
        }
763

    
764
        public boolean implementsOperation(int code) {
765
                DataManager manager = DataManager.getManager();
766
                return manager.implementsDataStoreOperation(this.getName(), code);
767
        }
768

    
769
        public boolean implementsOperation(String name) {
770
                DataManager manager = DataManager.getManager();
771
                return manager.implementsDataStoreOperation(this.getName(), name);
772
        }
773

    
774
        private void notifySelectionChange() {
775
        this.observable.notifyObservers(this,
776
                                new DefaultFeatureStoreNotification(this,
777
                                                DefaultFeatureStoreNotification.SELECTION_CHANGE));
778

    
779
        }
780

    
781
        public class SelectionObserver implements Observer {
782
                private AbstractFeatureStore store;
783

    
784
                public SelectionObserver(AbstractFeatureStore store) {
785
                        this.store = store;
786
                }
787

    
788
                public void update(Observable observable, Object notification) {
789
                        this.store.notifySelectionChange();
790
                }
791
        }
792

    
793
        /**
794
         * Create a default spatial index. If a filename is provided then the index will be persistent
795
         * (the extension of the resulting index file depends on each implementation).
796
         *
797
         * Convenience method for creating a default spatial index that any AbstractFeatureStore subclass can use
798
         */
799
        protected void createDefaultSpatialIndex(FeatureType fType, String colName, String filename) throws IndexException {
800
                // the column must be a geometry, otherwise throw an exception
801
                FeatureAttributeDescriptor fad = fType.get(colName);
802
                if (!fad.getDataType().equals(FeatureAttributeDescriptor.TYPE_GEOMETRY)) {
803
                        throw new IllegalArgumentException("Can't create spatial index because " + colName + " is not a GEOMETRY.");
804
                }
805

    
806
                SpatialIndex index = null;
807

    
808
                FeatureStore fstore = this;
809

    
810
                try {
811
                        SpatialIndexFactory factory = SpatialIndexFactory.getFactory(SpatialIndexFactory.Factories.GT2_QUADTREE);
812

    
813
                        SpatialIndexParameters param = new SpatialIndexParameters();
814
                        param.setEnvelope((Envelope) fstore.getMetadata().get("extent"));
815

    
816
                        DataCollection data = getDataCollection();
817
                        param.setFeatureCount(data.size());
818
                        //param.setFilename(((FileStoreParameters) getParameters()).getFile().getAbsolutePath());
819
                        param.setFilename(filename);
820
                        param.setOverwrite(true);
821

    
822
                        index = factory.createSpatialIndex(param);
823

    
824
                        Iterator it = data.iterator();
825

    
826
                        int i=0;
827
                        while (it.hasNext()) {
828
                                Feature feat = (Feature) it.next();
829
                                Geometry geom = (Geometry) feat.get(colName);
830
                                index.insert(geom.getEnvelope(), feat.getID());
831
                        }
832

    
833
                        indexStore.addIndex(fType, colName, index);
834

    
835
                        if (index instanceof PersistentSpatialIndex) {
836
                                ((PersistentSpatialIndex)index).flush();
837
                        }
838

    
839
                } catch (IllegalAccessException e) {
840
                        throw new IndexException(e);
841
                } catch (InstantiationException e) {
842
                        throw new IndexException(e);
843
                } catch (ReadException e) {
844
                        throw new IndexException(e);
845
            } catch (BaseException e) {
846
                        throw new IndexException(e);
847
            }
848
        }
849

    
850
        public boolean hasIndex(FeatureType fType, String colName) {
851
                return indexStore.contains(fType, colName);
852
        }
853

    
854
        public FeatureAttributeDescriptor addEvaluatedAttribute(
855
                        FeatureType featureType, String attributeName,
856
                        String attributeType, String expression,
857
                        AttributeValueEvaluator evaluator) throws ReadException {
858
                if (featureType == null) {
859
                        featureType = this.getDefaultFeatureType();
860
                } else {
861
                        List types = this.getFeatureTypes();
862
                        if (!types.contains(featureType)) {
863
                                throw new ReadException("Incompatible feature type", this
864
                                                .getName());
865
                        }
866
                }
867

    
868
                if (evaluator == null) {
869
                        evaluator = DataManager.getManager().getExpressionParser()
870
                                        .newAttributeValueEvaluator();
871
                }
872

    
873
                AttributeDescriptor attr = (AttributeDescriptor) featureType
874
                                .createNewAttributeDescriptor();
875
                attr.loading();
876
                try {
877
                        attr.setEvalued(true);
878
                        attr.setName(attributeName);
879
                        attr.setType(attributeType);
880
                        attr.setExpression(expression);
881
                        attr.setEvaluator(evaluator);
882
                } catch (IsNotAttributeSettingException e) {
883
                        throw new ReadException(this.getName(), e);
884
                }
885
                featureType.add(attr);
886

    
887
                return attr;
888
        }
889

    
890
        public void removeEvaluatedAttribute(FeatureAttributeDescriptor attibute)
891
                        throws DataException {
892
                // TODO Auto-generated method stub
893

    
894
        }
895

    
896

    
897
        public String getClassName() {
898
                return this.getClass().getName();
899
        }
900

    
901
        protected FeatureType checkFeatureTypeForCollection(FeatureType fType)
902
                        throws DataException {
903
                FeatureType defType = this.getDefaultFeatureType();
904
                if (fType == null || fType.equals(defType)) {
905
                        //TODO we must return a copy of Ftype but there are probles with
906
                        // weakRefs of Ftype of Attributes in edition mode
907
                        //                        return defType.getSubFeatureType(null);
908
                        return defType;
909
                }
910
                if (fType.isSubtypeOf(defType)) {
911
                        return fType;
912
                }
913
                Iterator iter = this.getFeatureTypes().iterator();
914
                FeatureType tmpType;
915
                while (iter.hasNext()) {
916
                        tmpType = (FeatureType) iter.next();
917
                        if (fType.isSubtypeOf(tmpType)) {
918
                                return fType;
919
                        }
920

    
921
                }
922
                throw new ReadException("invalid type", this.getName());
923
        }
924
}