Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_data / src / org / gvsig / fmap / data / feature / impl / DefaultFeatureStore.java @ 24178

History | View | Annotate | Download (29.1 KB)

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

    
3
import java.util.*;
4

    
5
import org.gvsig.fmap.data.*;
6
import org.gvsig.fmap.data.exceptions.*;
7
import org.gvsig.fmap.data.feature.*;
8
import org.gvsig.fmap.data.feature.exceptions.*;
9
import org.gvsig.fmap.data.feature.impl.commands.AbstractCommandsRecord;
10
import org.gvsig.fmap.data.feature.impl.commands.implementation.FeatureCommandsRecord;
11
import org.gvsig.fmap.data.feature.impl.expansionadapter.MemoryExpansionAdapter;
12
import org.gvsig.fmap.data.feature.impl.featureSet.DefaultFeatureSet;
13
import org.gvsig.fmap.data.feature.spi.*;
14
import org.gvsig.fmap.data.feature.spi.index.FeatureIndexProviderServices;
15
import org.gvsig.fmap.data.impl.DefaultDataManager;
16
import org.gvsig.fmap.geom.primitive.Envelope;
17
import org.gvsig.metadata.Metadata;
18
import org.gvsig.tools.exception.BaseException;
19
import org.gvsig.tools.observer.Observable;
20
import org.gvsig.tools.observer.Observer;
21
import org.gvsig.tools.observer.impl.DelegateObservable;
22
import org.gvsig.tools.operations.OperationContext;
23
import org.gvsig.tools.operations.OperationException;
24
import org.gvsig.tools.operations.OperationNotSupportedException;
25
import org.gvsig.tools.persistence.AbstractPersistenceManager;
26
import org.gvsig.tools.persistence.PersistenceException;
27
import org.gvsig.tools.persistence.PersistentState;
28
import org.slf4j.Logger;
29
import org.slf4j.LoggerFactory;
30

    
31
final public class DefaultFeatureStore implements
32
                FeatureStoreProviderServices,
