Statistics
| Revision:

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

History | View | Annotate | Download (30.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.exception.NotYetImplemented;
20
import org.gvsig.tools.observer.Observer;
21
import org.gvsig.tools.observer.WeakReferencingObservable;
22
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
23
import org.gvsig.tools.operations.OperationContext;
24
import org.gvsig.tools.operations.OperationException;
25
import org.gvsig.tools.operations.OperationNotSupportedException;
26
import org.gvsig.tools.persistence.AbstractPersistenceManager;
27
import org.gvsig.tools.persistence.PersistenceException;
28
import org.gvsig.tools.persistence.PersistentState;
29
import org.slf4j.Logger;
30
import org.slf4j.LoggerFactory;
31

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

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

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

    
43
        private DelegateWeakReferencingObservable delegateObservable = new DelegateWeakReferencingObservable(this);
44

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

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

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

    
57
        private DefaultDataManager dataManager = null;
58

    
59
        private FeatureStoreProvider provider = null;
60

    
61
        private DefaultFeatureIndexes indexes;
62

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

    
72
        public DefaultFeatureStore() {
73

    
74
        }
75

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

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

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

    
95
        public DataStoreParameters getParameters() {
96
                return parameters;
97
        }
98

    
99
        public DefaultDataManager getManager() {
100
                return this.dataManager;
101
        }
102

    
103
        public Iterator getChilds() {
104
                return this.provider.getChilds();
105
        }
106

    
107
        public FeatureStoreProvider getProvider() {
108
                return this.provider;
109
        }
110

    
111
        public FeatureManager getFeatureManager() {
112
                return this.featureManager;
113
        }
114

    
115
        public void setFeatureTypes(List types, FeatureType defaultType) {
116
                this.featureTypes = types;
117
                this.defaultFeatureType = defaultType;
118
        }
119

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

    
127
        public void refresh() throws OpenException, InitializeException {
128
                if (this.mode != MODE_QUERY) {
129
                        throw new IllegalStateException();
130
                }
131
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
132
                this.provider.refresh();
133
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
134
        }
135

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

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

    
152
                if (this.locks != null) {
153
                        this.locks.dispose();
154
                        this.locks = null;
155
                }
156

    
157
                this.featureManager = null;
158
                this.spatialManager = null;
159

    
160
                this.parameters = null;
161
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
162
                this.delegateObservable.deleteObservers();
163
                this.delegateObservable = null;
164
        }
165

    
166
        public boolean allowWrite() {
167
                return this.provider.allowWrite();
168
        }
169

    
170
        public boolean canWriteGeometry(int geometryType) {
171
                return this.provider.canWriteGeometry(geometryType);
172
        }
173

    
174
        public DataExplorer getExplorer() throws ReadException {
175
                return this.provider.getExplorer();
176
        }
177

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

    
185
        public Envelope getEnvelope() {
186
                // FIXME: Y en edicion/append
187
                return this.provider.getEnvelope();
188
        }
189

    
190
        public FeatureIndexes getIndexes() {
191
                return this.indexes;
192
        }
193

    
194
        /**
195
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
196
         */
197
        public String getSRSDefaultGeometry() throws DataException {
198
                return this.getDefaultFeatureType().getDefaultSRS();
199
        }
200

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

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

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

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

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

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

    
235
                try {
236

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

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

    
246
        }
247

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

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

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

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

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

    
275
                this.selection.deleteObserver(this);
276
                if (selection instanceof FeatureSelection) {
277
                        if (isEditing()) {
278
                                commands.selectionSet(this, this.selection,
279
                                                (FeatureSelection) selection);
280
                        }
281
                        this.selection = (FeatureSelection) selection;
282
                } else {
283
                        if (isEditing()) {
284
                                commands.startComplex("_selectionSet");
285
                        }
286
                        this.selection.deselectAll();
287
                        this.selection.select(selection);
288
                        if (isEditing()) {
289
                                commands.endComplex();
290
                        }
291
                }
292
                this.selection.addObserver(this);
293

    
294
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
295
        }
296

    
297
        public FeatureSelection createFeatureSelection() throws DataException {
298
                return this.provider.createFeatureSelection();
299
        }
300

    
301
        public FeatureSelection getFeatureSelection() throws DataException {
302
                if (selection == null) {
303
                        this.selection = createFeatureSelection();
304
                        this.selection.addObserver(this);
305
                }
306
                return selection;
307
        }
