Statistics
| Revision:

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

History | View | Annotate | Download (32.8 KB)

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

    
3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.Iterator;
6
import java.util.List;
7

    
8
import org.gvsig.fmap.data.DALLocator;
9
import org.gvsig.fmap.data.DataExplorer;
10
import org.gvsig.fmap.data.DataManager;
11
import org.gvsig.fmap.data.DataQuery;
12
import org.gvsig.fmap.data.DataSet;
13
import org.gvsig.fmap.data.DataStoreNotification;
14
import org.gvsig.fmap.data.DataStoreParameters;
15
import org.gvsig.fmap.data.exceptions.CloseException;
16
import org.gvsig.fmap.data.exceptions.DataException;
17
import org.gvsig.fmap.data.exceptions.InitializeException;
18
import org.gvsig.fmap.data.exceptions.OpenException;
19
import org.gvsig.fmap.data.exceptions.ProviderNotRegisteredException;
20
import org.gvsig.fmap.data.exceptions.ReadException;
21
import org.gvsig.fmap.data.feature.Command;
22
import org.gvsig.fmap.data.feature.CommandsRecord;
23
import org.gvsig.fmap.data.feature.EditableFeature;
24
import org.gvsig.fmap.data.feature.EditableFeatureType;
25
import org.gvsig.fmap.data.feature.Feature;
26
import org.gvsig.fmap.data.feature.FeatureExplorer;
27
import org.gvsig.fmap.data.feature.FeatureIndex;
28
import org.gvsig.fmap.data.feature.FeatureIndexes;
29
import org.gvsig.fmap.data.feature.FeatureQuery;
30
import org.gvsig.fmap.data.feature.FeatureReference;
31
import org.gvsig.fmap.data.feature.FeatureSelection;
32
import org.gvsig.fmap.data.feature.FeatureSet;
33
import org.gvsig.fmap.data.feature.FeatureStore;
34
import org.gvsig.fmap.data.feature.FeatureStoreNotification;
35
import org.gvsig.fmap.data.feature.FeatureStoreParameters;
36
import org.gvsig.fmap.data.feature.FeatureType;
37
import org.gvsig.fmap.data.feature.exceptions.AlreadyEditingException;
38
import org.gvsig.fmap.data.feature.exceptions.ConcurrentDataModificationException;
39
import org.gvsig.fmap.data.feature.exceptions.CreateFeatureException;
40
import org.gvsig.fmap.data.feature.exceptions.DataExportException;
41
import org.gvsig.fmap.data.feature.exceptions.DataIndexException;
42
import org.gvsig.fmap.data.feature.exceptions.FinishEditingException;
43
import org.gvsig.fmap.data.feature.exceptions.GetFeatureTypeException;
44
import org.gvsig.fmap.data.feature.exceptions.IllegalFeatureException;
45
import org.gvsig.fmap.data.feature.exceptions.IllegalFeatureTypeException;
46
import org.gvsig.fmap.data.feature.exceptions.NeedEditingModeException;
47
import org.gvsig.fmap.data.feature.exceptions.NoNewFeatureInsertException;
48
import org.gvsig.fmap.data.feature.exceptions.NullFeatureTypeException;
49
import org.gvsig.fmap.data.feature.exceptions.SelectionNotAllowedException;
50
import org.gvsig.fmap.data.feature.exceptions.StoreCancelEditingException;
51
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteEditableFeatureException;
52
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteFeatureException;
53
import org.gvsig.fmap.data.feature.exceptions.StoreEditException;
54
import org.gvsig.fmap.data.feature.exceptions.StoreInsertFeatureException;
55
import org.gvsig.fmap.data.feature.exceptions.StoreRedoException;
56
import org.gvsig.fmap.data.feature.exceptions.StoreUndoException;
57
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureException;
58
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureTypeException;
59
import org.gvsig.fmap.data.feature.exceptions.ValidateFeaturesException;
60
import org.gvsig.fmap.data.feature.exceptions.WriteNotAllowedException;
61
import org.gvsig.fmap.data.feature.impl.commands.AbstractCommandsRecord;
62
import org.gvsig.fmap.data.feature.impl.commands.implementation.FeatureCommandsRecord;
63
import org.gvsig.fmap.data.feature.impl.expansionadapter.MemoryExpansionAdapter;
64
import org.gvsig.fmap.data.feature.impl.featureSet.DefaultFeatureSet;
65
import org.gvsig.fmap.data.feature.spi.DefaultFeatureData;
66
import org.gvsig.fmap.data.feature.spi.FeatureData;
67
import org.gvsig.fmap.data.feature.spi.FeatureLocks;
68
import org.gvsig.fmap.data.feature.spi.FeatureStoreProvider;
69
import org.gvsig.fmap.data.feature.spi.FeatureStoreProviderServices;
70
import org.gvsig.fmap.data.feature.spi.index.FeatureIndexProviderServices;
71
import org.gvsig.fmap.data.impl.DefaultDataManager;
72
import org.gvsig.fmap.geom.primitive.Envelope;
73
import org.gvsig.metadata.Metadata;
74
import org.gvsig.tools.exception.BaseException;
75
import org.gvsig.tools.exception.NotYetImplemented;
76
import org.gvsig.tools.observer.Observable;
77
import org.gvsig.tools.observer.Observer;
78
import org.gvsig.tools.observer.impl.DelegateObservable;
79
import org.gvsig.tools.operations.OperationContext;
80
import org.gvsig.tools.operations.OperationException;
81
import org.gvsig.tools.operations.OperationNotSupportedException;
82
import org.gvsig.tools.persistence.AbstractPersistenceManager;
83
import org.gvsig.tools.persistence.PersistenceException;
84
import org.gvsig.tools.persistence.PersistentState;
85
import org.slf4j.Logger;
86
import org.slf4j.LoggerFactory;
87

    
88
final public class DefaultFeatureStore implements
89
                FeatureStoreProviderServices,