33
                Observer {
34

    
35
    final static private Logger logger = LoggerFactory
36
            .getLogger(DefaultFeatureStore.class);
37

    
38
        private DataStoreParameters parameters = null;
39
        private FeatureSelection selection;
40
        private FeatureLocks locks;
41

    
42
        private DelegateObservable delegateObservable = new DelegateObservable(this);
43

    
44
        private AbstractCommandsRecord commands;
45
        private FeatureTypeManager featureTypeManager;
46
        private FeatureManager featureManager;
47
        private SpatialManager spatialManager;
48

    
49
        private FeatureType defaultFeatureType = null;
50
        private List featureTypes = new ArrayList();
51

    
52
        private int mode = MODE_QUERY;
53
        private long versionOfUpdate = 0;
54
        private boolean hasStrongChanges = true;
55

    
56
        private DefaultDataManager dataManager = null;
57

    
58
        private FeatureStoreProvider provider = null;
59

    
60
        private DefaultFeatureIndexes indexes;
61

    
62
        /*
63
         * TODO:
64
         *
65
         * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
66
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
67
         * featureType al que se le han cambiado las reglas de validacion cuando
68
         * hasStrongChanges=false.
69
         */
70

    
71
        public DefaultFeatureStore() {
72

    
73
        }
74

    
75
        public DefaultFeatureStore(DefaultDataManager manager,
76
                        DataStoreParameters parameters, FeatureStoreProvider provider)
77
                        throws InitializeException {
78
                initialize(manager, parameters, provider);
79
        }
80

    
81
        private void initialize(DefaultDataManager manager,
82
                        DataStoreParameters parameters, FeatureStoreProvider provider)
83
                        throws InitializeException {
84
                this.dataManager = manager;
85
                this.provider = provider;
86
                this.parameters = parameters;
87
                this.provider.initialize(this);
88
        }
89

    
90
        public String getName() {
91
                return this.parameters.getDataStoreName();
92
        }
93

    
94
        public String getClassName() {
95
                return this.getClass().getName();
96
        }
97

    
98
        public DataStoreParameters getParameters() {
99
                return parameters;
100
        }
101

    
102
        public DefaultDataManager getManager() {
103
                return this.dataManager;
104
        }
105

    
106
        public Iterator getChilds() {
107
                return this.provider.getChilds();
108
        }
109

    
110
        public FeatureStoreProvider getProvider() {
111
                return this.provider;
112
        }
113

    
114
        public FeatureManager getFeatureManager() {
115
                return this.featureManager;
116
        }
117

    
118
        public void setFeatureTypes(List types, FeatureType defaultType) {
119
                this.featureTypes = types;
120
                this.defaultFeatureType = defaultType;
121
        }
122

    
123
        public void open() throws OpenException {
124
                // TODO: Se puede hacer un open estando en edicion ?
125
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
126
                this.provider.open();
127
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
128
        }
129

    
130
        public void refresh() throws OpenException, InitializeException {
131
                if (this.isEditing()) {
132
                        throw new IllegalStateException();
133
                }
134
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
135
                this.provider.refresh();
136
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
137
        }
138

    
139
        public void close() throws CloseException {
140
                // TODO: Se puede hacer un close estando en edicion ?
141
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
142
                this.provider.close();
143
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
144
        }
145

    
146
        public void dispose() throws CloseException {
147
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
148
                this.provider.dispose();
149
                if (this.selection != null) {
150
                        this.selection.dispose();
151
                        this.selection = null;
152
                }
153
                this.commands = null;
154

    
155
                if (this.locks != null) {
156
                        this.locks.dispose();
157
                        this.locks = null;
158
                }
159

    
160
                this.featureManager = null;
161
                this.spatialManager = null;
162

    
163
                this.parameters = null;
164
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
165
                this.delegateObservable.deleteObservers();
166
                this.delegateObservable = null;
167
        }
168

    
169
        public boolean allowWrite() {
170
                return this.provider.allowWrite();
171
        }
172

    
173
        public boolean canWriteGeometry(int geometryType) {
174
                return this.provider.canWriteGeometry(geometryType);
175
        }
176

    
177
        public DataExplorer getExplorer() throws ReadException {
178
                return this.provider.getExplorer();
179
        }
180

    
181
        public Metadata getMetadata() throws BaseException {
182
                // TODO:
183
                // Si el provider devuelbe null habria que ver de construir aqui
184
                // los metadatos basicos, como el Envelope y el SRS.
185
                return this.provider.getMetadata();
186
        }
187

    
188
        public Envelope getEnvelope() {
189
                return this.provider.getEnvelope();
190
        }
191

    
192
        public FeatureIndexes getIndexes() {
193
                return this.indexes;
194
        }
195

    
196
        public String getSRSDefaultGeometry() throws DataException {
197
                DefaultFeatureType type = (DefaultFeatureType) this
198
                                .getDefaultFeatureType();
199
                return type.getDefaultSRS();
200
        }
201

    
202
        public FeatureSelection createDefaultFeatureSelection()
203
                        throws DataException {
204
                return new DefaultFeatureSelection(this);
205
        }
206

    
207
        public FeatureData createDefaultFeatureData(FeatureType type)
208
                        throws DataException {
209
                return new DefaultFeatureData(type);
210
        }
211

    
212
        public PersistentState getState()
213
                        throws PersistenceException {
214
                return AbstractPersistenceManager.getState(this);
215
        }
216

    
217
        public void loadState(PersistentState state) throws PersistenceException {
218
                state.setTheClass(this);
219
                state.set("dataStoreName", this.getName());
220
                state.set("parameters", this.parameters);
221
                state.set("provider", this.provider);
222
                state.set("selection", this.selection);
223
        }
224

    
225
        public void setState(PersistentState state) throws PersistenceException {
226
                if (this.provider != null) {
227
                        throw new PersistenceException(null);
228
                }
229
                if (this.getManager() == null) {
230
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
231
                }
232

    
233
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
234
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
235

    
236
                try {
237

    
238
                        initialize(this.getManager(), params, provider);
239
                        setSelection((FeatureSelection) state.get("selection"));
240

    
241
                } catch (InitializeException e) {
242
                        throw new PersistenceException(e);
243
                } catch (DataException e) {
244
                        throw new PersistenceException(e);
245
                }
246

    
247
        }
248

    
249
        //
250
        // ====================================================================
251
        // Gestion de la seleccion
252
        //
253

    
254
        public void setSelection(DataSet selection)
255
                        throws DataException {
256
                this.setSelection((FeatureSet) selection);
257
        }
258

    
259
        public DataSet createSelection() throws DataException {
260
                return createFeatureSelection();
261
        }
262

    
263
        public DataSet getSelection() throws DataException {
264
                return this.getFeatureSelection();
265
        }
266

    
267
        public void setSelection(FeatureSet selection)
268
                        throws DataException {
269
                if (selection.equals(this.selection)) {
270
                        return;
271
                }
272
                if (!selection.isFromStore(this)) {
273
                        throw new SelectionNotAllowedException(getName());
274
                }
275

    
276
                this.selection.deleteObserver(this);
277
                if (selection instanceof FeatureSelection) {
278
                        this.selection = (FeatureSelection) selection;
279
                } else {
280
                        this.selection.deselectAll();
281
                        this.selection.select(selection);
282
                }
283
                this.selection.addObserver(this);
284

    
285
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
286
        }
287

    
288
        public FeatureSelection createFeatureSelection() throws DataException {
289
                return this.provider.createFeatureSelection();
290
        }
291

    
292
        public FeatureSelection getFeatureSelection() throws DataException {
293
                if (selection == null) {
294
                        this.selection = createFeatureSelection();
295
                        this.selection.addObserver(this);
296
                }
297
                return selection;
298
        }
299

    
300
        //
301
        // ====================================================================
302
        // Gestion de notificaciones
303
        //
304

    
305
        public void notifyChange(String notification) {
306
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
307
                notification));
