Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 24690

History | View | Annotate | Download (34.4 KB)

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

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

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

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

    
100
        private DelegateWeakReferencingObservable delegateObservable = new DelegateWeakReferencingObservable(this);
101

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

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

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

    
114
        private DefaultDataManager dataManager = null;
115

    
116
        private FeatureStoreProvider provider = null;
117

    
118
        private DefaultFeatureIndexes indexes;
119

    
120
        private DefaultFeatureStoreTransforms transforms;
121

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

    
131
        public DefaultFeatureStore() {
132

    
133
        }
134

    
135
        public DefaultFeatureStore(DefaultDataManager manager,
136
                        DataStoreParameters parameters, FeatureStoreProvider provider)
137
                        throws InitializeException {
138
                initialize(manager, parameters, provider);
139
        }
140

    
141
        private void initialize(DefaultDataManager manager,
142
                        DataStoreParameters parameters, FeatureStoreProvider provider)
143
                        throws InitializeException {
144
                this.dataManager = manager;
145
                this.provider = provider;
146
                this.parameters = parameters;
147
                this.transforms = new DefaultFeatureStoreTransforms(this);
148
                this.provider.initialize(this);
149
        }
150

    
151
        public Logger getLogger() {
152
                return DefaultFeatureStore.logger;
153
        }
154

    
155
        public String getName() {
156
                return this.parameters.getDataStoreName();
157
        }
158

    
159
        public DataStoreParameters getParameters() {
160
                return parameters;
161
        }
162

    
163
        public int getMode() {
164
                return this.mode;
165
        }
166

    
167
        public DefaultDataManager getManager() {
168
                return this.dataManager;
169
        }
170

    
171
        public Iterator getChildren() {
172
                return this.provider.getChilds();
173
        }
174

    
175
        public FeatureStoreProvider getProvider() {
176
                return this.provider;
177
        }
178

    
179
        public FeatureManager getFeatureManager() {
180
                return this.featureManager;
181
        }
182

    
183
        public void setFeatureTypes(List types, FeatureType defaultType) {
184
                this.featureTypes = types;
185
                this.defaultFeatureType = defaultType;
186
        }
187

    
188
        public void open() throws OpenException {
189
                // TODO: Se puede hacer un open estando en edicion ?
190
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
191
                this.provider.open();
192
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
193
        }
194

    
195
        public void refresh() throws OpenException, InitializeException {
196
                if (this.mode != MODE_QUERY) {
197
                        throw new IllegalStateException();
198
                }
199
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
200
                this.provider.refresh();
201
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
202
        }
203

    
204
        public void close() throws CloseException {
205
                // TODO: Se puede hacer un close estando en edicion ?
206
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
207
                this.provider.close();
208
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
209
        }
210

    
211
        public void dispose() throws CloseException {
212
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
213
                this.provider.dispose();
214
                if (this.selection != null) {
215
                        this.selection.dispose();
216
                        this.selection = null;
217
                }
218
                this.commands = null;
219

    
220
                if (this.locks != null) {
221
                        this.locks.dispose();
222
                        this.locks = null;
223
                }
224

    
225
                this.featureManager = null;
226
                this.spatialManager = null;
227

    
228
                this.parameters = null;
229
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
230
                this.delegateObservable.deleteObservers();
231
                this.delegateObservable = null;
232
        }
233

    
234
        public boolean allowWrite() {
235
                return this.provider.allowWrite();
236
        }
237

    
238
        public boolean canWriteGeometry(int geometryType) throws DataException {
239
                return this.provider.canWriteGeometry(geometryType);
240
        }
241

    
242
        public DataExplorer getExplorer() throws ReadException {
243
                return this.provider.getExplorer();
244
        }
245

    
246
        public Metadata getMetadata() throws BaseException {
247
                // TODO:
248
                // Si el provider devuelbe null habria que ver de construir aqui
249
                // los metadatos basicos, como el Envelope y el SRS.
250
                return this.provider.getMetadata();
251
        }