90
                Observer {
91

    
92
    final static private Logger logger = LoggerFactory
93
            .getLogger(DefaultFeatureStore.class);
94

    
95
        private DataStoreParameters parameters = null;
96
        private FeatureSelection selection;
97
        private FeatureLocks locks;
98

    
99
        private DelegateObservable delegateObservable = new DelegateObservable(this);
100

    
101
        private AbstractCommandsRecord commands;
102
        private FeatureTypeManager featureTypeManager;
103
        private FeatureManager featureManager;
104
        private SpatialManager spatialManager;
105

    
106
        private FeatureType defaultFeatureType = null;
107
        private List featureTypes = new ArrayList();
108

    
109
        private int mode = MODE_QUERY;
110
        private long versionOfUpdate = 0;
111
        private boolean hasStrongChanges = true;
112

    
113
        private DefaultDataManager dataManager = null;
114

    
115
        private FeatureStoreProvider provider = null;
116

    
117
        private DefaultFeatureIndexes indexes;
118

    
119
        /*
120
         * TODO:
121
         *
122
         * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
123
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
124
         * featureType al que se le han cambiado las reglas de validacion cuando
125
         * hasStrongChanges=false.
126
         */
127

    
128
        public DefaultFeatureStore() {
129

    
130
        }
131

    
132
        public DefaultFeatureStore(DefaultDataManager manager,
133
                        DataStoreParameters parameters, FeatureStoreProvider provider)
134
                        throws InitializeException {
135
                initialize(manager, parameters, provider);
136
        }
137

    
138
        private void initialize(DefaultDataManager manager,
139
                        DataStoreParameters parameters, FeatureStoreProvider provider)
140
                        throws InitializeException {
141
                this.dataManager = manager;
142
                this.provider = provider;
143
                this.parameters = parameters;
144
                this.provider.initialize(this);
145
        }
146

    
147
        public String getName() {
148
                return this.parameters.getDataStoreName();
149
        }
150

    
151
        public DataStoreParameters getParameters() {
152
                return parameters;
153
        }
154

    
155
        public DefaultDataManager getManager() {
156
                return this.dataManager;
157
        }
158

    
159
        public Iterator getChilds() {
160
                return this.provider.getChilds();
161
        }
162

    
163
        public FeatureStoreProvider getProvider() {
164
                return this.provider;
165
        }
166

    
167
        public FeatureManager getFeatureManager() {
168
                return this.featureManager;
169
        }
170

    
171
        public void setFeatureTypes(List types, FeatureType defaultType) {
172
                this.featureTypes = types;
173
                this.defaultFeatureType = defaultType;
174
        }
175

    
176
        public void open() throws OpenException {
177
                // TODO: Se puede hacer un open estando en edicion ?
178
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
179
                this.provider.open();
180
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
181
        }
182

    
183
        public void refresh() throws OpenException, InitializeException {
184
                if (this.mode != MODE_QUERY) {
185
                        throw new IllegalStateException();
186
                }
187
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
188
                this.provider.refresh();
189
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
190
        }
191

    
192
        public void close() throws CloseException {
193
                // TODO: Se puede hacer un close estando en edicion ?
194
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
195
                this.provider.close();
196
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
197
        }
198

    
199
        public void dispose() throws CloseException {
200
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
201
                this.provider.dispose();
202
                if (this.selection != null) {
203
                        this.selection.dispose();
204
                        this.selection = null;
205
                }
206
                this.commands = null;
207

    
208
                if (this.locks != null) {
209
                        this.locks.dispose();
210
                        this.locks = null;
211
                }
212

    
213
                this.featureManager = null;
214
                this.spatialManager = null;
215

    
216
                this.parameters = null;
217
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
218
                this.delegateObservable.deleteObservers();
219
                this.delegateObservable = null;
220
        }
221

    
222
        public boolean allowWrite() {
223
                return this.provider.allowWrite();
224
        }
225

    
226
        public boolean canWriteGeometry(int geometryType) {
227
                return this.provider.canWriteGeometry(geometryType);
228
        }
229

    
230
        public DataExplorer getExplorer() throws ReadException {
231
                return this.provider.getExplorer();
232
        }
233

    
234
        public Metadata getMetadata() throws BaseException {
235
                // TODO:
236
                // Si el provider devuelbe null habria que ver de construir aqui
237
                // los metadatos basicos, como el Envelope y el SRS.
238
                return this.provider.getMetadata();
239
        }
240

    
241
        public Envelope getEnvelope() {
242
                // FIXME: Y en edicion/append
243
                return this.provider.getEnvelope();
244
        }
245

    
246
        public FeatureIndexes getIndexes() {
247
                return this.indexes;
248
        }
249

    
250
        /**
251
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
252
         */
253
        public String getSRSDefaultGeometry() throws DataException {
254
                return this.getDefaultFeatureType().getDefaultSRS();
255
        }
256

    
257
        public FeatureSelection createDefaultFeatureSelection()
258
                        throws DataException {
259
                return new DefaultFeatureSelection(this);
260
        }
261

    
262
        public FeatureData createDefaultFeatureData(FeatureType type)
263
                        throws DataException {
264
                return new DefaultFeatureData(type);
265
        }
266

    
267
        public PersistentState getState()
268
                        throws PersistenceException {
269
                return AbstractPersistenceManager.getState(this);
270
        }
271

    
272
        public void loadState(PersistentState state) throws PersistenceException {
273
                state.setTheClass(this);
274
                state.set("dataStoreName", this.getName());
275
                state.set("parameters", this.parameters);
276
                state.set("provider", this.provider);
277
                state.set("selection", this.selection);
278
        }
279

    
280
        public void setState(PersistentState state) throws PersistenceException {
281
                if (this.provider != null) {
282
                        throw new PersistenceException(null);
283
                }
284
                if (this.getManager() == null) {
285
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
286
                }
287

    
288
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
289
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
290

    
291
                try {
292

    
293
                        initialize(this.getManager(), params, provider);
294
                        setSelection((FeatureSelection) state.get("selection"));
295

    
296
                } catch (InitializeException e) {
297
                        throw new PersistenceException(e);
298
                } catch (DataException e) {
299
                        throw new PersistenceException(e);
300
                }
301

    
302
        }
303

    
304
        //
305
        // ====================================================================
306
        // Gestion de la seleccion
307
        //
308

    
309
        public void setSelection(DataSet selection)
310
                        throws DataException {
311
                this.setSelection((FeatureSet) selection);
312
        }
313

    
314
        public DataSet createSelection() throws DataException {
315
                return createFeatureSelection();
316
        }
317

    
318
        public DataSet getSelection() throws DataException {
319
                return this.getFeatureSelection();
320
        }
321

    
322
        public void setSelection(FeatureSet selection)
323
                        throws DataException {
324
                if (selection.equals(this.selection)) {
325
                        return;
326
                }
327
                if (!selection.isFromStore(this)) {
328
                        throw new SelectionNotAllowedException(getName());
329
                }
330

    
331
                this.selection.deleteObserver(this);
332
                if (selection instanceof FeatureSelection) {
333
                        this.selection = (FeatureSelection) selection;
334
                } else {
335
                        this.selection.deselectAll();
336
                        this.selection.select(selection);
337
                }
338
                this.selection.addObserver(this);
339

    
340
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
341
        }
342

    
343
        public FeatureSelection createFeatureSelection() throws DataException {
344
                return this.provider.createFeatureSelection();
345
        }
346

    
347
        public FeatureSelection getFeatureSelection() throws DataException {
348
                if (selection == null) {
349
                        this.selection = createFeatureSelection();
350
                        this.selection.addObserver(this);
351
                }
352
                return selection;
353
        }
354

    
355
        //
356
        // ====================================================================
357
        // Gestion de notificaciones
358
        //
359

    
360
        public void notifyChange(String notification) {
361
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
362
                notification));