308

    
309
        }
310

    
311
        public void notifyChange(String notification, Feature feature) {
312
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
313
                                                this, notification, feature));
314
        }
315

    
316
        public void notifyChange(String notification, Command command) {
317
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
318
                                                this, notification, command));
319
        }
320

    
321
        public void notifyChange(String notification, EditableFeatureType type) {
322
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
323
                notification, type));
324
        }
325

    
326

    
327
        //
328
        // ====================================================================
329
        // Gestion de bloqueos
330
        //
331

    
332

    
333
        public FeatureSet getLocks() throws DataException {
334
                if (!this.provider.isLocksSupported()) {
335
                        getLogger().warn("Locks not supporteds");
336
                        return null;
337
                }
338
                if (locks == null) {
339
                        this.locks = this.provider.createFeatureLocks();
340
                }
341
                return locks;
342
        }
343

    
344
        //
345
        // ====================================================================
346
    // Interface Observable
347
        //
348

    
349
    public void disableNotifications() {
350
        this.delegateObservable.disableNotifications();
351

    
352
    }
353

    
354
    public void enableNotifications() {
355
        this.delegateObservable.enableNotifications();
356
    }
357

    
358
    public void beginComplexNotification() {
359
        this.delegateObservable.beginComplexNotification();
360

    
361
    }
362

    
363
    public void endComplexNotification() {
364
        this.delegateObservable.endComplexNotification();
365

    
366
    }
367

    
368
        public void addObserver(Observer observer) {
369
                this.delegateObservable.addObserver(observer);
370

    
371
        }
372

    
373
    //
374
    // public void addObserver(Reference ref) {
375
    // this.observable.addObserver(ref);
376
    // }
377

    
378
        public void deleteObserver(Observer observer) {
379
        this.delegateObservable.deleteObserver(observer);
380
        }
381

    
382
    //
383
    // public void deleteObserver(Reference ref) {
384
    // this.observable.deleteObserver(ref);
385
    // }
386

    
387
        public void deleteObservers() {
388
                this.delegateObservable.deleteObservers();
389

    
390
        }
391

    
392
        //
393
        // ====================================================================