308

    
309
        //
310
        // ====================================================================
311
        // Gestion de notificaciones
312
        //
313

    
314
        public void notifyChange(String notification) {
315
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
316
                notification));
317

    
318
        }
319

    
320
        public void notifyChange(String notification, Feature feature) {
321
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
322
                                                this, notification, feature));
323
        }
324

    
325
        public void notifyChange(String notification, Command command) {
326
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
327
                                                this, notification, command));
328
        }
329

    
330
        public void notifyChange(String notification, EditableFeatureType type) {
331
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
332
                notification, type));
333
        }
334

    
335

    
336
        //
337
        // ====================================================================
338
        // Gestion de bloqueos
339
        //
340

    
341

    
342
        public FeatureSet getLocks() throws DataException {
343
                if (!this.provider.isLocksSupported()) {
344
                        getLogger().warn("Locks not supporteds");
345
                        return null;
346
                }
347
                if (locks == null) {
348
                        this.locks = this.provider.createFeatureLocks();
349
                }
350
                return locks;
351
        }
352

    
353
        //
354
        // ====================================================================
355
    // Interface Observable
356
        //
357

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

    
361
    }
362

    
363
    public void enableNotifications() {
364
        this.delegateObservable.enableNotifications();
365
    }
366

    
367
    public void beginComplexNotification() {
368
        this.delegateObservable.beginComplexNotification();
369

    
370
    }
371

    
372
    public void endComplexNotification() {
373
        this.delegateObservable.endComplexNotification();
374

    
375
    }
376

    
377
        public void addObserver(Observer observer) {
378
                this.delegateObservable.addObserver(observer);
379

    
380
        }
381

    
382
        public void deleteObserver(Observer observer) {
383
        this.delegateObservable.deleteObserver(observer);
384
        }
385

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

    
389
        }
390

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

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

    
409
                }
410
        }
411

    
412

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

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

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

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

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

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

    
444
        //
445
        // ====================================================================
446
        // Edicion
447
        //
448

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

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

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

    
464
        private void checkNotInAppendMode() throws IllegalStateException {
465
                if (mode == MODE_APPEND) {
466
                        throw new IllegalStateException(this.getName());
467
                }
468
        }
469

    
470
        private void checkIsOwnFeature(Feature feature)
471
                        throws IllegalFeatureException {
472
                if (((DefaultFeature) feature).getStore() != this) {
473
                        throw new IllegalFeatureException(this.getName());
474
                }
475
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
476
                // fixFeatureType((DefaultFeatureType) feature.getType());
477
        }
478

    
479
        private void exitEditingMode() {
480
                commands.clear();
481
                featureManager = null;
482
                spatialManager = null;
483
                featureTypeManager = null;
484
                commands = null;
485

    
486
                mode = MODE_QUERY;
487
                hasStrongChanges = true; // Lo deja a true por si las moscas
488
        }
489

    
490
        synchronized public void edit() throws DataException {
491
                edit(MODE_FULLEDIT);
492
        }
493

    
494
        synchronized public void edit(int mode) throws DataException {
495
                try {
496
                        if ( this.mode != MODE_QUERY ) {
497
                                throw new AlreadyEditingException(this.getName());
498
                        }
499
                        if (!this.provider.supportsAppendMode()) {
500
                                mode = MODE_FULLEDIT;
501
                        }
502
                        switch (mode) {
503
                        case MODE_QUERY:
504
                                throw new IllegalStateException(this.getName());
505

    
506
                        case MODE_FULLEDIT:
507
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
508
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
509
                                featureTypeManager = new FeatureTypeManager(
510
                                                new MemoryExpansionAdapter());
511
                                spatialManager = new SpatialManager();
512

    
513
                                commands = new FeatureCommandsRecord(featureManager,
514
                                                spatialManager, featureTypeManager);
515
                                this.mode = MODE_FULLEDIT;
516
                                hasStrongChanges = false;
517
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
518
                                break;
519
                        case MODE_APPEND:
520
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
521
                                this.provider.beginAppend();
522
                                this.mode = MODE_APPEND;
523
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
524
                                break;
525
                        }
526
                } catch (Exception e) {
527
                        throw new StoreEditException(e, this.getName());
528
                }
529
        }