363

    
364
        }
365

    
366
        public void notifyChange(String notification, Feature feature) {
367
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
368
                                                this, notification, feature));
369
        }
370

    
371
        public void notifyChange(String notification, Command command) {
372
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
373
                                                this, notification, command));
374
        }
375

    
376
        public void notifyChange(String notification, EditableFeatureType type) {
377
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
378
                notification, type));
379
        }
380

    
381

    
382
        //
383
        // ====================================================================
384
        // Gestion de bloqueos
385
        //
386

    
387

    
388
        public FeatureSet getLocks() throws DataException {
389
                if (!this.provider.isLocksSupported()) {
390
                        getLogger().warn("Locks not supporteds");
391
                        return null;
392
                }
393
                if (locks == null) {
394
                        this.locks = this.provider.createFeatureLocks();
395
                }
396
                return locks;
397
        }
398

    
399
        //
400
        // ====================================================================
401
    // Interface Observable
402
        //
403

    
404
    public void disableNotifications() {
405
        this.delegateObservable.disableNotifications();
406

    
407
    }
408

    
409
    public void enableNotifications() {
410
        this.delegateObservable.enableNotifications();
411
    }
412

    
413
    public void beginComplexNotification() {
414
        this.delegateObservable.beginComplexNotification();
415

    
416
    }