252

    
253
        public Envelope getEnvelope() {
254
                // FIXME: Y en edicion/append
255
                return this.provider.getEnvelope();
256
        }
257

    
258
        /**
259
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
260
         */
261
        public String getSRSDefaultGeometry() throws DataException {
262
                return this.getDefaultFeatureType().getDefaultSRS();
263
        }
264

    
265
        public FeatureSelection createDefaultFeatureSelection()
266
                        throws DataException {
267
                return new DefaultFeatureSelection(this);
268
        }
269

    
270
        public FeatureData createDefaultFeatureData(FeatureType type)
271
                        throws DataException {
272
                return new DefaultFeatureData(type);
273
        }
274

    
275
        public PersistentState getState()
276
                        throws PersistenceException {
277
                return AbstractPersistenceManager.getState(this);
278
        }
279

    
280
        public void loadState(PersistentState state) throws PersistenceException {
281
                state.setTheClass(this);
282
                state.set("dataStoreName", this.getName());
283
                state.set("parameters", this.parameters);
284
                state.set("provider", this.provider);
285
                state.set("selection", this.selection);
286
        }
287

    
288
        public void setState(PersistentState state) throws PersistenceException {
289
                if (this.provider != null) {
290
                        throw new PersistenceException(null);
291
                }
292
                if (this.getManager() == null) {
293
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
294
                }
295

    
296
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
297
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
298

    
299
                try {
300

    
301
                        initialize(this.getManager(), params, provider);
302
                        setSelection((FeatureSelection) state.get("selection"));
303

    
304
                } catch (InitializeException e) {
305
                        throw new PersistenceException(e);
306
                } catch (DataException e) {
307
                        throw new PersistenceException(e);
308
                }
309

    
310
        }
311

    
312
        //
313
        // ====================================================================
314
        // Gestion de la seleccion
315
        //
316

    
317
        public void setSelection(DataSet selection)
318
                        throws DataException {
319
                this.setSelection((FeatureSet) selection);
320
        }
321

    
322
        public DataSet createSelection() throws DataException {
323
                return createFeatureSelection();
324
        }
325

    
326
        public DataSet getSelection() throws DataException {
327
                return this.getFeatureSelection();
328
        }
329

    
330
        public void setSelection(FeatureSet selection)
331
                        throws DataException {
332
                if (selection.equals(this.selection)) {
333
                        return;
334
                }
335
                if (!selection.isFromStore(this)) {
336
                        throw new SelectionNotAllowedException(getName());
337
                }
338

    
339
                this.selection.deleteObserver(this);
340
                if (selection instanceof FeatureSelection) {
341
                        if (isEditing()) {
342
                                commands.selectionSet(this, this.selection,
343
                                                (FeatureSelection) selection);
344
                        }
345
                        this.selection = (FeatureSelection) selection;
346
                } else {
347
                        if (isEditing()) {
348
                                commands.startComplex("_selectionSet");
349
                        }
350
                        this.selection.deselectAll();
351
                        this.selection.select(selection);
352
                        if (isEditing()) {
353
                                commands.endComplex();
354
                        }
355
                }
356
                this.selection.addObserver(this);
357

    
358
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
359
        }
360

    
361
        public FeatureSelection createFeatureSelection() throws DataException {
362
                return this.provider.createFeatureSelection();
363
        }
364

    
365
        public FeatureSelection getFeatureSelection() throws DataException {
366
                if (selection == null) {
367
                        this.selection = createFeatureSelection();
368
                        this.selection.addObserver(this);
369
                }
370
                return selection;
371
        }
372

    
373
        //
374
        // ====================================================================
375
        // Gestion de notificaciones
376
        //
377

    
378
        public void notifyChange(String notification) {
379
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
380
                notification));
381

    
382
        }
383

    
384
        public void notifyChange(String notification, Feature feature) {
385
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
386
                                                this, notification, feature));
387
        }
388

    
389
        public void notifyChange(String notification, Command command) {
390
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
391
                                                this, notification, command));
392
        }
393

    
394
        public void notifyChange(String notification, EditableFeatureType type) {
395
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
396
                notification, type));
