Statistics
| Revision:

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

History | View | Annotate | Download (33.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.exceptions.CloseException;
16
import org.gvsig.fmap.dal.exceptions.DataException;
17
import org.gvsig.fmap.dal.exceptions.InitializeException;
18
import org.gvsig.fmap.dal.exceptions.OpenException;
19
import org.gvsig.fmap.dal.exceptions.ProviderNotRegisteredException;
20
import org.gvsig.fmap.dal.exceptions.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.FeatureExplorer;
27
import org.gvsig.fmap.dal.feature.FeatureIndex;
28
import org.gvsig.fmap.dal.feature.FeatureIndexes;
29
import org.gvsig.fmap.dal.feature.FeatureQuery;
30
import org.gvsig.fmap.dal.feature.FeatureReference;
31
import org.gvsig.fmap.dal.feature.FeatureSelection;
32
import org.gvsig.fmap.dal.feature.FeatureSet;
33
import org.gvsig.fmap.dal.feature.FeatureStore;
34
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
35
import org.gvsig.fmap.dal.feature.FeatureStoreParameters;
36
import org.gvsig.fmap.dal.feature.FeatureType;
37
import org.gvsig.fmap.dal.feature.exceptions.AlreadyEditingException;
38
import org.gvsig.fmap.dal.feature.exceptions.ConcurrentDataModificationException;
39
import org.gvsig.fmap.dal.feature.exceptions.CreateFeatureException;
40
import org.gvsig.fmap.dal.feature.exceptions.DataExportException;
41
import org.gvsig.fmap.dal.feature.exceptions.FeatureIndexException;
42
import org.gvsig.fmap.dal.feature.exceptions.FinishEditingException;
43
import org.gvsig.fmap.dal.feature.exceptions.GetFeatureTypeException;
44
import org.gvsig.fmap.dal.feature.exceptions.IllegalFeatureException;
45
import org.gvsig.fmap.dal.feature.exceptions.IllegalFeatureTypeException;
46
import org.gvsig.fmap.dal.feature.exceptions.NeedEditingModeException;
47
import org.gvsig.fmap.dal.feature.exceptions.NoNewFeatureInsertException;
48
import org.gvsig.fmap.dal.feature.exceptions.NullFeatureTypeException;
49
import org.gvsig.fmap.dal.feature.exceptions.SelectionNotAllowedException;
50
import org.gvsig.fmap.dal.feature.exceptions.StoreCancelEditingException;
51
import org.gvsig.fmap.dal.feature.exceptions.StoreDeleteEditableFeatureException;
52
import org.gvsig.fmap.dal.feature.exceptions.StoreDeleteFeatureException;
53
import org.gvsig.fmap.dal.feature.exceptions.StoreEditException;
54
import org.gvsig.fmap.dal.feature.exceptions.StoreInsertFeatureException;
55
import org.gvsig.fmap.dal.feature.exceptions.StoreRedoException;
56
import org.gvsig.fmap.dal.feature.exceptions.StoreUndoException;
57
import org.gvsig.fmap.dal.feature.exceptions.StoreUpdateFeatureException;
58
import org.gvsig.fmap.dal.feature.exceptions.StoreUpdateFeatureTypeException;
59
import org.gvsig.fmap.dal.feature.exceptions.ValidateFeaturesException;
60
import org.gvsig.fmap.dal.feature.exceptions.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
        /*
121
         * TODO:
122
         *
123
         * - Comprobar que solo se pueden a�adir reglas de validacion sobre un
124
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
125
         * featureType al que se le han cambiado las reglas de validacion cuando
126
         * hasStrongChanges=false.
127
         */
128

    
129
        public DefaultFeatureStore() {
130

    
131
        }
132

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
292
                try {
293

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

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

    
303
        }
304

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

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

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

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

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

    
332
                this.selection.deleteObserver(this);
333
                if (selection instanceof FeatureSelection) {
334
                        if (isEditing()) {
335
                                commands.selectionSet(this, this.selection,
336
                                                (FeatureSelection) selection);
337
                        }
338
                        this.selection = (FeatureSelection) selection;
339
                } else {
340
                        if (isEditing()) {
341
                                commands.startComplex("_selectionSet");
342
                        }
343
                        this.selection.deselectAll();
344
                        this.selection.select(selection);
345
                        if (isEditing()) {
346
                                commands.endComplex();
347
                        }
348
                }
349
                this.selection.addObserver(this);
350

    
351
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
352
        }