417

    
418
    public void endComplexNotification() {
419
        this.delegateObservable.endComplexNotification();
420

    
421
    }
422

    
423
        public void addObserver(Observer observer) {
424
                this.delegateObservable.addObserver(observer);
425

    
426
        }
427

    
428
        public void deleteObserver(Observer observer) {
429
        this.delegateObservable.deleteObserver(observer);
430
        }
431

    
432
        public void deleteObservers() {
433
                this.delegateObservable.deleteObservers();
434

    
435
        }
436

    
437
        //
438
        // ====================================================================
439
        // Interface Observer
440
        //
441
        // Usado para observar:
442
        // - su seleccion
443
        // - sus bloqueos
444
        // - sus recursos
445
        //
446

    
447
        public void update(Observable observable, Object notification) {
448
                if (observable instanceof FeatureSet) {
449
                        if (observable == this.selection) {
450
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
451
                        } else if (observable == this.locks) {
452
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
453
                        }
454

    
455
                }
456
        }
457

    
458

    
459
        //
460
        // ====================================================================
461
        // Gestion de operaciones
462
        // Interface ExtendedOperations
463
        //
464
        public Object invokeOperation(int code, OperationContext context)
465
                        throws OperationException, OperationNotSupportedException {
466
                return this.dataManager.getOperationManager().invokeOperation(this, code, context);
467
        }
468

    
469
        public Object invokeOperation(String name, OperationContext context)
470
                        throws OperationException, OperationNotSupportedException {
471
                return this.dataManager.getOperationManager().invokeOperation(this, name, context);
472
        }
473

    
474
        public boolean hasOperation(int code) {
475
                return this.dataManager.getOperationManager().hasOperation(this, code);
476
        }
477

    
478
        public boolean hasOperation(String name) {
479
                return this.dataManager.getOperationManager().hasOperation(this, name);
480
        }
481

    
482
        public Object getOperation(int code) throws OperationException {
483
                return this.dataManager.getOperationManager().getOperation(this, code);
484
        }
485

    
486
        public Object getOperation(String name) throws OperationException {
487
                return this.dataManager.getOperationManager().getOperation(this, name);
488
        }
489

    
490
        //
491
        // ====================================================================
492
        // Edicion
493
        //
494

    
495
        private void newVersionOfUpdate() {
496
                this.versionOfUpdate++;
497
        }
498

    
499
        private long currentVersionOfUpdate() {
500
                return this.versionOfUpdate;
501
        }
502

    
503
        private void checkInEditingMode()
504
                        throws NeedEditingModeException {
505
                if (mode != MODE_FULLEDIT) {
506
                        throw new NeedEditingModeException(this.getName());
507
                }
508
        }
509

    
510
        private void checkNotInAppendMode() throws IllegalStateException {
511
                if (mode == MODE_APPEND) {
512
                        throw new IllegalStateException(this.getName());
513
                }
514
        }
515

    
516
        private void checkIsOwnFeature(Feature feature)
517
                        throws IllegalFeatureException {
518
                if (((DefaultFeature) feature).getStore() != this) {
519
                        throw new IllegalFeatureException(this.getName());
520
                }
521
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
522
                // fixFeatureType((DefaultFeatureType) feature.getType());
523
        }