394
        // Interface Observer
395
        //
396
        // Usado para observar:
397
        // - su seleccion
398
        // - sus bloqueos
399
        // - sus recursos
400
        //
401

    
402
        public void update(Observable observable, Object notification) {
403
                if (observable instanceof FeatureSet) {
404
                        if (observable == this.selection) {
405
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
406
                        } else if (observable == this.locks) {
407
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
408
                        }
409

    
410
                }
411
        }
412

    
413

    
414
        //
415
        // ====================================================================
416
        // Gestion de operaciones
417
        // Interface ExtendedOperations
418
        //
419
        public Object invokeOperation(int code, OperationContext context)
420
                        throws OperationException, OperationNotSupportedException {
421
                return this.dataManager.getOperationManager().invokeOperation(this, code, context);
422
        }
423

    
424
        public Object invokeOperation(String name, OperationContext context)
425
                        throws OperationException, OperationNotSupportedException {
426
                return this.dataManager.getOperationManager().invokeOperation(this, name, context);
427
        }
428

    
429
        public boolean hasOperation(int code) {
430
                return this.dataManager.getOperationManager().hasOperation(this, code);
431
        }
432

    
433
        public boolean hasOperation(String name) {
434
                return this.dataManager.getOperationManager().hasOperation(this, name);
435
        }
436

    
437
        public Object getOperation(int code) throws OperationException {
438
                return this.dataManager.getOperationManager().getOperation(this, code);
439
        }
440

    
441
        public Object getOperation(String name) throws OperationException {
442
                return this.dataManager.getOperationManager().getOperation(this, name);
443
        }
444

    
445
        //
446
        // ====================================================================
447
        // Edicion
448
        //
449

    
450
        private void newVersionOfUpdate() {
451
                this.versionOfUpdate++;
452
        }
453

    
454
        private long currentVersionOfUpdate() {
455
                return this.versionOfUpdate;
456
        }
457

    
458
        private void checkInEditingMode()
459
                        throws NeedEditingModeException {
460
                if (mode != MODE_FULLEDIT) {
461
                        throw new NeedEditingModeException(this.getName());
462
                }
463
        }
464

    
465
        private void checkIsOwnFeature(Feature feature)
466
                        throws IllegalFeatureException {
467
                if (((DefaultFeature) feature).getStore() != this) {
468
                        throw new IllegalFeatureException(this.getName());
469
                }
470
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
471
                // fixFeatureType((DefaultFeatureType) feature.getType());
472
        }
473

    
474
        private void exitEditingMode() {
475
                commands.clear();
476
                featureManager = null;
477
                spatialManager = null;
478
                featureTypeManager = null;
479
                commands = null;
480

    
481
                mode = MODE_QUERY;
482
                hasStrongChanges = true; // Lo deja a true por si las moscas
483
        }
484

    
485
        synchronized public void edit() throws DataException {
486
                edit(MODE_FULLEDIT);
487
        }
488

    
489
        synchronized public void edit(int mode) throws DataException {
490
                try {
491
                        if ( this.mode != MODE_QUERY ) {
492
                                throw new AlreadyEditingException(this.getName());
493
                        }
494
                        switch (mode) {
495
                        case MODE_QUERY:
496
                                throw new IllegalStateException(this.getName());
497

    
498
                        case MODE_FULLEDIT:
499
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
500
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
501
                                featureTypeManager = new FeatureTypeManager(
502
                                                new MemoryExpansionAdapter());
503
                                spatialManager = new SpatialManager();
504

    
505
                                commands = new FeatureCommandsRecord(featureManager,
506
                                                spatialManager, featureTypeManager);
507
                                this.mode = MODE_FULLEDIT;
508
                                hasStrongChanges = false;
509
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
510
                                break;
511
                        case MODE_APPEND:
512
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
513
                                this.provider.beginAppend();
514
                                this.mode = MODE_APPEND;
515
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
516
                                break;
517
                        }
518
                } catch (Exception e) {
519
                        throw new StoreEditException(e, this.getName());
520
                }
521
        }