353

    
354
        public FeatureSelection createFeatureSelection() throws DataException {
355
                return this.provider.createFeatureSelection();
356
        }
357

    
358
        public FeatureSelection getFeatureSelection() throws DataException {
359
                if (selection == null) {
360
                        this.selection = createFeatureSelection();
361
                        this.selection.addObserver(this);
362
                }
363
                return selection;
364
        }
365

    
366
        //
367
        // ====================================================================
368
        // Gestion de notificaciones
369
        //
370

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

    
375
        }
376

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

    
382
        public void notifyChange(String notification, Command command) {
383
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
384
                                                this, notification, command));
385
        }
386

    
387
        public void notifyChange(String notification, EditableFeatureType type) {
388
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
389
                notification, type));
390
        }
391

    
392

    
393
        //
394
        // ====================================================================
395
        // Gestion de bloqueos
396
        //
397

    
398

    
399
        public FeatureSet getLocks() throws DataException {
400
                if (!this.provider.isLocksSupported()) {
401
                        getLogger().warn("Locks not supporteds");
402
                        return null;
403
                }
404
                if (locks == null) {
405
                        this.locks = this.provider.createFeatureLocks();
406
                }
407
                return locks;
408
        }
409

    
410
        //
411
        // ====================================================================
412
    // Interface Observable
413
        //
414

    
415
    public void disableNotifications() {
416
        this.delegateObservable.disableNotifications();
417

    
418
    }
419

    
420
    public void enableNotifications() {
421
        this.delegateObservable.enableNotifications();
422
    }
423

    
424
    public void beginComplexNotification() {
425
        this.delegateObservable.beginComplexNotification();
426

    
427
    }
428

    
429
    public void endComplexNotification() {
430
        this.delegateObservable.endComplexNotification();
431

    
432
    }
433

    
434
        public void addObserver(Observer observer) {
435
                this.delegateObservable.addObserver(observer);
436

    
437
        }
438

    
439
        public void deleteObserver(Observer observer) {
440
        this.delegateObservable.deleteObserver(observer);
441
        }
442

    
443
        public void deleteObservers() {
444
                this.delegateObservable.deleteObservers();
445

    
446
        }
447

    
448
        //
449
        // ====================================================================
450
        // Interface Observer
451
        //
452
        // Usado para observar:
453
        // - su seleccion
454
        // - sus bloqueos
455
        // - sus recursos
456
        //
457

    
458
        public void update(WeakReferencingObservable observable, Object notification) {
459
                if (observable instanceof FeatureSet) {
460
                        if (observable == this.selection) {
461
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
462
                        } else if (observable == this.locks) {
463
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
464
                        }
465

    
466
                }
467
        }
468

    
469

    
470
        //
471
        // ====================================================================
472
        // Gestion de operaciones
473
        // Interface ExtendedOperations
474
        //
475
        public Object invokeOperation(int code, OperationContext context)
476
                        throws OperationException, OperationNotSupportedException {
477
                return this.dataManager.getOperationManager().invokeOperation(this, code, context);
478
        }
479

    
480
        public Object invokeOperation(String name, OperationContext context)
481
                        throws OperationException, OperationNotSupportedException {
482
                return this.dataManager.getOperationManager().invokeOperation(this, name, context);
483
        }
484

    
485
        public boolean hasOperation(int code) {
486
                return this.dataManager.getOperationManager().hasOperation(this, code);
487
        }
488

    
489
        public boolean hasOperation(String name) {
490
                return this.dataManager.getOperationManager().hasOperation(this, name);
491
        }