397
        }
398

    
399

    
400
        //
401
        // ====================================================================
402
        // Gestion de bloqueos
403
        //
404

    
405
        public boolean isLocksSupported() {
406
                return this.provider.isLocksSupported();
407
        }
408

    
409

    
410
        public FeatureSet getLocks() throws DataException {
411
                if (!this.provider.isLocksSupported()) {
412
                        getLogger().warn("Locks not supporteds");
413
                        return null;
414
                }
415
                if (locks == null) {
416
                        this.locks = this.provider.createFeatureLocks();
417
                }
418
                return locks;
419
        }
420

    
421
        //
422
        // ====================================================================
423
    // Interface Observable
424
        //
425

    
426
    public void disableNotifications() {
427
        this.delegateObservable.disableNotifications();
428

    
429
    }
430

    
431
    public void enableNotifications() {
432
        this.delegateObservable.enableNotifications();
433
    }
434

    
435
    public void beginComplexNotification() {
436
        this.delegateObservable.beginComplexNotification();
437

    
438
    }
439

    
440
    public void endComplexNotification() {
441
        this.delegateObservable.endComplexNotification();
442

    
443
    }
444

    
445
        public void addObserver(Observer observer) {
446
                this.delegateObservable.addObserver(observer);
447

    
448
        }
449

    
450
        public void deleteObserver(Observer observer) {
451
        this.delegateObservable.deleteObserver(observer);
452
        }
453

    
454
        public void deleteObservers() {
455
                this.delegateObservable.deleteObservers();
456

    
457
        }
458

    
459
        //
460
        // ====================================================================
461
        // Interface Observer
462
        //
463
        // Usado para observar:
464
        // - su seleccion
465
        // - sus bloqueos
466
        // - sus recursos
467
        //
468

    
469
        public void update(WeakReferencingObservable observable, Object notification) {
470
                if (observable instanceof FeatureSet) {
471
                        if (observable == this.selection) {
472
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
473
                        } else if (observable == this.locks) {
474
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
475
                        }
476

    
477
                }
478
        }
479

    
480

    
481
        //
482
        // ====================================================================
483
        // Gestion de operaciones
484
        // Interface ExtendedOperations
485
        //
486
        public Object invokeOperation(int code, OperationContext context)
487
                        throws OperationException, OperationNotSupportedException {
488
                return this.dataManager.getOperationManager().invokeOperation(this, code, context);
489
        }
490

    
491
        public Object invokeOperation(String name, OperationContext context)
492
                        throws OperationException, OperationNotSupportedException {
493
                return this.dataManager.getOperationManager().invokeOperation(this, name, context);
494
        }
495

    
496
        public boolean hasOperation(int code) {
497
                return this.dataManager.getOperationManager().hasOperation(this, code);
498
        }
499

    
500
        public boolean hasOperation(String name) {
501
                return this.dataManager.getOperationManager().hasOperation(this, name);
502
        }
503

    
504
        public Object getOperation(int code) throws OperationException {
505
                return this.dataManager.getOperationManager().getOperation(this, code);
506
        }
507

    
508
        public Object getOperation(String name) throws OperationException {
509
                return this.dataManager.getOperationManager().getOperation(this, name);
510
        }
511

    
512
        //
513
        // ====================================================================
514
        // Edicion
515
        //
516

    
517
        private void newVersionOfUpdate() {
518
                this.versionOfUpdate++;
519
        }
520

    
521
        private long currentVersionOfUpdate() {
522
                return this.versionOfUpdate;
523
        }
524

    
525
        private void checkInEditingMode()
526
                        throws NeedEditingModeException {
527
                if (mode != MODE_FULLEDIT) {
528
                        throw new NeedEditingModeException(this.getName());
529
                }
530
        }
531

    
532
        private void checkNotInAppendMode() throws IllegalStateException {
533
                if (mode == MODE_APPEND) {
534
                        throw new IllegalStateException(this.getName());
535
                }
536
        }
537

    
538
        private void checkIsOwnFeature(Feature feature)