522

    
523
        public boolean isEditing() {
524
                return mode == MODE_FULLEDIT;
525
        }
526

    
527
        public boolean isAppending() {
528
                return mode == MODE_APPEND;
529
        }
530

    
531
        synchronized public void update(EditableFeatureType type)
532
                        throws DataException {
533
                try {
534
                        checkInEditingMode();
535
                        if (type == null) {
536
                                throw new NullFeatureTypeException(getName());
537
                        }
538
                        // FIXME: Comprobar que es un featureType aceptable.
539
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
540
                        newVersionOfUpdate();
541

    
542
                        FeatureType oldt = type.getSource().getCopy();
543
                        FeatureType newt = type.getNotEditableCopy();
544
                        commands.update(newt, oldt);
545

    
546
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
547
                                hasStrongChanges = true;
548
                        }
549
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
550
                } catch (Exception e) {
551
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
552
                }
553
        }
554

    
555
        synchronized public void delete(Feature feature) throws DataException {
556
                try {
557
                        checkInEditingMode();
558
                        checkIsOwnFeature(feature);
559
                        if (feature instanceof EditableFeature) {
560
                                throw new StoreDeleteEditableFeatureException(getName());
561
                        }
562
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
563
                        this.commands.delete(feature);
564
                        newVersionOfUpdate();
565
                        hasStrongChanges = true;
566
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
567
                } catch (Exception e) {
568
                        throw new StoreDeleteFeatureException(e, this.getName());
569
                }
570
        }
571

    
572
        private static EditableFeature lastChangedFeature = null;
573

    
574
        synchronized public void insert(EditableFeature feature)
575
                        throws DataException {
576
                try {
577
                        switch (mode) {
578
                        case MODE_QUERY:
579
                                throw new NeedEditingModeException(this.getName());
580

    
581
                        case MODE_APPEND:
582
                                checkIsOwnFeature(feature);
583
                                if (feature.getSource() != null) {
584
                                        throw new NoNewFeatureInsertException(this.getName());
585
                                }
586
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
587
                                feature.validate(Feature.UPDATE);
588
                                provider.append(feature);
589
                                hasStrongChanges = true;
590
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
591
                                break;
592

    
593
                        case MODE_FULLEDIT:
594
                                checkIsOwnFeature(feature);
595
                                if (feature.getSource() != null) {
596
                                        throw new NoNewFeatureInsertException(this.getName());
597
                                }
598
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
599
                                newVersionOfUpdate();
600
                                if (lastChangedFeature.getSource() != feature.getSource()) {
601
                                        lastChangedFeature = feature;
602
                                        feature.validate(Feature.UPDATE);
603
                                        lastChangedFeature = null;
604
                                }
605
                                commands.insert(feature.getNotEditableCopy());
606
                                hasStrongChanges = true;
607
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
608
                                break;
609
                        }
610
                } catch (Exception e) {
611
                        throw new StoreInsertFeatureException(e, this.getName());
612
                }
613
        }
614

    
615
        synchronized public void update(EditableFeature feature)
616
                        throws DataException {
617
                try {
618
                        if ((feature).getSource() == null) {
619
                                insert(feature);
620
                                return;
621
                        }
622
                        checkInEditingMode();
623
                        checkIsOwnFeature(feature);
624
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
625
                        newVersionOfUpdate();
626
                        if (lastChangedFeature.getSource() != feature.getSource()) {
627
                                lastChangedFeature = feature;
628
                                feature.validate(Feature.UPDATE);
629
                                lastChangedFeature = null;
630
                        }
631

    
632
                        Feature oldf = feature.getSource();
633
                        Feature newf = feature.getNotEditableCopy();
634
                        commands.update(newf, oldf);
635

    
636
                        hasStrongChanges = true;
637
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
638
                } catch (Exception e) {
639
                        throw new StoreUpdateFeatureException(e, this.getName());
640
                }
641
        }