524

    
525
        private void exitEditingMode() {
526
                commands.clear();
527
                featureManager = null;
528
                spatialManager = null;
529
                featureTypeManager = null;
530
                commands = null;
531

    
532
                mode = MODE_QUERY;
533
                hasStrongChanges = true; // Lo deja a true por si las moscas
534
        }
535

    
536
        synchronized public void edit() throws DataException {
537
                edit(MODE_FULLEDIT);
538
        }
539

    
540
        synchronized public void edit(int mode) throws DataException {
541
                try {
542
                        if ( this.mode != MODE_QUERY ) {
543
                                throw new AlreadyEditingException(this.getName());
544
                        }
545
                        if (!this.provider.supportsAppendMode()) {
546
                                mode = MODE_FULLEDIT;
547
                        }
548
                        switch (mode) {
549
                        case MODE_QUERY:
550
                                throw new IllegalStateException(this.getName());
551

    
552
                        case MODE_FULLEDIT:
553
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
554
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
555
                                featureTypeManager = new FeatureTypeManager(
556
                                                new MemoryExpansionAdapter());
557
                                spatialManager = new SpatialManager();
558

    
559
                                commands = new FeatureCommandsRecord(featureManager,
560
                                                spatialManager, featureTypeManager);
561
                                this.mode = MODE_FULLEDIT;
562
                                hasStrongChanges = false;
563
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
564
                                break;
565
                        case MODE_APPEND:
566
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
567
                                this.provider.beginAppend();
568
                                this.mode = MODE_APPEND;
569
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
570
                                break;
571
                        }
572
                } catch (Exception e) {
573
                        throw new StoreEditException(e, this.getName());
574
                }
575
        }
576

    
577
        public boolean isEditing() {
578
                return mode == MODE_FULLEDIT;
579
        }
580

    
581
        public boolean isAppending() {
582
                return mode == MODE_APPEND;
583
        }
584

    
585
        synchronized public void update(EditableFeatureType type)
586
                        throws DataException {
587
                try {
588
                        checkInEditingMode();
589
                        if (type == null) {
590
                                throw new NullFeatureTypeException(getName());
591
                        }
592
                        // FIXME: Comprobar que es un featureType aceptable.
593
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
594
                        newVersionOfUpdate();
595

    
596
                        FeatureType oldt = type.getSource().getCopy();
597
                        FeatureType newt = type.getNotEditableCopy();
598
                        commands.update(newt, oldt);
599

    
600
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
601
                                hasStrongChanges = true;
602
                        }
603
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
604
                } catch (Exception e) {
605
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
606
                }
607
        }
608

    
609
        synchronized public void delete(Feature feature) throws DataException {
610
                try {
611
                        checkInEditingMode();
612
                        checkIsOwnFeature(feature);
613
                        if (feature instanceof EditableFeature) {
614
                                throw new StoreDeleteEditableFeatureException(getName());
615
                        }
616
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
617
                        this.commands.delete(feature);
618
                        newVersionOfUpdate();
619
                        hasStrongChanges = true;
620
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
621
                } catch (Exception e) {
622
                        throw new StoreDeleteFeatureException(e, this.getName());
623
                }
624
        }
625

    
626
        private static EditableFeature lastChangedFeature = null;
627

    
628
        synchronized public void insert(EditableFeature feature)
629
                        throws DataException {
630
                try {
631
                        switch (mode) {
632
                        case MODE_QUERY:
633
                                throw new NeedEditingModeException(this.getName());
634

    
635
                        case MODE_APPEND:
636
                                checkIsOwnFeature(feature);
637
                                if (feature.getSource() != null) {
638
                                        throw new NoNewFeatureInsertException(this.getName());
639
                                }
640
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
641
                                feature.validate(Feature.UPDATE);
642
                                provider.append(feature);
643
                                hasStrongChanges = true;
644
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
645
                                break;
646

    
647
                        case MODE_FULLEDIT:
648
                                checkIsOwnFeature(feature);
649
                                if (feature.getSource() != null) {
650
                                        throw new NoNewFeatureInsertException(this.getName());
651
                                }
652
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
653
                                newVersionOfUpdate();
654
                                if (lastChangedFeature.getSource() != feature.getSource()) {
655
                                        lastChangedFeature = feature;
656
                                        feature.validate(Feature.UPDATE);
657
                                        lastChangedFeature = null;
658
                                }
659
                                commands.insert(feature.getNotEditableCopy());
660
                                hasStrongChanges = true;
661
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
662
                                break;
663
                        }
664
                } catch (Exception e) {
665
                        throw new StoreInsertFeatureException(e, this.getName());
666
                }
667
        }
668

    
669
        synchronized public void update(EditableFeature feature)