530

    
531
        public boolean isEditing() {
532
                return mode == MODE_FULLEDIT;
533
        }
534

    
535
        public boolean isAppending() {
536
                return mode == MODE_APPEND;
537
        }
538

    
539
        synchronized public void update(EditableFeatureType type)
540
                        throws DataException {
541
                try {
542
                        checkInEditingMode();
543
                        if (type == null) {
544
                                throw new NullFeatureTypeException(getName());
545
                        }
546
                        // FIXME: Comprobar que es un featureType aceptable.
547
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
548
                        newVersionOfUpdate();
549

    
550
                        FeatureType oldt = type.getSource().getCopy();
551
                        FeatureType newt = type.getNotEditableCopy();
552
                        commands.update(newt, oldt);
553

    
554
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
555
                                hasStrongChanges = true;
556
                        }
557
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
558
                } catch (Exception e) {
559
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
560
                }
561
        }
562

    
563
        synchronized public void delete(Feature feature) throws DataException {
564
                try {
565
                        checkInEditingMode();
566
                        checkIsOwnFeature(feature);
567
                        if (feature instanceof EditableFeature) {
568
                                throw new StoreDeleteEditableFeatureException(getName());
569
                        }
570
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
571
                        this.commands.delete(feature);
572
                        newVersionOfUpdate();
573
                        hasStrongChanges = true;
574
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
575
                } catch (Exception e) {
576
                        throw new StoreDeleteFeatureException(e, this.getName());
577
                }
578
        }
579

    
580
        private static EditableFeature lastChangedFeature = null;
581

    
582
        synchronized public void insert(EditableFeature feature)
583
                        throws DataException {
584
                try {
585
                        switch (mode) {
586
                        case MODE_QUERY:
587
                                throw new NeedEditingModeException(this.getName());
588

    
589
                        case MODE_APPEND:
590
                                checkIsOwnFeature(feature);
591
                                if (feature.getSource() != null) {
592
                                        throw new NoNewFeatureInsertException(this.getName());
593
                                }
594
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
595
                                feature.validate(Feature.UPDATE);
596
                                provider.append(feature);
597
                                hasStrongChanges = true;
598
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
599
                                break;
600

    
601
                        case MODE_FULLEDIT:
602
                                checkIsOwnFeature(feature);
603
                                if (feature.getSource() != null) {
604
                                        throw new NoNewFeatureInsertException(this.getName());
605
                                }
606
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
607
                                newVersionOfUpdate();
608
                                if (lastChangedFeature.getSource() != feature.getSource()) {
609
                                        lastChangedFeature = feature;
610
                                        feature.validate(Feature.UPDATE);
611
                                        lastChangedFeature = null;
612
                                }
613
                                commands.insert(feature.getNotEditableCopy());
614
                                hasStrongChanges = true;
615
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
616
                                break;
617
                        }
618
                } catch (Exception e) {
619
                        throw new StoreInsertFeatureException(e, this.getName());
620
                }
621
        }
622

    
623
        synchronized public void update(EditableFeature feature)
624
                        throws DataException {
625
                try {
626
                        if ((feature).getSource() == null) {
627
                                insert(feature);
628
                                return;
629
                        }
630
                        checkInEditingMode();
631
                        checkIsOwnFeature(feature);
632
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
633
                        newVersionOfUpdate();
634
                        if (lastChangedFeature.getSource() != feature.getSource()) {
635
                                lastChangedFeature = feature;
636
                                feature.validate(Feature.UPDATE);
637
                                lastChangedFeature = null;
638
                        }
639

    
640
                        Feature oldf = feature.getSource();
641
                        Feature newf = feature.getNotEditableCopy();
642
                        commands.update(newf, oldf);
643

    
644
                        hasStrongChanges = true;
645
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
646
                } catch (Exception e) {
647
                        throw new StoreUpdateFeatureException(e, this.getName());
648
                }
649
        }
650

    
651
        synchronized public void redo() throws DataException {
652
                try {
653
                        checkInEditingMode();
654
                        Command redo = commands.getNextRedoCommand();
655
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
656
                        newVersionOfUpdate();
657
                        commands.redo();
658
                        hasStrongChanges = true;
659
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
660
                } catch (Exception e) {
661
                        throw new StoreRedoException(e, this.getName());
662
                }
663
        }