642

    
643
        synchronized public void redo() throws DataException {
644
                try {
645
                        checkInEditingMode();
646
                        Command redo = commands.getNextRedoCommand();
647
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
648
                        newVersionOfUpdate();
649
                        commands.redo();
650
                        hasStrongChanges = true;
651
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
652
                } catch (Exception e) {
653
                        throw new StoreRedoException(e, this.getName());
654
                }
655
        }
656

    
657
        synchronized public void undo() throws DataException {
658
                try {
659
                        checkInEditingMode();
660
                        Command undo = commands.getNextUndoCommand();
661
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
662
                        newVersionOfUpdate();
663
                        commands.undo();
664
                        hasStrongChanges = true;
665
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
666
                } catch (Exception e) {
667
                        throw new StoreUndoException(e, this.getName());
668
                }
669
        }
670

    
671
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
672
                checkInEditingMode();
673
                return commands;
674
        }
675

    
676
        synchronized public void cancelEditing() throws DataException {
677
                try {
678
                        checkInEditingMode();
679
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
680
                        exitEditingMode();
681
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
682
                } catch (Exception e) {
683
                        throw new StoreCancelEditingException(e, this.getName());
684
                }
685
        }
686

    
687
        synchronized public void finishEditing() throws DataException {
688
                try {
689
                        switch (mode) {
690
                        case MODE_QUERY:
691
                                throw new NeedEditingModeException(this.getName());
692

    
693
                        case MODE_APPEND:
694
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
695
                                provider.endAppend();
696
                                exitEditingMode();
697
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
698
                                break;
699

    
700
                        case MODE_FULLEDIT:
701
                                if (!hasStrongChanges) {
702
                                        performLightEditing();
703
                                        return;
704
                                }
705
                                if (!this.allowWrite()) {
706
                                        throw new WriteNotAllowedException(getName());
707
                                }
708

    
709
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
710
                                validateFeatures(Feature.FINISH_EDITING);
711
                                provider.performEditing(featureManager.getInserted(),
712
                                                featureManager.getUpdated(), featureManager
713
                                                                .getDeleted());
714
                                exitEditingMode();
715
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
716
                                break;
717
                        }
718
                } catch (Exception e) {
719
                        throw new FinishEditingException(e);
720
                }
721
        }
722

    
723
        private void performLightEditing() throws DataException {
724
                throw new UnsupportedOperationException(
725
                                "lightFinishEdition not yet implemented");
726

    
727
                // TODO: implementar
728
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
729
                // exitEditingMode();
730
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
731
        }
732

    
733
        public void export(FeatureExplorer explorer, FeatureStoreParameters params)
734
                        throws DataException {
735

    
736
                if (this.getFeatureTypes().size() != 1) {
737
                        throw new UnsupportedOperationException(
738
                                        "export whith more than one type not yet implemented");
739
                }
740
                try {
741
                        FeatureType type = this.getDefaultFeatureType();
742
                        params.setDefaultFeatureType(type);
743
                        explorer.add(params);
744

    
745
                        DataManager manager = DALLocator.getDataManager();
746
                        FeatureStore target = (FeatureStore) manager
747
                                        .createStore(params);
748
                        target.edit();
749

    
750
                        FeatureSet features = this.getFeatureSet();
751
                        Iterator it1 = features.iterator();
752
                        while (it1.hasNext()) {
753
                                Feature feature = (Feature) it1.next();
754
                                target.insert(target.createNewFeature(type, feature));
755
                        }
756
                        features.dispose();
757
                        target.finishEditing();
758
                        target.dispose();
759
                } catch (Exception e) {
760
                        throw new DataExportException(e, params.toString());
761
                }
762
        }
763

    
764
        //
765
        // ====================================================================
766
        // Obtencion de datos
767
        // getDataCollection, getFeatureCollection
768
        //
769

    
770
        public DataSet getDataSet() throws DataException {
771
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
772
                return new DefaultFeatureSet(this, query);
773
        }
774

    
775
        public DataSet getDataSet(DataQuery dataQuery)
776
                        throws DataException {
777
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
778
        }
779

    
780
        public void getDataSet(Observer observer) throws DataException {
781
                this.getFeatureSet(null, observer);
782
        }