492

    
493
        public Object getOperation(int code) throws OperationException {
494
                return this.dataManager.getOperationManager().getOperation(this, code);
495
        }
496

    
497
        public Object getOperation(String name) throws OperationException {
498
                return this.dataManager.getOperationManager().getOperation(this, name);
499
        }
500

    
501
        //
502
        // ====================================================================
503
        // Edicion
504
        //
505

    
506
        private void newVersionOfUpdate() {
507
                this.versionOfUpdate++;
508
        }
509

    
510
        private long currentVersionOfUpdate() {
511
                return this.versionOfUpdate;
512
        }
513

    
514
        private void checkInEditingMode()
515
                        throws NeedEditingModeException {
516
                if (mode != MODE_FULLEDIT) {
517
                        throw new NeedEditingModeException(this.getName());
518
                }
519
        }
520

    
521
        private void checkNotInAppendMode() throws IllegalStateException {
522
                if (mode == MODE_APPEND) {
523
                        throw new IllegalStateException(this.getName());
524
                }
525
        }
526

    
527
        private void checkIsOwnFeature(Feature feature)
528
                        throws IllegalFeatureException {
529
                if (((DefaultFeature) feature).getStore() != this) {
530
                        throw new IllegalFeatureException(this.getName());
531
                }
532
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
533
                // fixFeatureType((DefaultFeatureType) feature.getType());
534
        }
535

    
536
        private void exitEditingMode() {
537
                commands.clear();
538
                featureManager = null;
539
                spatialManager = null;
540
                featureTypeManager = null;
541
                commands = null;
542

    
543
                mode = MODE_QUERY;
544
                hasStrongChanges = true; // Lo deja a true por si las moscas
545
        }
546

    
547
        synchronized public void edit() throws DataException {
548
                edit(MODE_FULLEDIT);
549
        }
550

    
551
        synchronized public void edit(int mode) throws DataException {
552
                try {
553
                        if ( this.mode != MODE_QUERY ) {
554
                                throw new AlreadyEditingException(this.getName());
555
                        }
556
                        if (!this.provider.supportsAppendMode()) {
557
                                mode = MODE_FULLEDIT;
558
                        }
559
                        switch (mode) {
560
                        case MODE_QUERY:
561
                                throw new IllegalStateException(this.getName());
562

    
563
                        case MODE_FULLEDIT:
564
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
565
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
566
                                featureTypeManager = new FeatureTypeManager(
567
                                                new MemoryExpansionAdapter());
568
                                spatialManager = new SpatialManager();
569

    
570
                                commands = new FeatureCommandsRecord(featureManager,
571
                                                spatialManager, featureTypeManager);
572
                                this.mode = MODE_FULLEDIT;
573
                                hasStrongChanges = false;
574
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
575
                                break;
576
                        case MODE_APPEND:
577
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
578
                                this.provider.beginAppend();
579
                                this.mode = MODE_APPEND;
580
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
581
                                break;
582
                        }
583
                } catch (Exception e) {
584
                        throw new StoreEditException(e, this.getName());
585
                }
586
        }
587

    
588
        public boolean isEditing() {
589
                return mode == MODE_FULLEDIT;
590
        }
591

    
592
        public boolean isAppending() {
593
                return mode == MODE_APPEND;
594
        }
595

    
596
        synchronized public void update(EditableFeatureType type)
597
                        throws DataException {
598
                try {
599
                        checkInEditingMode();
600
                        if (type == null) {
601
                                throw new NullFeatureTypeException(getName());
602
                        }
603
                        // FIXME: Comprobar que es un featureType aceptable.
604
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
605
                        newVersionOfUpdate();
606

    
607
                        FeatureType oldt = type.getSource().getCopy();
608
                        FeatureType newt = type.getNotEditableCopy();
609
                        commands.update(newt, oldt);
610

    
611
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
612
                                hasStrongChanges = true;
613
                        }
614
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
615
                } catch (Exception e) {
616
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
617
                }
618
        }