539
                        throws IllegalFeatureException {
540
                if (((DefaultFeature) feature).getStore() != this) {
541
                        throw new IllegalFeatureException(this.getName());
542
                }
543
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
544
                // fixFeatureType((DefaultFeatureType) feature.getType());
545
        }
546

    
547
        private void exitEditingMode() {
548
                commands.clear();
549
                featureManager = null;
550
                spatialManager = null;
551
                featureTypeManager = null;
552
                commands = null;
553

    
554
                mode = MODE_QUERY;
555
                hasStrongChanges = true; // Lo deja a true por si las moscas
556
        }
557

    
558
        synchronized public void edit() throws DataException {
559
                edit(MODE_FULLEDIT);
560
        }
561

    
562
        synchronized public void edit(int mode) throws DataException {
563
                try {
564
                        if ( this.mode != MODE_QUERY ) {
565
                                throw new AlreadyEditingException(this.getName());
566
                        }
567
                        if (!this.provider.supportsAppendMode()) {
568
                                mode = MODE_FULLEDIT;
569
                        }
570
                        switch (mode) {
571
                        case MODE_QUERY:
572
                                throw new IllegalStateException(this.getName());
573

    
574
                        case MODE_FULLEDIT:
575
                                if (!this.transforms.isEmpty()) {
576
                                        throw new IllegalStateException(this.getName());
577
                                }
578
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
579
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
580
                                featureTypeManager = new FeatureTypeManager(
581
                                                new MemoryExpansionAdapter());
582
                                spatialManager = new SpatialManager();
583

    
584
                                commands = new FeatureCommandsRecord(featureManager,
585
                                                spatialManager, featureTypeManager);
586
                                this.mode = MODE_FULLEDIT;
587
                                hasStrongChanges = false;
588
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
589
                                break;
590
                        case MODE_APPEND:
591
                                if (!this.transforms.isEmpty()) {
592
                                        throw new IllegalStateException(this.getName());
593
                                }
594
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
595
                                this.provider.beginAppend();
596
                                this.mode = MODE_APPEND;
597
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
598
                                break;
599
                        }
600
                } catch (Exception e) {
601
                        throw new StoreEditException(e, this.getName());
602
                }
603
        }
604

    
605
        public boolean isEditing() {
606
                return mode == MODE_FULLEDIT;
607
        }
608

    
609
        public boolean isAppending() {
610
                return mode == MODE_APPEND;
611
        }
612

    
613
        synchronized public void update(EditableFeatureType type)
614
                        throws DataException {
615
                try {
616
                        checkInEditingMode();
617
                        if (type == null) {
618
                                throw new NullFeatureTypeException(getName());
619
                        }
620
                        // FIXME: Comprobar que es un featureType aceptable.
621
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
622
                        newVersionOfUpdate();
623

    
624
                        FeatureType oldt = type.getSource().getCopy();
625
                        FeatureType newt = type.getNotEditableCopy();
626
                        commands.update(newt, oldt);
627

    
628
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
629
                                hasStrongChanges = true;
630
                        }
631
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
632
                } catch (Exception e) {
633
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
634
                }
635
        }
636

    
637
        synchronized public void delete(Feature feature) throws DataException {
638
                try {
639
                        checkInEditingMode();
640
                        checkIsOwnFeature(feature);
641
                        if (feature instanceof EditableFeature) {
642
                                throw new StoreDeleteEditableFeatureException(getName());
643
                        }
644
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
645
                        this.commands.delete(feature);
646
                        newVersionOfUpdate();
647
                        hasStrongChanges = true;
648
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
649
                } catch (Exception e) {
650
                        throw new StoreDeleteFeatureException(e, this.getName());
651
                }
652
        }
653

    
654
        private static EditableFeature lastChangedFeature = null;
655

    
656
        synchronized public void insert(EditableFeature feature)