783

    
784
        public void getDataSet(DataQuery dataQuery, Observer observer)
785
                        throws DataException {
786
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
787
        }
788

    
789
        public FeatureSet getFeatureSet() throws DataException {
790
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
791
                return new DefaultFeatureSet(this, query);
792
        }
793

    
794
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
795
                        throws DataException {
796
                fixFeatureQuery(featureQuery);
797
                return new DefaultFeatureSet(this, featureQuery);
798
        }
799

    
800
        private void fixFeatureQuery(FeatureQuery featureQuery)
801
                        throws DataException {
802
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
803
                if (featureQuery.getAttributeNames() != null){
804
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
805
                                        .getFeatureType();
806
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
807
                                        .getAttributeNames()));
808
                }
809
        }
810

    
811
        public void getFeatureSet(Observer observer)
812
                        throws DataException {
813
                this.getFeatureSet(null, observer);
814
        }
815

    
816
        public void getFeatureSet(FeatureQuery query, Observer observer)
817
                        throws DataException {
818
                class LoadInBackGround implements Runnable {
819
                        private FeatureStore store;
820
                        private FeatureQuery query;
821
                        private Observer observer;
822

    
823
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
824
                                        Observer observer) {
825
                                this.store = store;
826
                                this.query = query;
827
                                this.observer = observer;
828
                        }
829

    
830
                        public void run() {
831
                                try {
832
                                        FeatureSet collection = store.getFeatureSet(query);
833
                                        observer.update(
834
                                                        store,
835
                                                        new DefaultFeatureStoreNotification(
836
                                                                        store,
837
                                                                        FeatureStoreNotification.LOAD_FINISHED,
838
                                                                        collection
839
                                                                )
840
                                                );
841
                                } catch (Exception e) {
842
                                        observer.update(
843
                                                        store,
844
                                                        new DefaultFeatureStoreNotification(
845
                                                                        store,
846
                                                                        FeatureStoreNotification.LOAD_FINISHED,
847
                                                                        e
848
                                                                )
849
                                                );
850
                                }
851
                        }
852
                }
853

    
854
                if (query == null) {
855
                        query = new FeatureQuery(this.getDefaultFeatureType());
856
                }
857
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
858
                Thread thread = new Thread(task);
859
                thread.run();
860
        }
861

    
862
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
863
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
864
        }
865

    
866
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
867
                        throws DataException {
868
                featureType = fixFeatureType((DefaultFeatureType) featureType);
869
                // TODO comprobar que el id es de este store
870

    
871
                if (this.mode == MODE_FULLEDIT) {
872
                        Feature f = featureManager.get(reference, this, featureType);
873
                        if (f!=null) {
874
                                return f;
875
                        }
876
                }
877
                return this.createFeature(featureType, this.provider
878
                                .getFeatureDataByReference(reference, featureType));
879
        }
880

    
881
        //
882
        // ====================================================================
883
        // Gestion de features
884
        //
885

    
886
        private FeatureType fixFeatureType(DefaultFeatureType type)
887
                        throws DataException {
888
                FeatureType defaultType = this.getDefaultFeatureType();
889
                if (type == null || type.equals(defaultType)) {
890
                        return defaultType;
891
                }
892
                if (type.isSubtypeOf(defaultType)) {
893
                        return type;
894
                }
895
                Iterator iter = this.getFeatureTypes().iterator();
896
                FeatureType tmpType;
897
                while (iter.hasNext()) {
898
                        tmpType = (FeatureType) iter.next();
899
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
900
                                return type;
901
                        }
902

    
903
                }
904
                throw new IllegalFeatureTypeException(getName());
905
        }
906

    
907
        public void validateFeatures(int mode) throws DataException {
908
                try {
909
                        FeatureSet collection = this.getFeatureSet();
910
                        Iterator iter = collection.iterator();
911
                        long previousVersionOfUpdate = currentVersionOfUpdate();
912
                        while (iter.hasNext()) {
913
                                ((DefaultFeature) iter.next()).validate(mode);
914
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
915
                                        throw new ConcurrentDataModificationException(getName());
916
                                }
917
                        }
918
                } catch (Exception e) {
919
                        throw new ValidateFeaturesException(e, getName());
920
                }