664

    
665
        synchronized public void undo() throws DataException {
666
                try {
667
                        checkInEditingMode();
668
                        Command undo = commands.getNextUndoCommand();
669
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
670
                        newVersionOfUpdate();
671
                        commands.undo();
672
                        hasStrongChanges = true;
673
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
674
                } catch (Exception e) {
675
                        throw new StoreUndoException(e, this.getName());
676
                }
677
        }
678

    
679
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
680
                checkInEditingMode();
681
                return commands;
682
        }
683

    
684
        synchronized public void cancelEditing() throws DataException {
685
                try {
686
                        checkInEditingMode();
687
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
688
                        exitEditingMode();
689
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
690
                } catch (Exception e) {
691
                        throw new StoreCancelEditingException(e, this.getName());
692
                }
693
        }
694

    
695
        synchronized public void finishEditing() throws DataException {
696
                try {
697
                        switch (mode) {
698
                        case MODE_QUERY:
699
                                throw new NeedEditingModeException(this.getName());
700

    
701
                        case MODE_APPEND:
702
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
703
                                provider.endAppend();
704
                                exitEditingMode();
705
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
706
                                break;
707

    
708
                        case MODE_FULLEDIT:
709
                                if (!hasStrongChanges) {
710
                                        performLightEditing();
711
                                        return;
712
                                }
713
                                if (!this.allowWrite()) {
714
                                        throw new WriteNotAllowedException(getName());
715
                                }
716

    
717
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
718
                                validateFeatures(Feature.FINISH_EDITING);
719
                                provider.performEditing(featureManager.getInserted(),
720
                                                featureManager.getUpdated(), featureManager
721
                                                                .getDeleted());
722
                                exitEditingMode();
723
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
724
                                break;
725
                        }
726
                } catch (Exception e) {
727
                        throw new FinishEditingException(e);
728
                }
729
        }
730

    
731
        private void performLightEditing() throws DataException {
732
                throw new NotYetImplemented(
733
                                "lightFinishEdition not yet implemented");
734

    
735
                // TODO: implementar
736
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
737
                // exitEditingMode();
738
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
739
        }
740

    
741

    
742
        public boolean isAppendModeSupported() {
743
                return this.provider.supportsAppendMode();
744
        }
745

    
746

    
747
        public void export(FeatureExplorer explorer, FeatureStoreParameters params)
748
                        throws DataException {
749

    
750
                if (this.getFeatureTypes().size() != 1) {
751
                        throw new NotYetImplemented(
752
                                        "export whith more than one type not yet implemented");
753
                }
754
                try {
755
                        FeatureType type = this.getDefaultFeatureType();
756
                        params.setDefaultFeatureType(type);
757
                        explorer.add(params);
758

    
759
                        DataManager manager = DALLocator.getDataManager();
760
                        FeatureStore target = (FeatureStore) manager
761
                                        .createStore(params);
762
                        target.edit();
763

    
764
                        FeatureSet features = this.getFeatureSet();
765
                        Iterator it1 = features.iterator();
766
                        while (it1.hasNext()) {
767
                                Feature feature = (Feature) it1.next();
768
                                target.insert(target.createNewFeature(type, feature));
769
                        }
770
                        features.dispose();
771
                        target.finishEditing();
772
                        target.dispose();
773
                } catch (Exception e) {
774
                        throw new DataExportException(e, params.toString());
775
                }
776
        }
777

    
778
        //
779
        // ====================================================================
780
        // Obtencion de datos
781
        // getDataCollection, getFeatureCollection
782
        //
783

    
784
        public DataSet getDataSet() throws DataException {
785
                checkNotInAppendMode();
786
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
787
                return new DefaultFeatureSet(this, query);
788
        }
789

    
790
        public DataSet getDataSet(DataQuery dataQuery)
791
                        throws DataException {
792
                checkNotInAppendMode();
793
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
794
        }
795

    
796
        public void getDataSet(Observer observer) throws DataException {
797
                checkNotInAppendMode();
798
                this.getFeatureSet(null, observer);
799
        }
800

    
801
        public void getDataSet(DataQuery dataQuery, Observer observer)
802
                        throws DataException {
803
                checkNotInAppendMode();
804
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
805
        }