670
                        throws DataException {
671
                try {
672
                        if ((feature).getSource() == null) {
673
                                insert(feature);
674
                                return;
675
                        }
676
                        checkInEditingMode();
677
                        checkIsOwnFeature(feature);
678
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
679
                        newVersionOfUpdate();
680
                        if (lastChangedFeature.getSource() != feature.getSource()) {
681
                                lastChangedFeature = feature;
682
                                feature.validate(Feature.UPDATE);
683
                                lastChangedFeature = null;
684
                        }
685

    
686
                        Feature oldf = feature.getSource();
687
                        Feature newf = feature.getNotEditableCopy();
688
                        commands.update(newf, oldf);
689

    
690
                        hasStrongChanges = true;
691
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
692
                } catch (Exception e) {
693
                        throw new StoreUpdateFeatureException(e, this.getName());
694
                }
695
        }
696

    
697
        synchronized public void redo() throws DataException {
698
                try {
699
                        checkInEditingMode();
700
                        Command redo = commands.getNextRedoCommand();
701
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
702
                        newVersionOfUpdate();
703
                        commands.redo();
704
                        hasStrongChanges = true;
705
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
706
                } catch (Exception e) {
707
                        throw new StoreRedoException(e, this.getName());
708
                }
709
        }
710

    
711
        synchronized public void undo() throws DataException {
712
                try {
713
                        checkInEditingMode();
714
                        Command undo = commands.getNextUndoCommand();
715
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
716
                        newVersionOfUpdate();
717
                        commands.undo();
718
                        hasStrongChanges = true;
719
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
720
                } catch (Exception e) {
721
                        throw new StoreUndoException(e, this.getName());
722
                }
723
        }
724

    
725
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
726
                checkInEditingMode();
727
                return commands;
728
        }
729

    
730
        synchronized public void cancelEditing() throws DataException {
731
                try {
732
                        checkInEditingMode();
733
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
734
                        exitEditingMode();
735
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
736
                } catch (Exception e) {
737
                        throw new StoreCancelEditingException(e, this.getName());
738
                }
739
        }
740

    
741
        synchronized public void finishEditing() throws DataException {
742
                try {
743
                        switch (mode) {
744
                        case MODE_QUERY:
745
                                throw new NeedEditingModeException(this.getName());
746

    
747
                        case MODE_APPEND:
748
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
749
                                provider.endAppend();
750
                                exitEditingMode();
751
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
752
                                break;
753

    
754
                        case MODE_FULLEDIT:
755
                                if (!hasStrongChanges) {
756
                                        performLightEditing();
757
                                        return;
758
                                }
759
                                if (!this.allowWrite()) {
760
                                        throw new WriteNotAllowedException(getName());
761
                                }
762

    
763
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
764
                                validateFeatures(Feature.FINISH_EDITING);
765
                                provider.performEditing(featureManager.getInserted(),
766
                                                featureManager.getUpdated(), featureManager
767
                                                                .getDeleted());
768
                                exitEditingMode();
769
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
770
                                break;
771
                        }
772
                } catch (Exception e) {
773
                        throw new FinishEditingException(e);
774
                }
775
        }
776

    
777
        private void performLightEditing() throws DataException {
778
                throw new NotYetImplemented(
779
                                "lightFinishEdition not yet implemented");
780

    
781
                // TODO: implementar
782
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
783
                // exitEditingMode();
784
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
785
        }
786

    
787

    
788
        public boolean isAppendModeSupported() {
789
                return this.provider.supportsAppendMode();
790
        }
791

    
792

    
793
        public void export(FeatureExplorer explorer, FeatureStoreParameters params)
794
                        throws DataException {
795

    
796
                if (this.getFeatureTypes().size() != 1) {
797
                        throw new NotYetImplemented(
798
                                        "export whith more than one type not yet implemented");
799
                }
800
                try {
801
                        FeatureType type = this.getDefaultFeatureType();
802
                        params.setDefaultFeatureType(type);
803
                        explorer.add(params);
804

    
805
                        DataManager manager = DALLocator.getDataManager();
806
                        FeatureStore target = (FeatureStore) manager
807
                                        .createStore(params);
808
                        target.edit();
809

    
810
                        FeatureSet features = this.getFeatureSet();
811
                        Iterator it1 = features.iterator();
812
                        while (it1.hasNext()) {
813
                                Feature feature = (Feature) it1.next();
814
                                target.insert(target.createNewFeature(type, feature));
815
                        }
816
                        features.dispose();
817
                        target.finishEditing();
818
                        target.dispose();
819
                } catch (Exception e) {
820
                        throw new DataExportException(e, params.toString());
821
                }
822
        }