921
        }
922

    
923
        public FeatureType getDefaultFeatureType() throws DataException {
924
                try {
925
                        if (isEditing()) {
926
                                return featureTypeManager.getType(defaultFeatureType.getId());
927
                        }
928
                        return defaultFeatureType;
929
                } catch (Exception e) {
930
                        throw new GetFeatureTypeException(e, getName());
931
                }
932
        }
933

    
934
        public List getFeatureTypes() throws DataException {
935
                try {
936
                        List types;
937
                        if (isEditing()) {
938
                                types=new ArrayList();
939
                                Iterator it=featureTypes.iterator();
940
                                while (it.hasNext()) {
941
                                        FeatureType type = (FeatureType) it.next();
942
                                        type=featureTypeManager.getType(type.getId());
943
                                        if (type!=null) {
944
                                                types.add(type);
945
                                        }
946
                                }
947
                                it = featureTypeManager.newsIterator();
948
                                while (it.hasNext()) {
949
                                        FeatureType type = (FeatureType) it.next();
950
                                        types.add(type);
951
                                }
952
                        } else {
953
                                types = featureTypes;
954
                        }
955
                        return Collections.unmodifiableList(types);
956
                } catch (Exception e) {
957
                        throw new GetFeatureTypeException(e, getName());
958
                }
959
        }
960

    
961
        public Feature createFeature(FeatureData data)
962
                        throws DataException {
963
                DefaultFeature feature = new DefaultFeature(this, data);
964
                return feature;
965
        }
966

    
967
        /**
968
         * @deprecated
969
         */
970
        public Feature createFeature(FeatureType type, FeatureData data)
971
                        throws DataException {
972
                // FIXME: falta por implementar
973
                // Comprobar si es un subtipo del feature de data
974
                // y construir un feature usando el subtipo.
975
                // Probablemente requiera generar una copia del data.
976
                return null;
977
        }
978

    
979
        public EditableFeature createNewFeature(FeatureType type,
980
                        Feature defaultValues)
981
                        throws DataException {
982
                try {
983
                        type = this.fixFeatureType((DefaultFeatureType) type);
984
                        FeatureData data = this.provider.createNewFeatureData(type);
985
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
986
                                        data);
987
                        feature.initializeValues(defaultValues);
988
                        return feature;
989
                } catch (Exception e) {
990
                        throw new CreateFeatureException(e, getName());
991
                }
992
        }
993

    
994
        public EditableFeature createNewFeature(FeatureType type,
995
                        boolean defaultValues)
996
                        throws DataException {
997
                try {
998
                        type = this.fixFeatureType((DefaultFeatureType) type);
999
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1000
                        if (defaultValues) {
1001
                                feature.initializeValues();
1002
                        }
1003
                        return feature;
1004
                } catch (Exception e) {
1005
                        throw new CreateFeatureException(e, getName());
1006
                }
1007
        }
1008

    
1009
        public EditableFeature createNewFeature(boolean defaultValues)
1010
                        throws DataException {
1011
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1012
        }
1013

    
1014
        public EditableFeature createNewFeature() throws DataException {
1015
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1016
        }
1017

    
1018
        public EditableFeatureType createFeatureType() {
1019
                return new DefaultEditableFeatureType();
1020
        }
1021

    
1022
        public boolean isLocksSupported() {
1023
                return this.provider.isLocksSupported();
1024
        }
1025

    
1026
        public Logger getLogger() {
1027
                return DefaultFeatureStore.logger;
1028
        }
1029

    
1030
        public FeatureIndex createIndex(FeatureType featureType,
1031
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1032
                FeatureIndexProviderServices index = null;
1033
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1034
                try {
1035
                        index.fill();
1036
                } catch (DataIndexException e) {
1037
                        throw new InitializeException(index.getName(), e);
1038
                }
1039
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1040
                return index;
1041
        }
1042

    
1043
}