619

    
620
        synchronized public void delete(Feature feature) throws DataException {
621
                try {
622
                        checkInEditingMode();
623
                        checkIsOwnFeature(feature);
624
                        if (feature instanceof EditableFeature) {
625
                                throw new StoreDeleteEditableFeatureException(getName());
626
                        }
627
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
628
                        this.commands.delete(feature);
629
                        newVersionOfUpdate();
630
                        hasStrongChanges = true;
631
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
632
                } catch (Exception e) {
633
                        throw new StoreDeleteFeatureException(e, this.getName());
634
                }
635
        }
636

    
637
        private static EditableFeature lastChangedFeature = null;
638

    
639
        synchronized public void insert(EditableFeature feature)
640
                        throws DataException {
641
                try {
642
                        switch (mode) {
643
                        case MODE_QUERY:
644
                                throw new NeedEditingModeException(this.getName());
645

    
646
                        case MODE_APPEND:
647
                                checkIsOwnFeature(feature);
648
                                if (feature.getSource() != null) {
649
                                        throw new NoNewFeatureInsertException(this.getName());
650
                                }
651
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
652
                                feature.validate(Feature.UPDATE);
653
                                provider.append(feature);
654
                                hasStrongChanges = true;
655
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
656
                                break;
657

    
658
                        case MODE_FULLEDIT:
659
                                checkIsOwnFeature(feature);
660
                                if (feature.getSource() != null) {
661
                                        throw new NoNewFeatureInsertException(this.getName());
662
                                }
663
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
664
                                newVersionOfUpdate();
665
                                if (lastChangedFeature.getSource() != feature.getSource()) {
666
                                        lastChangedFeature = feature;
667
                                        feature.validate(Feature.UPDATE);
668
                                        lastChangedFeature = null;
669
                                }
670
                                commands.insert(feature.getNotEditableCopy());
671
                                hasStrongChanges = true;
672
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
673
                                break;
674
                        }
675
                } catch (Exception e) {
676
                        throw new StoreInsertFeatureException(e, this.getName());
677
                }
678
        }
679

    
680
        synchronized public void update(EditableFeature feature)
681
                        throws DataException {
682
                try {
683
                        if ((feature).getSource() == null) {
684
                                insert(feature);
685
                                return;
686
                        }
687
                        checkInEditingMode();
688
                        checkIsOwnFeature(feature);
689
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
690
                        newVersionOfUpdate();
691
                        if (lastChangedFeature.getSource() != feature.getSource()) {
692
                                lastChangedFeature = feature;
693
                                feature.validate(Feature.UPDATE);
694
                                lastChangedFeature = null;
695
                        }
696

    
697
                        Feature oldf = feature.getSource();
698
                        Feature newf = feature.getNotEditableCopy();
699
                        commands.update(newf, oldf);
700

    
701
                        hasStrongChanges = true;
702
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
703
                } catch (Exception e) {
704
                        throw new StoreUpdateFeatureException(e, this.getName());
705
                }
706
        }
707

    
708
        synchronized public void redo() throws DataException {
709
                try {
710
                        checkInEditingMode();
711
                        Command redo = commands.getNextRedoCommand();
712
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
713
                        newVersionOfUpdate();
714
                        commands.redo();
715
                        hasStrongChanges = true;
716
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
717
                } catch (Exception e) {
718
                        throw new StoreRedoException(e, this.getName());
719
                }
720
        }
721

    
722
        synchronized public void undo() throws DataException {
723
                try {
724
                        checkInEditingMode();
725
                        Command undo = commands.getNextUndoCommand();
726
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
727
                        newVersionOfUpdate();
728
                        commands.undo();
729
                        hasStrongChanges = true;
730
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
731
                } catch (Exception e) {
732
                        throw new StoreUndoException(e, this.getName());
733
                }
734
        }
735

    
736
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
737
                checkInEditingMode();
738
                return commands;
739
        }
740

    
741
        synchronized public void cancelEditing() throws DataException {
742
                try {
743
                        checkInEditingMode();
744
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
745
                        exitEditingMode();
746
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
747
                } catch (Exception e) {
748
                        throw new StoreCancelEditingException(e, this.getName());
749
                }
750
        }