806

    
807
        public FeatureSet getFeatureSet() throws DataException {
808
                checkNotInAppendMode();
809
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
810
                return new DefaultFeatureSet(this, query);
811
        }
812

    
813
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
814
                        throws DataException {
815
                checkNotInAppendMode();
816
                fixFeatureQuery(featureQuery);
817
                return new DefaultFeatureSet(this, featureQuery);
818
        }
819

    
820
        private void fixFeatureQuery(FeatureQuery featureQuery)
821
                        throws DataException {
822
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
823
                if (featureQuery.getAttributeNames() != null){
824
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
825
                                        .getFeatureType();
826
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
827
                                        .getAttributeNames()));
828
                }
829
        }
830

    
831
        public void getFeatureSet(Observer observer)
832
                        throws DataException {
833
                checkNotInAppendMode();
834
                this.getFeatureSet(null, observer);
835
        }
836

    
837
        public void getFeatureSet(FeatureQuery query, Observer observer)
838
                        throws DataException {
839
                class LoadInBackGround implements Runnable {
840
                        private FeatureStore store;
841
                        private FeatureQuery query;
842
                        private Observer observer;
843

    
844
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
845
                                        Observer observer) {
846
                                this.store = store;
847
                                this.query = query;
848
                                this.observer = observer;
849
                        }
850

    
851
                        public void run() {
852
                                try {
853
                                        FeatureSet collection = store.getFeatureSet(query);
854
                                        observer.update(
855
                                                        store,
856
                                                        new DefaultFeatureStoreNotification(
857
                                                                        store,
858
                                                                        FeatureStoreNotification.LOAD_FINISHED,
859
                                                                        collection
860
                                                                )
861
                                                );
862
                                } catch (Exception e) {
863
                                        observer.update(
864
                                                        store,
865
                                                        new DefaultFeatureStoreNotification(
866
                                                                        store,
867
                                                                        FeatureStoreNotification.LOAD_FINISHED,
868
                                                                        e
869
                                                                )
870
                                                );
871
                                }
872
                        }
873
                }
874

    
875
                checkNotInAppendMode();
876
                if (query == null) {
877
                        query = new FeatureQuery(this.getDefaultFeatureType());
878
                }
879
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
880
                Thread thread = new Thread(task);
881
                thread.run();
882
        }
883

    
884
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
885
                checkNotInAppendMode();
886
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
887
        }
888

    
889
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
890
                        throws DataException {
891
                checkNotInAppendMode();
892
                featureType = fixFeatureType((DefaultFeatureType) featureType);
893
                // TODO comprobar que el id es de este store
894

    
895
                if (this.mode == MODE_FULLEDIT) {
896
                        Feature f = featureManager.get(reference, this, featureType);
897
                        if (f!=null) {
898
                                return f;
899
                        }
900
                }
901
                return new DefaultFeature(this, this.provider
902
                                .getFeatureDataByReference((FeatureReferenceProviderServices) reference));
903
        }
904

    
905
        //
906
        // ====================================================================
907
        // Gestion de features
908
        //
909

    
910
        private FeatureType fixFeatureType(DefaultFeatureType type)
911
                        throws DataException {
912
                FeatureType defaultType = this.getDefaultFeatureType();
913
                if (type == null || type.equals(defaultType)) {
914
                        return defaultType;
915
                }
916
                if (type.isSubtypeOf(defaultType)) {
917
                        return type;
918
                }
919
                Iterator iter = this.getFeatureTypes().iterator();
920
                FeatureType tmpType;
921
                while (iter.hasNext()) {
922
                        tmpType = (FeatureType) iter.next();
923
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
924
                                return type;
925
                        }
926

    
927
                }
928
                throw new IllegalFeatureTypeException(getName());
929
        }
930

    
931
        public void validateFeatures(int mode) throws DataException {
932
                try {
933
                        checkNotInAppendMode();
934
                        FeatureSet collection = this.getFeatureSet();
935
                        Iterator iter = collection.iterator();
936
                        long previousVersionOfUpdate = currentVersionOfUpdate();
937
                        while (iter.hasNext()) {
938
                                ((DefaultFeature) iter.next()).validate(mode);
939
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
940
                                        throw new ConcurrentDataModificationException(getName());
941
                                }
942
                        }
943
                } catch (Exception e) {
944
                        throw new ValidateFeaturesException(e, getName());
945
                }