823

    
824
        //
825
        // ====================================================================
826
        // Obtencion de datos
827
        // getDataCollection, getFeatureCollection
828
        //
829

    
830
        public DataSet getDataSet() throws DataException {
831
                checkNotInAppendMode();
832
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
833
                return new DefaultFeatureSet(this, query);
834
        }
835

    
836
        public DataSet getDataSet(DataQuery dataQuery)
837
                        throws DataException {
838
                checkNotInAppendMode();
839
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
840
        }
841

    
842
        public void getDataSet(Observer observer) throws DataException {
843
                checkNotInAppendMode();
844
                this.getFeatureSet(null, observer);
845
        }
846

    
847
        public void getDataSet(DataQuery dataQuery, Observer observer)
848
                        throws DataException {
849
                checkNotInAppendMode();
850
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
851
        }
852

    
853
        public FeatureSet getFeatureSet() throws DataException {
854
                checkNotInAppendMode();
855
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
856
                return new DefaultFeatureSet(this, query);
857
        }
858

    
859
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
860
                        throws DataException {
861
                checkNotInAppendMode();
862
                fixFeatureQuery(featureQuery);
863
                return new DefaultFeatureSet(this, featureQuery);
864
        }
865

    
866
        private void fixFeatureQuery(FeatureQuery featureQuery)
867
                        throws DataException {
868
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
869
                if (featureQuery.getAttributeNames() != null){
870
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
871
                                        .getFeatureType();
872
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
873
                                        .getAttributeNames()));
874
                }
875
        }
876

    
877
        public void getFeatureSet(Observer observer)
878
                        throws DataException {
879
                checkNotInAppendMode();
880
                this.getFeatureSet(null, observer);
881
        }
882

    
883
        public void getFeatureSet(FeatureQuery query, Observer observer)
884
                        throws DataException {
885
                class LoadInBackGround implements Runnable {
886
                        private FeatureStore store;
887
                        private FeatureQuery query;
888
                        private Observer observer;
889

    
890
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
891
                                        Observer observer) {
892
                                this.store = store;
893
                                this.query = query;
894
                                this.observer = observer;
895
                        }
896

    
897
                        public void run() {
898
                                try {
899
                                        FeatureSet collection = store.getFeatureSet(query);
900
                                        observer.update(
901
                                                        store,
902
                                                        new DefaultFeatureStoreNotification(
903
                                                                        store,
904
                                                                        FeatureStoreNotification.LOAD_FINISHED,
905
                                                                        collection
906
                                                                )
907
                                                );
908
                                } catch (Exception e) {
909
                                        observer.update(
910
                                                        store,
911
                                                        new DefaultFeatureStoreNotification(
912
                                                                        store,
913
                                                                        FeatureStoreNotification.LOAD_FINISHED,
914
                                                                        e
915
                                                                )
916
                                                );
917
                                }
918
                        }
919
                }
920

    
921
                checkNotInAppendMode();
922
                if (query == null) {
923
                        query = new FeatureQuery(this.getDefaultFeatureType());
924
                }
925
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
926
                Thread thread = new Thread(task);
927
                thread.run();
928
        }
929

    
930
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
931
                checkNotInAppendMode();
932
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
933
        }
934

    
935
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
936
                        throws DataException {
937
                checkNotInAppendMode();
938
                featureType = fixFeatureType((DefaultFeatureType) featureType);
939
                // TODO comprobar que el id es de este store
940

    
941
                if (this.mode == MODE_FULLEDIT) {
942
                        Feature f = featureManager.get(reference, this, featureType);
943
                        if (f!=null) {
944
                                return f;
945
                        }
946
                }
947
                return this.createFeature(featureType, this.provider
948
                                .getFeatureDataByReference(reference, featureType));
949
        }
950

    
951
        //
952
        // ====================================================================
953
        // Gestion de features
954
        //
955

    
956
        private FeatureType fixFeatureType(DefaultFeatureType type)
957
                        throws DataException {
958
                FeatureType defaultType = this.getDefaultFeatureType();
959
                if (type == null || type.equals(defaultType)) {
960
                        return defaultType;
961
                }
962
                if (type.isSubtypeOf(defaultType)) {
963
                        return type;
964
                }
965
                Iterator iter = this.getFeatureTypes().iterator();
966
                FeatureType tmpType;
967
                while (iter.hasNext()) {
968
                        tmpType = (FeatureType) iter.next();
969
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
970
                                return type;
971
                        }
972

    
973
                }
974
                throw new IllegalFeatureTypeException(getName());
975
        }