751

    
752
        synchronized public void finishEditing() throws DataException {
753
                try {
754
                        switch (mode) {
755
                        case MODE_QUERY:
756
                                throw new NeedEditingModeException(this.getName());
757

    
758
                        case MODE_APPEND:
759
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
760
                                provider.endAppend();
761
                                exitEditingMode();
762
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
763
                                break;
764

    
765
                        case MODE_FULLEDIT:
766
                                if (!hasStrongChanges) {
767
                                        performLightEditing();
768
                                        return;
769
                                }
770
                                if (!this.allowWrite()) {
771
                                        throw new WriteNotAllowedException(getName());
772
                                }
773

    
774
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
775
                                validateFeatures(Feature.FINISH_EDITING);
776
                                provider.performEditing(featureManager.getInserted(),
777
                                                featureManager.getUpdated(), featureManager
778
                                                                .getDeleted());
779
                                exitEditingMode();
780
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
781
                                break;
782
                        }
783
                } catch (Exception e) {
784
                        throw new FinishEditingException(e);
785
                }
786
        }
787

    
788
        private void performLightEditing() throws DataException {
789
                throw new NotYetImplemented(
790
                                "lightFinishEdition not yet implemented");
791

    
792
                // TODO: implementar
793
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
794
                // exitEditingMode();
795
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
796
        }
797

    
798

    
799
        public boolean isAppendModeSupported() {
800
                return this.provider.supportsAppendMode();
801
        }
802

    
803

    
804
        public void export(FeatureExplorer explorer, FeatureStoreParameters params)
805
                        throws DataException {
806

    
807
                if (this.getFeatureTypes().size() != 1) {
808
                        throw new NotYetImplemented(
809
                                        "export whith more than one type not yet implemented");
810
                }
811
                try {
812
                        FeatureType type = this.getDefaultFeatureType();
813
                        params.setDefaultFeatureType(type);
814
                        explorer.add(params);
815

    
816
                        DataManager manager = DALLocator.getDataManager();
817
                        FeatureStore target = (FeatureStore) manager
818
                                        .createStore(params);
819
                        target.edit();
820

    
821
                        FeatureSet features = this.getFeatureSet();
822
                        Iterator it1 = features.iterator();
823
                        while (it1.hasNext()) {
824
                                Feature feature = (Feature) it1.next();
825
                                target.insert(target.createNewFeature(type, feature));
826
                        }
827
                        features.dispose();
828
                        target.finishEditing();
829
                        target.dispose();
830
                } catch (Exception e) {
831
                        throw new DataExportException(e, params.toString());
832
                }
833
        }
834

    
835
        //
836
        // ====================================================================
837
        // Obtencion de datos
838
        // getDataCollection, getFeatureCollection
839
        //
840

    
841
        public DataSet getDataSet() throws DataException {
842
                checkNotInAppendMode();
843
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
844
                return new DefaultFeatureSet(this, query);
845
        }
846

    
847
        public DataSet getDataSet(DataQuery dataQuery)
848
                        throws DataException {
849
                checkNotInAppendMode();
850
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
851
        }
852

    
853
        public void getDataSet(Observer observer) throws DataException {
854
                checkNotInAppendMode();
855
                this.getFeatureSet(null, observer);
856
        }
857

    
858
        public void getDataSet(DataQuery dataQuery, Observer observer)
859
                        throws DataException {
860
                checkNotInAppendMode();
861
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
862
        }
863

    
864
        public FeatureSet getFeatureSet() throws DataException {
865
                checkNotInAppendMode();
866
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
867
                return new DefaultFeatureSet(this, query);
868
        }
869

    
870
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
871
                        throws DataException {
872
                checkNotInAppendMode();
873
                fixFeatureQuery(featureQuery);
874
                return new DefaultFeatureSet(this, featureQuery);
875
        }
876

    
877
        private void fixFeatureQuery(FeatureQuery featureQuery)