946
        }
947

    
948
        public FeatureType getDefaultFeatureType() throws DataException {
949
                try {
950
                        if (isEditing()) {
951
                                return featureTypeManager.getType(defaultFeatureType.getId());
952
                        }
953
                        return defaultFeatureType;
954
                } catch (Exception e) {
955
                        throw new GetFeatureTypeException(e, getName());
956
                }
957
        }
958

    
959
        public List getFeatureTypes() throws DataException {
960
                try {
961
                        List types;
962
                        if (isEditing()) {
963
                                types=new ArrayList();
964
                                Iterator it=featureTypes.iterator();
965
                                while (it.hasNext()) {
966
                                        FeatureType type = (FeatureType) it.next();
967
                                        type=featureTypeManager.getType(type.getId());
968
                                        if (type!=null) {
969
                                                types.add(type);
970
                                        }
971
                                }
972
                                it = featureTypeManager.newsIterator();
973
                                while (it.hasNext()) {
974
                                        FeatureType type = (FeatureType) it.next();
975
                                        types.add(type);
976
                                }
977
                        } else {
978
                                types = featureTypes;
979
                        }
980
                        return Collections.unmodifiableList(types);
981
                } catch (Exception e) {
982
                        throw new GetFeatureTypeException(e, getName());
983
                }
984
        }
985

    
986
        public Feature createFeature(FeatureData data)
987
                        throws DataException {
988
                DefaultFeature feature = new DefaultFeature(this, data);
989
                return feature;
990
        }
991

    
992
        public Feature createFeature(FeatureData data, FeatureType type)
993
                        throws DataException {
994
                // FIXME: falta por implementar
995
                // Comprobar si es un subtipo del feature de data
996
                // y construir un feature usando el subtipo.
997
                // Probablemente requiera generar una copia del data.
998
                throw new NotYetImplemented();
999
        }
1000

    
1001
        public EditableFeature createNewFeature(FeatureType type,
1002
                        Feature defaultValues)
1003
                        throws DataException {
1004
                try {
1005
                        type = this.fixFeatureType((DefaultFeatureType) type);
1006
                        FeatureData data = this.provider.createFeatureData(type);
1007
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1008
                                        data);
1009
                        feature.initializeValues(defaultValues);
1010
                        return feature;
1011
                } catch (Exception e) {
1012
                        throw new CreateFeatureException(e, getName());
1013
                }
1014
        }
1015

    
1016
        public EditableFeature createNewFeature(FeatureType type,
1017
                        boolean defaultValues)
1018
                        throws DataException {
1019
                try {
1020
                        type = this.fixFeatureType((DefaultFeatureType) type);
1021
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1022
                        if (defaultValues) {
1023
                                feature.initializeValues();
1024
                        }
1025
                        return feature;
1026
                } catch (Exception e) {
1027
                        throw new CreateFeatureException(e, getName());
1028
                }
1029
        }
1030

    
1031
        public EditableFeature createNewFeature(boolean defaultValues)
1032
                        throws DataException {
1033
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1034
        }
1035

    
1036
        public EditableFeature createNewFeature() throws DataException {
1037
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1038
        }
1039

    
1040
        public EditableFeatureType createFeatureType() {
1041
                return new DefaultEditableFeatureType();
1042
        }
1043

    
1044
        public boolean isLocksSupported() {
1045
                return this.provider.isLocksSupported();
1046
        }
1047

    
1048
        public Logger getLogger() {
1049
                return DefaultFeatureStore.logger;
1050
        }
1051

    
1052
        public FeatureIndex createIndex(FeatureType featureType,
1053
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1054
                checkNotInAppendMode();
1055
                FeatureIndexProviderServices index = null;
1056
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1057
                try {
1058
                        index.fill();
1059
                } catch (FeatureIndexException e) {
1060
                        throw new InitializeException(index.getName(), e);
1061
                }
1062
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1063
                return index;
1064
        }
1065

    
1066
        public void beginEditingGroup(String description)
1067
                        throws NeedEditingModeException {
1068
                checkInEditingMode();
1069
                commands.startComplex(description);
1070
        }
1071

    
1072
        public void endEditingGroup() throws NeedEditingModeException {
1073
                checkInEditingMode();
1074
                commands.endComplex();
1075
        }
1076
}