976

    
977
        public void validateFeatures(int mode) throws DataException {
978
                try {
979
                        checkNotInAppendMode();
980
                        FeatureSet collection = this.getFeatureSet();
981
                        Iterator iter = collection.iterator();
982
                        long previousVersionOfUpdate = currentVersionOfUpdate();
983
                        while (iter.hasNext()) {
984
                                ((DefaultFeature) iter.next()).validate(mode);
985
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
986
                                        throw new ConcurrentDataModificationException(getName());
987
                                }
988
                        }
989
                } catch (Exception e) {
990
                        throw new ValidateFeaturesException(e, getName());
991
                }
992
        }
993

    
994
        public FeatureType getDefaultFeatureType() throws DataException {
995
                try {
996
                        if (isEditing()) {
997
                                return featureTypeManager.getType(defaultFeatureType.getId());
998
                        }
999
                        return defaultFeatureType;
1000
                } catch (Exception e) {
1001
                        throw new GetFeatureTypeException(e, getName());
1002
                }
1003
        }
1004

    
1005
        public List getFeatureTypes() throws DataException {
1006
                try {
1007
                        List types;
1008
                        if (isEditing()) {
1009
                                types=new ArrayList();
1010
                                Iterator it=featureTypes.iterator();
1011
                                while (it.hasNext()) {
1012
                                        FeatureType type = (FeatureType) it.next();
1013
                                        type=featureTypeManager.getType(type.getId());
1014
                                        if (type!=null) {
1015
                                                types.add(type);
1016
                                        }
1017
                                }
1018
                                it = featureTypeManager.newsIterator();
1019
                                while (it.hasNext()) {
1020
                                        FeatureType type = (FeatureType) it.next();
1021
                                        types.add(type);
1022
                                }
1023
                        } else {
1024
                                types = featureTypes;
1025
                        }
1026
                        return Collections.unmodifiableList(types);
1027
                } catch (Exception e) {
1028
                        throw new GetFeatureTypeException(e, getName());
1029
                }
1030
        }
1031

    
1032
        public Feature createFeature(FeatureData data)
1033
                        throws DataException {
1034
                DefaultFeature feature = new DefaultFeature(this, data);
1035
                return feature;
1036
        }
1037

    
1038
        /**
1039
         * @deprecated
1040
         */
1041
        public Feature createFeature(FeatureType type, FeatureData data)
1042
                        throws DataException {
1043
                // FIXME: falta por implementar
1044
                // Comprobar si es un subtipo del feature de data
1045
                // y construir un feature usando el subtipo.
1046
                // Probablemente requiera generar una copia del data.
1047
                return null;
1048
        }
1049

    
1050
        public EditableFeature createNewFeature(FeatureType type,
1051
                        Feature defaultValues)
1052
                        throws DataException {
1053
                try {
1054
                        type = this.fixFeatureType((DefaultFeatureType) type);
1055
                        FeatureData data = this.provider.createNewFeatureData(type);
1056
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1057
                                        data);
1058
                        feature.initializeValues(defaultValues);
1059
                        return feature;
1060
                } catch (Exception e) {
1061
                        throw new CreateFeatureException(e, getName());
1062
                }
1063
        }
1064

    
1065
        public EditableFeature createNewFeature(FeatureType type,
1066
                        boolean defaultValues)
1067
                        throws DataException {
1068
                try {
1069
                        type = this.fixFeatureType((DefaultFeatureType) type);
1070
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1071
                        if (defaultValues) {
1072
                                feature.initializeValues();
1073
                        }
1074
                        return feature;
1075
                } catch (Exception e) {
1076
                        throw new CreateFeatureException(e, getName());
1077
                }
1078
        }
1079

    
1080
        public EditableFeature createNewFeature(boolean defaultValues)
1081
                        throws DataException {
1082
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1083
        }
1084

    
1085
        public EditableFeature createNewFeature() throws DataException {
1086
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1087
        }
1088

    
1089
        public EditableFeatureType createFeatureType() {
1090
                return new DefaultEditableFeatureType();
1091
        }
1092

    
1093
        public boolean isLocksSupported() {
1094
                return this.provider.isLocksSupported();
1095
        }
1096

    
1097
        public Logger getLogger() {
1098
                return DefaultFeatureStore.logger;
1099
        }
1100

    
1101
        public FeatureIndex createIndex(FeatureType featureType,
1102
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1103
                checkNotInAppendMode();
1104
                FeatureIndexProviderServices index = null;
1105
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1106
                try {
1107
                        index.fill();
1108
                } catch (DataIndexException e) {
1109
                        throw new InitializeException(index.getName(), e);
1110
                }
1111
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1112
                return index;
1113
        }
1114

    
1115

    
1116
}