878
                        throws DataException {
879
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
880
                if (featureQuery.getAttributeNames() != null){
881
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
882
                                        .getFeatureType();
883
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
884
                                        .getAttributeNames()));
885
                }
886
        }
887

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

    
894
        public void getFeatureSet(FeatureQuery query, Observer observer)
895
                        throws DataException {
896
                class LoadInBackGround implements Runnable {
897
                        private FeatureStore store;
898
                        private FeatureQuery query;
899
                        private Observer observer;
900

    
901
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
902
                                        Observer observer) {
903
                                this.store = store;
904
                                this.query = query;
905
                                this.observer = observer;
906
                        }
907

    
908
                        public void run() {
909
                                try {
910
                                        FeatureSet collection = store.getFeatureSet(query);
911
                                        observer.update(
912
                                                        store,
913
                                                        new DefaultFeatureStoreNotification(
914
                                                                        store,
915
                                                                        FeatureStoreNotification.LOAD_FINISHED,
916
                                                                        collection
917
                                                                )
918
                                                );
919
                                } catch (Exception e) {
920
                                        observer.update(
921
                                                        store,
922
                                                        new DefaultFeatureStoreNotification(
923
                                                                        store,
924
                                                                        FeatureStoreNotification.LOAD_FINISHED,
925
                                                                        e
926
                                                                )
927
                                                );
928
                                }
929
                        }
930
                }
931

    
932
                checkNotInAppendMode();
933
                if (query == null) {
934
                        query = new FeatureQuery(this.getDefaultFeatureType());
935
                }
936
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
937
                Thread thread = new Thread(task);
938
                thread.run();
939
        }
940

    
941
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
942
                checkNotInAppendMode();
943
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
944
        }
945

    
946
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
947
                        throws DataException {
948
                checkNotInAppendMode();
949
                featureType = fixFeatureType((DefaultFeatureType) featureType);
950
                // TODO comprobar que el id es de este store
951

    
952
                if (this.mode == MODE_FULLEDIT) {
953
                        Feature f = featureManager.get(reference, this, featureType);
954
                        if (f!=null) {
955
                                return f;
956
                        }
957
                }
958
                return new DefaultFeature(this, this.provider
959
                                .getFeatureDataByReference((FeatureReferenceProviderServices) reference));
960
        }
961

    
962
        //
963
        // ====================================================================
964
        // Gestion de features
965
        //
966

    
967
        private FeatureType fixFeatureType(DefaultFeatureType type)
968
                        throws DataException {
969
                FeatureType defaultType = this.getDefaultFeatureType();
970
                if (type == null || type.equals(defaultType)) {
971
                        return defaultType;
972
                }
973
                if (type.isSubtypeOf(defaultType)) {
974
                        return type;
975
                }
976
                Iterator iter = this.getFeatureTypes().iterator();
977
                FeatureType tmpType;
978
                while (iter.hasNext()) {
979
                        tmpType = (FeatureType) iter.next();
980
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
981
                                return type;
982
                        }
983

    
984
                }
985
                throw new IllegalFeatureTypeException(getName());
986
        }
987

    
988
        public void validateFeatures(int mode) throws DataException {
989
                try {
990
                        checkNotInAppendMode();
991
                        FeatureSet collection = this.getFeatureSet();
992
                        Iterator iter = collection.iterator();
993
                        long previousVersionOfUpdate = currentVersionOfUpdate();
994
                        while (iter.hasNext()) {
995
                                ((DefaultFeature) iter.next()).validate(mode);
996
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
997
                                        throw new ConcurrentDataModificationException(getName());
998
                                }
999
                        }
1000
                } catch (Exception e) {
1001
                        throw new ValidateFeaturesException(e, getName());
1002
                }
1003
        }
1004

    
1005
        public FeatureType getDefaultFeatureType() throws DataException {
1006
                try {
1007
                        if (isEditing()) {
1008
                                return featureTypeManager.getType(defaultFeatureType.getId());
1009
                        }
1010
                        return defaultFeatureType;
1011
                } catch (Exception e) {
1012
                        throw new GetFeatureTypeException(e, getName());
1013
                }
1014
        }