657
                        throws DataException {
658
                try {
659
                        switch (mode) {
660
                        case MODE_QUERY:
661
                                throw new NeedEditingModeException(this.getName());
662

    
663
                        case MODE_APPEND:
664
                                checkIsOwnFeature(feature);
665
                                if (feature.getSource() != null) {
666
                                        throw new NoNewFeatureInsertException(this.getName());
667
                                }
668
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
669
                                feature.validate(Feature.UPDATE);
670
                                provider.append(feature);
671
                                hasStrongChanges = true;
672
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
673
                                break;
674

    
675
                        case MODE_FULLEDIT:
676
                                checkIsOwnFeature(feature);
677
                                if (feature.getSource() != null) {
678
                                        throw new NoNewFeatureInsertException(this.getName());
679
                                }
680
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
681
                                newVersionOfUpdate();
682
                                if (lastChangedFeature.getSource() != feature.getSource()) {
683
                                        lastChangedFeature = feature;
684
                                        feature.validate(Feature.UPDATE);
685
                                        lastChangedFeature = null;
686
                                }
687
                                commands.insert(feature.getNotEditableCopy());
688
                                hasStrongChanges = true;
689
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
690
                                break;
691
                        }
692
                } catch (Exception e) {
693
                        throw new StoreInsertFeatureException(e, this.getName());
694
                }
695
        }
696

    
697
        synchronized public void update(EditableFeature feature)
698
                        throws DataException {
699
                try {
700
                        if ((feature).getSource() == null) {
701
                                insert(feature);
702
                                return;
703
                        }
704
                        checkInEditingMode();
705
                        checkIsOwnFeature(feature);
706
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
707
                        newVersionOfUpdate();
708
                        if (lastChangedFeature.getSource() != feature.getSource()) {
709
                                lastChangedFeature = feature;
710
                                feature.validate(Feature.UPDATE);
711
                                lastChangedFeature = null;
712
                        }
713

    
714
                        Feature oldf = feature.getSource();
715
                        Feature newf = feature.getNotEditableCopy();
716
                        commands.update(newf, oldf);
717

    
718
                        hasStrongChanges = true;
719
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
720
                } catch (Exception e) {
721
                        throw new StoreUpdateFeatureException(e, this.getName());
722
                }
723
        }
724

    
725
        synchronized public void redo() throws DataException {
726
                try {
727
                        checkInEditingMode();
728
                        Command redo = commands.getNextRedoCommand();
729
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
730
                        newVersionOfUpdate();
731
                        commands.redo();
732
                        hasStrongChanges = true;
733
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
734
                } catch (Exception e) {
735
                        throw new StoreRedoException(e, this.getName());
736
                }
737
        }
738

    
739
        synchronized public void undo() throws DataException {
740
                try {
741
                        checkInEditingMode();
742
                        Command undo = commands.getNextUndoCommand();
743
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
744
                        newVersionOfUpdate();
745
                        commands.undo();
746
                        hasStrongChanges = true;
747
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
748
                } catch (Exception e) {
749
                        throw new StoreUndoException(e, this.getName());
750
                }
751
        }
752

    
753
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
754
                checkInEditingMode();
755
                return commands;
756
        }
757

    
758
        synchronized public void cancelEditing() throws DataException {
759
                try {
760
                        checkInEditingMode();
761
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
762
                        exitEditingMode();
763
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
764
                } catch (Exception e) {
765
                        throw new StoreCancelEditingException(e, this.getName());
766
                }
767
        }
768

    
769
        synchronized public void finishEditing() throws DataException {
770
                try {
771
                        switch (mode) {
772
                        case MODE_QUERY:
773
                                throw new NeedEditingModeException(this.getName());
774

    
775
                        case MODE_APPEND:
776
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
777
                                provider.endAppend();
778
                                exitEditingMode();
779
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
780
                                break;
781

    
782
                        case MODE_FULLEDIT:
783
                                if (!hasStrongChanges) {
784
                                        performLightEditing();
785
                                        return;
786
                                }
787
                                if (!this.allowWrite()) {
788
                                        throw new WriteNotAllowedException(getName());
789
                                }
790

    
791
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
792
                                validateFeatures(Feature.FINISH_EDITING);
793
                                provider.performEditing(featureManager.getInserted(),
794
                                                featureManager.getUpdated(), featureManager
795
                                                                .getDeleted());
796
                                exitEditingMode();
797
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
798
                                break;
799
                        }
800
                } catch (Exception e) {
801
                        throw new FinishEditingException(e);
802
                }
803
        }