1015

    
1016
        public List getFeatureTypes() throws DataException {
1017
                try {
1018
                        List types;
1019
                        if (isEditing()) {
1020
                                types=new ArrayList();
1021
                                Iterator it=featureTypes.iterator();
1022
                                while (it.hasNext()) {
1023
                                        FeatureType type = (FeatureType) it.next();
1024
                                        type=featureTypeManager.getType(type.getId());
1025
                                        if (type!=null) {
1026
                                                types.add(type);
1027
                                        }
1028
                                }
1029
                                it = featureTypeManager.newsIterator();
1030
                                while (it.hasNext()) {
1031
                                        FeatureType type = (FeatureType) it.next();
1032
                                        types.add(type);
1033
                                }
1034
                        } else {
1035
                                types = featureTypes;
1036
                        }
1037
                        return Collections.unmodifiableList(types);
1038
                } catch (Exception e) {
1039
                        throw new GetFeatureTypeException(e, getName());
1040
                }
1041
        }
1042

    
1043
        public Feature createFeature(FeatureData data)
1044
                        throws DataException {
1045
                DefaultFeature feature = new DefaultFeature(this, data);
1046
                return feature;
1047
        }
1048

    
1049
        public Feature createFeature(FeatureData data, FeatureType type)
1050
                        throws DataException {
1051
                // FIXME: falta por implementar
1052
                // Comprobar si es un subtipo del feature de data
1053
                // y construir un feature usando el subtipo.
1054
                // Probablemente requiera generar una copia del data.
1055
                throw new NotYetImplemented();
1056
        }
1057

    
1058
        public EditableFeature createNewFeature(FeatureType type,
1059
                        Feature defaultValues)
1060
                        throws DataException {
1061
                try {
1062
                        type = this.fixFeatureType((DefaultFeatureType) type);
1063
                        FeatureData data = this.provider.createFeatureData(type);
1064
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1065
                                        data);
1066
                        feature.initializeValues(defaultValues);
1067
                        return feature;
1068
                } catch (Exception e) {
1069
                        throw new CreateFeatureException(e, getName());
1070
                }
1071
        }
1072

    
1073
        public EditableFeature createNewFeature(FeatureType type,
1074
                        boolean defaultValues)
1075
                        throws DataException {
1076
                try {
1077
                        type = this.fixFeatureType((DefaultFeatureType) type);
1078
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1079
                        if (defaultValues) {
1080
                                feature.initializeValues();
1081
                        }
1082
                        return feature;
1083
                } catch (Exception e) {
1084
                        throw new CreateFeatureException(e, getName());
1085
                }
1086
        }
1087

    
1088
        public EditableFeature createNewFeature(boolean defaultValues)
1089
                        throws DataException {
1090
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1091
        }
1092

    
1093
        public EditableFeature createNewFeature() throws DataException {
1094
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1095
        }
1096

    
1097
        public EditableFeatureType createFeatureType() {
1098
                return new DefaultEditableFeatureType();
1099
        }
1100

    
1101
        public boolean isLocksSupported() {
1102
                return this.provider.isLocksSupported();
1103
        }
1104

    
1105
        public Logger getLogger() {
1106
                return DefaultFeatureStore.logger;
1107
        }
1108

    
1109
        public FeatureIndex createIndex(FeatureType featureType,
1110
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1111
                checkNotInAppendMode();
1112
                FeatureIndexProviderServices index = null;
1113
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1114
                try {
1115
                        index.fill();
1116
                } catch (FeatureIndexException e) {
1117
                        throw new InitializeException(index.getName(), e);
1118
                }
1119
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1120
                return index;
1121
        }
1122

    
1123
        public void beginEditingGroup(String description)
1124
                        throws NeedEditingModeException {
1125
                checkInEditingMode();
1126
                commands.startComplex(description);
1127
        }
1128

    
1129
        public void endEditingGroup() throws NeedEditingModeException {
1130
                checkInEditingMode();
1131
                commands.endComplex();
1132
        }
1133
}