804

    
805
        private void performLightEditing() throws DataException {
806
                throw new NotYetImplemented(
807
                                "lightFinishEdition not yet implemented");
808

    
809
                // TODO: implementar
810
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
811
                // exitEditingMode();
812
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
813
        }
814

    
815

    
816
        public void beginEditingGroup(String description)
817
                        throws NeedEditingModeException {
818
                checkInEditingMode();
819
                commands.startComplex(description);
820
        }
821

    
822
        public void endEditingGroup() throws NeedEditingModeException {
823
                checkInEditingMode();
824
                commands.endComplex();
825
        }
826

    
827
        public boolean isAppendModeSupported() {
828
                return this.provider.supportsAppendMode();
829
        }
830

    
831

    
832
        public void export(DataExplorer explorer, NewFeatureStoreParameters params)
833
                        throws DataException {
834

    
835
                if (this.getFeatureTypes().size() != 1) {
836
                        throw new NotYetImplemented(
837
                                        "export whith more than one type not yet implemented");
838
                }
839
                try {
840
                        FeatureType type = this.getDefaultFeatureType();
841
                        if (params.getDefaultFeatureType() == null) {
842
                                params.setDefaultFeatureType(type);
843
                        }
844
                        explorer.add(params, false);
845

    
846
                        DataManager manager = DALLocator.getDataManager();
847
                        FeatureStore target = (FeatureStore) manager
848
                                        .createStore(params);
849
                        target.edit(MODE_APPEND);
850

    
851
                        FeatureSet features = this.getFeatureSet();
852
                        Iterator it1 = features.iterator();
853
                        while (it1.hasNext()) {
854
                                Feature feature = (Feature) it1.next();
855
                                target.insert(target.createNewFeature(type, feature));
856
                        }
857
                        features.dispose();
858
                        target.finishEditing();
859
                        target.dispose();
860
                } catch (Exception e) {
861
                        throw new DataExportException(e, params.toString());
862
                }
863
        }
864

    
865
        //
866
        // ====================================================================
867
        // Obtencion de datos
868
        // getDataCollection, getFeatureCollection
869
        //
870

    
871
        public DataSet getDataSet() throws DataException {
872
                checkNotInAppendMode();
873
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
874
                return new DefaultFeatureSet(this, query);
875
        }
876

    
877
        public DataSet getDataSet(DataQuery dataQuery)
878
                        throws DataException {
879
                checkNotInAppendMode();
880
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
881
        }
882

    
883
        public void getDataSet(Observer observer) throws DataException {
884
                checkNotInAppendMode();
885
                this.getFeatureSet(null, observer);
886
        }
887

    
888
        public void getDataSet(DataQuery dataQuery, Observer observer)
889
                        throws DataException {
890
                checkNotInAppendMode();
891
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
892
        }
893

    
894
        public FeatureSet getFeatureSet() throws DataException {
895
                checkNotInAppendMode();
896
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
897
                return new DefaultFeatureSet(this, query);
898
        }
899

    
900
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
901
                        throws DataException {
902
                checkNotInAppendMode();
903
                fixFeatureQuery(featureQuery);
904
                return new DefaultFeatureSet(this, featureQuery);
905
        }
906

    
907
        private void fixFeatureQuery(FeatureQuery featureQuery)
908
                        throws DataException {
909
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
910
                if (featureQuery.getAttributeNames() != null){
911
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
912
                                        .getFeatureType();
913
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
914
                                        .getAttributeNames()));
915
                }
916
        }
917

    
918
        public void getFeatureSet(Observer observer)
919
                        throws DataException {
920
                checkNotInAppendMode();
921
                this.getFeatureSet(null, observer);
922
        }
923

    
924
        public void getFeatureSet(FeatureQuery query, Observer observer)
925
                        throws DataException {
926
                class LoadInBackGround implements Runnable {
927
                        private FeatureStore store;
928
                        private FeatureQuery query;
929
                        private Observer observer;
930

    
931
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
932
                                        Observer observer) {
933
                                this.store = store;
934
                                this.query = query;
935
                                this.observer = observer;
936
                        }
937

    
938
                        public void run() {
939
                                try {
940
                                        FeatureSet collection = store.getFeatureSet(query);
941
                                        observer.update(
942
                                                        store,
943
                                                        new DefaultFeatureStoreNotification(
944
                                                                        store,
945
                                                                        FeatureStoreNotification.LOAD_FINISHED,
946
                                                                        collection
947
                                                                )
948
                                                );
949
                                } catch (Exception e) {
950
                                        observer.update(
951
                                                        store,
952
                                                        new DefaultFeatureStoreNotification(
953
                                                                        store,
954
                                                                        FeatureStoreNotification.LOAD_FINISHED,
955
                                                                        e
956
                                                                )
957
                                                );
958
                                }
959
                        }
960
                }
961

    
962
                checkNotInAppendMode();
963
                if (query == null) {
964
                        query = new FeatureQuery(this.getDefaultFeatureType());
965
                }
966
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
967
                Thread thread = new Thread(task);
968
                thread.run();
969
        }
970

    
971
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
972
                checkNotInAppendMode();
973
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
974
        }
975

    
976
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
977
                        throws DataException {
978
                checkNotInAppendMode();
979
                featureType = fixFeatureType((DefaultFeatureType) featureType);
980
                // TODO comprobar que el id es de este store
981

    
982
                if (this.mode == MODE_FULLEDIT) {
983
                        Feature f = featureManager.get(reference, this, featureType);
984
                        if (f!=null) {
985
                                return f;
986
                        }
987
                }
988
                return new DefaultFeature(this, this.provider
989
                                .getFeatureDataByReference((FeatureReferenceProviderServices) reference));
990
        }
991

    
992
        //
993
        // ====================================================================
994
        // Gestion de features
995
        //
996

    
997
        private FeatureType fixFeatureType(DefaultFeatureType type)
998
                        throws DataException {
999
                FeatureType defaultType = this.getDefaultFeatureType();
1000
                if (type == null || type.equals(defaultType)) {
1001
                        return defaultType;
1002
                }
1003
                if (type.isSubtypeOf(defaultType)) {
1004
                        return type;
1005
                }
1006
                Iterator iter = this.getFeatureTypes().iterator();
1007
                FeatureType tmpType;
1008
                while (iter.hasNext()) {
1009
                        tmpType = (FeatureType) iter.next();
1010
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
1011
                                return type;
1012
                        }
1013

    
1014
                }
1015
                throw new IllegalFeatureTypeException(getName());
1016
        }
1017

    
1018
        public void validateFeatures(int mode) throws DataException {
1019
                try {
1020
                        checkNotInAppendMode();
1021
                        FeatureSet collection = this.getFeatureSet();
1022
                        Iterator iter = collection.iterator();
1023
                        long previousVersionOfUpdate = currentVersionOfUpdate();
1024
                        while (iter.hasNext()) {
1025
                                ((DefaultFeature) iter.next()).validate(mode);
1026
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1027
                                        throw new ConcurrentDataModificationException(getName());
1028
                                }
1029
                        }
1030
                } catch (Exception e) {
1031
                        throw new ValidateFeaturesException(e, getName());
1032
                }
1033
        }
1034

    
1035
        public FeatureType getDefaultFeatureType() throws DataException {
1036
                try {
1037
                        if (isEditing()) {
1038
                                return featureTypeManager.getType(defaultFeatureType.getId());
1039
                        }
1040
                        FeatureType type = this.transforms.getDefaultFeatureType();
1041
                        if (type != null) {
1042
                                return type;
1043
                        }
1044
                        return defaultFeatureType;
1045
                } catch (Exception e) {
1046
                        throw new GetFeatureTypeException(e, getName());
1047
                }
1048
        }
1049

    
1050
        public List getFeatureTypes() throws DataException {
1051
                try {
1052
                        List types;
1053
                        if (isEditing()) {
1054
                                types=new ArrayList();
1055
                                Iterator it=featureTypes.iterator();
1056
                                while (it.hasNext()) {
1057
                                        FeatureType type = (FeatureType) it.next();
1058
                                        type=featureTypeManager.getType(type.getId());
1059
                                        if (type!=null) {
1060
                                                types.add(type);
1061
                                        }
1062
                                }
1063
                                it = featureTypeManager.newsIterator();
1064
                                while (it.hasNext()) {
1065
                                        FeatureType type = (FeatureType) it.next();
1066
                                        types.add(type);
1067
                                }
1068
                        } else {
1069
                                types = this.transforms.getFeatureTypes();
1070
                                if (types == null) {
1071
                                        types = featureTypes;
1072
                                }
1073
                        }
1074
                        return Collections.unmodifiableList(types);
1075
                } catch (Exception e) {
1076
                        throw new GetFeatureTypeException(e, getName());
1077
                }
1078
        }
1079

    
1080
        public Feature createFeature(FeatureData data)
1081
                        throws DataException {
1082
                DefaultFeature feature = new DefaultFeature(this, data);
1083
                return feature;
1084
        }
1085

    
1086
        public Feature createFeature(FeatureData data, FeatureType type)
1087
                        throws DataException {
1088
                // FIXME: falta por implementar
1089
                // Comprobar si es un subtipo del feature de data
1090
                // y construir un feature usando el subtipo.
1091
                // Probablemente requiera generar una copia del data.
1092
                throw new NotYetImplemented();
1093
        }
1094

    
1095
        public EditableFeature createNewFeature(FeatureType type,
1096
                        Feature defaultValues)
1097
                        throws DataException {
1098
                try {
1099
                        type = this.fixFeatureType((DefaultFeatureType) type);
1100
                        FeatureData data = this.provider.createFeatureData(type);
1101
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1102
                                        data);
1103
                        feature.initializeValues(defaultValues);
1104
                        return feature;
1105
                } catch (Exception e) {
1106
                        throw new CreateFeatureException(e, getName());
1107
                }
1108
        }
1109

    
1110
        public EditableFeature createNewFeature(FeatureType type,
1111
                        boolean defaultValues)
1112
                        throws DataException {
1113
                try {
1114
                        type = this.fixFeatureType((DefaultFeatureType) type);
1115
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1116
                        if (defaultValues) {
1117
                                feature.initializeValues();
1118
                        }
1119
                        return feature;
1120
                } catch (Exception e) {
1121
                        throw new CreateFeatureException(e, getName());
1122
                }
1123
        }
1124

    
1125
        public EditableFeature createNewFeature(boolean defaultValues)
1126
                        throws DataException {
1127
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1128
        }
1129

    
1130
        public EditableFeature createNewFeature() throws DataException {
1131
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1132
        }
1133

    
1134
        public EditableFeatureType createFeatureType() {
1135
                return new DefaultEditableFeatureType();
1136
        }
1137

    
1138
        //
1139
        // ====================================================================
1140
        // Index related methods
1141
        //
1142

    
1143
        public FeatureIndexes getIndexes() {
1144
                return this.indexes;
1145
        }
1146

    
1147
        public FeatureIndex createIndex(FeatureType featureType,
1148
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1149
                checkNotInAppendMode();
1150
                FeatureIndexProviderServices index = null;
1151
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1152
                try {
1153
                        index.fill();
1154
                } catch (FeatureIndexException e) {
1155
                        throw new InitializeException(index.getName(), e);
1156
                }
1157
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1158
                return index;
1159
        }
1160

    
1161
        //
1162
        // ====================================================================
1163
        // Transforms related methods
1164
        //
1165

    
1166
        public FeatureStoreTransforms getTransforms() {
1167
                return this.transforms;
1168
        }
1169

    
1170
        public FeatureQuery createFeatureQuery() {
1171
                return new FeatureQuery();
1172
        }
1173

    
1174
}