Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 25587

History | View | Annotate | Download (36.3 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.DataManager;
10
import org.gvsig.fmap.dal.DataQuery;
11
import org.gvsig.fmap.dal.DataServerExplorer;
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.EditableFeature;
22
import org.gvsig.fmap.dal.feature.EditableFeatureType;
23
import org.gvsig.fmap.dal.feature.Feature;
24
import org.gvsig.fmap.dal.feature.FeatureIndex;
25
import org.gvsig.fmap.dal.feature.FeatureIndexes;
26
import org.gvsig.fmap.dal.feature.FeatureLocks;
27
import org.gvsig.fmap.dal.feature.FeatureQuery;
28
import org.gvsig.fmap.dal.feature.FeatureReference;
29
import org.gvsig.fmap.dal.feature.FeatureSelection;
30
import org.gvsig.fmap.dal.feature.FeatureSet;
31
import org.gvsig.fmap.dal.feature.FeatureStore;
32
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
33
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
34
import org.gvsig.fmap.dal.feature.FeatureType;
35
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
36
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
37
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
38
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
39
import org.gvsig.fmap.dal.feature.exception.DataExportException;
40
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
41
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
42
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
43
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
44
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
45
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
46
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
47
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
48
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
49
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
50
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
51
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
52
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
53
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
54
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
55
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
56
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
57
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
58
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
59
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
60
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
61
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
62
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureData;
63
import org.gvsig.fmap.dal.feature.spi.FeatureData;
64
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
65
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
66
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
67
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
68
import org.gvsig.fmap.dal.impl.DefaultDataManager;
69
import org.gvsig.fmap.geom.primitive.Envelope;
70
import org.gvsig.tools.ToolsLocator;
71
import org.gvsig.tools.exception.NotYetImplemented;
72
import org.gvsig.tools.observer.Observable;
73
import org.gvsig.tools.observer.Observer;
74
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
75
import org.gvsig.tools.operations.OperationContext;
76
import org.gvsig.tools.operations.OperationException;
77
import org.gvsig.tools.operations.OperationNotSupportedException;
78
import org.gvsig.tools.persistence.AbstractPersistenceManager;
79
import org.gvsig.tools.persistence.PersistenceException;
80
import org.gvsig.tools.persistence.PersistenceValueNotFoundException;
81
import org.gvsig.tools.persistence.PersistentState;
82
import org.gvsig.tools.task.Executor;
83
import org.gvsig.tools.undo.RedoException;
84
import org.gvsig.tools.undo.UndoException;
85
import org.gvsig.tools.undo.command.Command;
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 FeatureCommandsStack 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
                try {
150
                        indexes=new DefaultFeatureIndexes(this);
151
                } catch (DataException e) {
152
                        throw new InitializeException(e);
153
                }
154
        }
155

    
156
        public Logger getLogger() {
157
                return DefaultFeatureStore.logger;
158
        }
159

    
160
        public String getName() {
161
                return this.parameters.getDataStoreName();
162
        }
163

    
164
        public DataStoreParameters getParameters() {
165
                return parameters;
166
        }
167

    
168
        public int getMode() {
169
                return this.mode;
170
        }
171

    
172
        public DefaultDataManager getManager() {
173
                return this.dataManager;
174
        }
175

    
176
        public Iterator getChildren() {
177
                return this.provider.getChilds();
178
        }
179

    
180
        public FeatureStoreProvider getProvider() {
181
                return this.provider;
182
        }
183

    
184
        public FeatureManager getFeatureManager() {
185
                return this.featureManager;
186
        }
187

    
188
        public void setFeatureTypes(List types, FeatureType defaultType) {
189
                this.featureTypes = types;
190
                this.defaultFeatureType = defaultType;
191
        }
192

    
193
        public void open() throws OpenException {
194
                // TODO: Se puede hacer un open estando en edicion ?
195
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
196
                this.provider.open();
197
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
198
        }
199

    
200
        public void refresh() throws OpenException, InitializeException {
201
                if (this.mode != MODE_QUERY) {
202
                        throw new IllegalStateException();
203
                }
204
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
205
                this.provider.refresh();
206
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
207
        }
208

    
209
        public void close() throws CloseException {
210
                // TODO: Se puede hacer un close estando en edicion ?
211
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
212
                this.provider.close();
213
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
214
        }
215

    
216
        public void dispose() throws CloseException {
217
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
218
                this.provider.dispose();
219
                if (this.selection != null) {
220
                        this.selection.dispose();
221
                        this.selection = null;
222
                }
223
                this.commands = null;
224

    
225
                if (this.locks != null) {
226
                        //this.locks.dispose();
227
                        this.locks = null;
228
                }
229

    
230
                this.featureManager = null;
231
                this.spatialManager = null;
232

    
233
                this.parameters = null;
234
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
235
                this.delegateObservable.deleteObservers();
236
                this.delegateObservable = null;
237
        }
238

    
239
        public boolean allowWrite() {
240
                return this.provider.allowWrite();
241
        }
242

    
243
        public boolean canWriteGeometry(int geometryType) throws DataException {
244
                return this.provider.canWriteGeometry(geometryType);
245
        }
246

    
247
        public DataServerExplorer getExplorer() throws ReadException {
248
                return this.provider.getExplorer();
249
        }
250

    
251
        /*
252
        public Metadata getMetadata() throws MetadataNotFoundException {
253
                // TODO:
254
                // Si el provider devuelbe null habria que ver de construir aqui
255
                // los metadatos basicos, como el Envelope y el SRS.
256

257
                // TODO: Estando en edicion el Envelope deberia de
258
                // actualizarse usando el spatialManager
259
                return this.provider.getMetadata();
260
        }
261
        */
262

    
263
        public Envelope getEnvelope() throws DataException {
264
                if (this.mode == MODE_FULLEDIT) {
265
                        return this.spatialManager.getEnvelope();
266
                }
267
                return this.provider.getEnvelope();
268
        }
269

    
270
        /**
271
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
272
         */
273
        public String getSRSDefaultGeometry() throws DataException {
274
                return this.getDefaultFeatureType().getDefaultSRS();
275
        }
276

    
277
        public FeatureSelection createDefaultFeatureSelection()
278
                        throws DataException {
279
                return new DefaultFeatureSelection(this);
280
        }
281

    
282
        public FeatureData createDefaultFeatureData(FeatureType type)
283
                        throws DataException {
284
                return new DefaultFeatureData(type);
285
        }
286

    
287
        public PersistentState getState()
288
                        throws PersistenceException {
289
                return AbstractPersistenceManager.getState(this);
290
        }
291

    
292
        public void loadState(PersistentState state) throws PersistenceException {
293
                state.setTheClass(this);
294
                state.set("dataStoreName", this.getName());
295
                state.set("parameters", this.parameters);
296
                state.set("provider", this.provider);
297
                if (this.selection != null) {
298
                        state.set("selection", this.selection);
299
                }
300
        }
301

    
302
        public void setState(PersistentState state) throws PersistenceException {
303
                if (this.provider != null) {
304
                        throw new PersistenceException(null);
305
                }
306
                if (this.getManager() == null) {
307
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
308
                }
309

    
310
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
311
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
312

    
313
                try {
314

    
315
                        initialize(this.getManager(), params, provider);
316
                        try {
317
                                setSelection((FeatureSelection) state.get("selection"));
318
                        } catch (PersistenceValueNotFoundException e) {
319
                                setSelection(null);
320
                        }
321

    
322
                } catch (InitializeException e) {
323
                        throw new PersistenceException(e);
324
                } catch (DataException e) {
325
                        throw new PersistenceException(e);
326
                }
327

    
328
        }
329

    
330
        //
331
        // ====================================================================
332
        // Gestion de la seleccion
333
        //
334

    
335
        public void setSelection(DataSet selection)
336
                        throws DataException {
337
                this.setSelection((FeatureSet) selection);
338
        }
339

    
340
        public DataSet createSelection() throws DataException {
341
                return createFeatureSelection();
342
        }
343

    
344
        public DataSet getSelection() throws DataException {
345
                return this.getFeatureSelection();
346
        }
347

    
348
        public void setSelection(FeatureSet selection)
349
                        throws DataException {
350
                if (selection.equals(this.selection)) {
351
                        return;
352
                }
353
                if (!selection.isFromStore(this)) {
354
                        throw new SelectionNotAllowedException(getName());
355
                }
356

    
357
                this.selection.deleteObserver(this);
358
                if (selection instanceof FeatureSelection) {
359
                        if (isEditing()) {
360
                                commands.selectionSet(this, this.selection,
361
                                                (FeatureSelection) selection);
362
                        }
363
                        this.selection = (FeatureSelection) selection;
364
                } else {
365
                        if (isEditing()) {
366
                                commands.startComplex("_selectionSet");
367
                        }
368
                        this.selection.deselectAll();
369
                        this.selection.select(selection);
370
                        if (isEditing()) {
371
                                commands.endComplex();
372
                        }
373
                }
374
                this.selection.addObserver(this);
375

    
376
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
377
        }
378

    
379
        public FeatureSelection createFeatureSelection() throws DataException {
380
                return this.provider.createFeatureSelection();
381
        }
382

    
383
        public FeatureSelection getFeatureSelection() throws DataException {
384
                if (selection == null) {
385
                        this.selection = createFeatureSelection();
386
                        this.selection.addObserver(this);
387
                }
388
                return selection;
389
        }
390

    
391
        //
392
        // ====================================================================
393
        // Gestion de notificaciones
394
        //
395

    
396
        public void notifyChange(String notification) {
397
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
398
                notification));
399

    
400
        }
401

    
402
        public void notifyChange(String notification, Feature feature) {
403
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
404
                                                this, notification, feature));
405
        }
406

    
407
        public void notifyChange(String notification, Command command) {
408
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
409
                                                this, notification, command));
410
        }
411

    
412
        public void notifyChange(String notification, EditableFeatureType type) {
413
            delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
414
                notification, type));
415
        }
416

    
417

    
418
        //
419
        // ====================================================================
420
        // Gestion de bloqueos
421
        //
422

    
423
        public boolean isLocksSupported() {
424
                return this.provider.isLocksSupported();
425
        }
426

    
427
        public FeatureLocks getLocks() throws DataException {
428
                if (!this.provider.isLocksSupported()) {
429
                        getLogger().warn("Locks not supporteds");
430
                        return null;
431
                }
432
                if (locks == null) {
433
                        this.locks = (FeatureLocks)this.provider.createFeatureLocks();
434
                }
435
                return locks;
436
        }
437

    
438
        //
439
        // ====================================================================
440
    // Interface Observable
441
        //
442

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

    
446
    }
447

    
448
    public void enableNotifications() {
449
        this.delegateObservable.enableNotifications();
450
    }
451

    
452
    public void beginComplexNotification() {
453
        this.delegateObservable.beginComplexNotification();
454

    
455
    }
456

    
457
    public void endComplexNotification() {
458
        this.delegateObservable.endComplexNotification();
459

    
460
    }
461

    
462
        public void addObserver(Observer observer) {
463
                this.delegateObservable.addObserver(observer);
464

    
465
        }
466

    
467
        public void deleteObserver(Observer observer) {
468
        this.delegateObservable.deleteObserver(observer);
469
        }
470

    
471
        public void deleteObservers() {
472
                this.delegateObservable.deleteObservers();
473

    
474
        }
475

    
476
        //
477
        // ====================================================================
478
        // Interface Observer
479
        //
480
        // Usado para observar:
481
        // - su seleccion
482
        // - sus bloqueos
483
        // - sus recursos
484
        //
485

    
486
        public void update(Observable observable, Object notification) {
487
                if (observable instanceof FeatureSet) {
488
                        if (observable == this.selection) {
489
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
490
                        } else if (observable == this.locks) {
491
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
492
                        }
493

    
494
                }
495
        }
496

    
497

    
498
        //
499
        // ====================================================================
500
        // Gestion de operaciones
501
        // Interface ExtendedOperations
502
        //
503
        public Object invokeOperation(int code, OperationContext context)
504
                        throws OperationException, OperationNotSupportedException {
505
                return this.dataManager.getOperationManager().invokeOperation(this, code, context);
506
        }
507

    
508
        public Object invokeOperation(String name, OperationContext context)
509
                        throws OperationException, OperationNotSupportedException {
510
                return this.dataManager.getOperationManager().invokeOperation(this, name, context);
511
        }
512

    
513
        public boolean hasOperation(int code) {
514
                return this.dataManager.getOperationManager().hasOperation(this, code);
515
        }
516

    
517
        public boolean hasOperation(String name) {
518
                return this.dataManager.getOperationManager().hasOperation(this, name);
519
        }
520

    
521
        public Object getOperation(int code) throws OperationException {
522
                return this.dataManager.getOperationManager().getOperation(this, code);
523
        }
524

    
525
        public Object getOperation(String name) throws OperationException {
526
                return this.dataManager.getOperationManager().getOperation(this, name);
527
        }
528

    
529
        //
530
        // ====================================================================
531
        // Edicion
532
        //
533

    
534
        private void newVersionOfUpdate() {
535
                this.versionOfUpdate++;
536
        }
537

    
538
        private long currentVersionOfUpdate() {
539
                return this.versionOfUpdate;
540
        }
541

    
542
        private void checkInEditingMode()
543
                        throws NeedEditingModeException {
544
                if (mode != MODE_FULLEDIT) {
545
                        throw new NeedEditingModeException(this.getName());
546
                }
547
        }
548

    
549
        private void checkNotInAppendMode() throws IllegalStateException {
550
                if (mode == MODE_APPEND) {
551
                        throw new IllegalStateException(this.getName());
552
                }
553
        }
554

    
555
        private void checkIsOwnFeature(Feature feature)
556
                        throws IllegalFeatureException {
557
                if (((DefaultFeature) feature).getStore() != this) {
558
                        throw new IllegalFeatureException(this.getName());
559
                }
560
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
561
                // fixFeatureType((DefaultFeatureType) feature.getType());
562
        }
563

    
564
        private void exitEditingMode() {
565
                commands.clear();
566
                featureManager = null;
567
                spatialManager = null;
568
                featureTypeManager = null;
569
                commands = null;
570

    
571
                mode = MODE_QUERY;
572
                hasStrongChanges = true; // Lo deja a true por si las moscas
573
        }
574

    
575
        synchronized public void edit() throws DataException {
576
                edit(MODE_FULLEDIT);
577
        }
578

    
579
        synchronized public void edit(int mode) throws DataException {
580
                try {
581
                        if ( this.mode != MODE_QUERY ) {
582
                                throw new AlreadyEditingException(this.getName());
583
                        }
584
                        if (!this.provider.supportsAppendMode()) {
585
                                mode = MODE_FULLEDIT;
586
                        }
587
                        switch (mode) {
588
                        case MODE_QUERY:
589
                                throw new IllegalStateException(this.getName());
590

    
591
                        case MODE_FULLEDIT:
592
                                if (!this.transforms.isEmpty()) {
593
                                        throw new IllegalStateException(this.getName());
594
                                }
595
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
596
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
597
                                featureTypeManager = new FeatureTypeManager(
598
                                                new MemoryExpansionAdapter());
599
                                spatialManager = new SpatialManager(this);
600

    
601
                                commands = new DefaultFeatureCommandsStack(featureManager,
602
                                                spatialManager, featureTypeManager);
603
                                this.mode = MODE_FULLEDIT;
604
                                hasStrongChanges = false;
605
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
606
                                break;
607
                        case MODE_APPEND:
608
                                if (!this.transforms.isEmpty()) {
609
                                        throw new IllegalStateException(this.getName());
610
                                }
611
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
612
                                this.provider.beginAppend();
613
                                this.mode = MODE_APPEND;
614
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
615
                                break;
616
                        }
617
                } catch (Exception e) {
618
                        throw new StoreEditException(e, this.getName());
619
                }
620
        }
621

    
622
        public boolean isEditing() {
623
                return mode == MODE_FULLEDIT;
624
        }
625

    
626
        public boolean isAppending() {
627
                return mode == MODE_APPEND;
628
        }
629

    
630
        synchronized public void update(EditableFeatureType type)
631
                        throws DataException {
632
                try {
633
                        checkInEditingMode();
634
                        if (type == null) {
635
                                throw new NullFeatureTypeException(getName());
636
                        }
637
                        // FIXME: Comprobar que es un featureType aceptable.
638
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
639
                        newVersionOfUpdate();
640

    
641
                        FeatureType oldt = type.getSource().getCopy();
642
                        FeatureType newt = type.getNotEditableCopy();
643
                        commands.update(newt, oldt);
644

    
645
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
646
                                hasStrongChanges = true;
647
                        }
648
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
649
                } catch (Exception e) {
650
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
651
                }
652
        }
653

    
654
        synchronized public void delete(Feature feature) throws DataException {
655
                try {
656
                        checkInEditingMode();
657
                        checkIsOwnFeature(feature);
658
                        if (feature instanceof EditableFeature) {
659
                                throw new StoreDeleteEditableFeatureException(getName());
660
                        }
661
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
662
                        this.commands.delete(feature);
663
                        newVersionOfUpdate();
664
                        hasStrongChanges = true;
665
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
666
                } catch (Exception e) {
667
                        throw new StoreDeleteFeatureException(e, this.getName());
668
                }
669
        }
670

    
671
        private static EditableFeature lastChangedFeature = null;
672

    
673
        synchronized public void insert(EditableFeature feature)
674
                        throws DataException {
675
                try {
676
                        switch (mode) {
677
                        case MODE_QUERY:
678
                                throw new NeedEditingModeException(this.getName());
679

    
680
                        case MODE_APPEND:
681
                                checkIsOwnFeature(feature);
682
                                if (feature.getSource() != null) {
683
                                        throw new NoNewFeatureInsertException(this.getName());
684
                                }
685
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
686
                                feature.validate(Feature.UPDATE);
687
                                provider.append(feature);
688
                                hasStrongChanges = true;
689
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
690
                                break;
691

    
692
                        case MODE_FULLEDIT:
693
                                checkIsOwnFeature(feature);
694
                                if (feature.getSource() != null) {
695
                                        throw new NoNewFeatureInsertException(this.getName());
696
                                }
697
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
698
                                newVersionOfUpdate();
699
                                if (lastChangedFeature ==null || lastChangedFeature.getSource() != feature.getSource()) {
700
                                        lastChangedFeature = feature;
701
                                        feature.validate(Feature.UPDATE);
702
                                        lastChangedFeature = null;
703
                                }
704
                                commands.insert(feature.getNotEditableCopy());
705
                                hasStrongChanges = true;
706
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
707
                                break;
708
                        }
709
                } catch (Exception e) {
710
                        throw new StoreInsertFeatureException(e, this.getName());
711
                }
712
        }
713

    
714
        synchronized public void update(EditableFeature feature)
715
                        throws DataException {
716
                try {
717
                        if ((feature).getSource() == null) {
718
                                insert(feature);
719
                                return;
720
                        }
721
                        checkInEditingMode();
722
                        checkIsOwnFeature(feature);
723
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
724
                        newVersionOfUpdate();
725
                        if (lastChangedFeature.getSource() != feature.getSource()) {
726
                                lastChangedFeature = feature;
727
                                feature.validate(Feature.UPDATE);
728
                                lastChangedFeature = null;
729
                        }
730

    
731
                        Feature oldf = feature.getSource();
732
                        Feature newf = feature.getNotEditableCopy();
733
                        commands.update(newf, oldf);
734

    
735
                        hasStrongChanges = true;
736
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
737
                } catch (Exception e) {
738
                        throw new StoreUpdateFeatureException(e, this.getName());
739
                }
740
        }
741

    
742
        synchronized public void redo() throws RedoException {
743
            Command redo = commands.getNextRedoCommand();
744
        try {
745
            checkInEditingMode();
746
        } catch (NeedEditingModeException ex) {
747
            throw new RedoException(redo, ex);
748
        }
749
                notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
750
        newVersionOfUpdate();
751
        commands.redo();
752
        hasStrongChanges = true;
753
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
754
        }
755

    
756
        synchronized public void undo() throws UndoException {
757
            Command undo = commands.getNextUndoCommand();
758
        try {
759
            checkInEditingMode();
760
        } catch (NeedEditingModeException ex) {
761
            throw new UndoException(undo, ex);
762
        }
763
                notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
764
        newVersionOfUpdate();
765
        commands.undo();
766
        hasStrongChanges = true;
767
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
768
        }
769

    
770
    public List getRedoInfos() {
771
        if (isEditing() && commands != null) {
772
            return commands.getRedoInfos();
773
        } else {
774
            return null;
775
        }
776
    }
777

    
778
    public List getUndoInfos() {
779
        if (isEditing() && commands != null) {
780
            return commands.getUndoInfos();
781
        } else {
782
            return null;
783
        }
784
    }
785

    
786
    public synchronized FeatureCommandsStack getCommandsStack()
787
            throws DataException {
788
        checkInEditingMode();
789
        return commands;
790
    }
791

    
792
        synchronized public void cancelEditing() throws DataException {
793
                try {
794
                        checkInEditingMode();
795
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
796
                        exitEditingMode();
797
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
798
                } catch (Exception e) {
799
                        throw new StoreCancelEditingException(e, this.getName());
800
                }
801
        }
802

    
803
        synchronized public void finishEditing() throws DataException {
804
                try {
805
                        switch (mode) {
806
                        case MODE_QUERY:
807
                                throw new NeedEditingModeException(this.getName());
808

    
809
                        case MODE_APPEND:
810
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
811
                                provider.endAppend();
812
                                exitEditingMode();
813
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
814
                                break;
815

    
816
                        case MODE_FULLEDIT:
817
                                if (!hasStrongChanges) {
818
                                        performLightEditing();
819
                                        return;
820
                                }
821
                                if (!this.allowWrite()) {
822
                                        throw new WriteNotAllowedException(getName());
823
                                }
824

    
825
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
826
                                validateFeatures(Feature.FINISH_EDITING);
827
                                provider.performEditing(featureManager.getInserted(),
828
                                                featureManager.getUpdated(), featureManager
829
                                                                .getDeleted());
830
                                exitEditingMode();
831
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
832
                                break;
833
                        }
834
                } catch (Exception e) {
835
                        throw new FinishEditingException(e);
836
                }
837
        }
838

    
839
        private void performLightEditing() throws DataException {
840
                throw new NotYetImplemented(
841
                                "lightFinishEdition not yet implemented");
842

    
843
                // TODO: implementar
844
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
845
                // exitEditingMode();
846
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
847
        }
848

    
849

    
850
        public void beginEditingGroup(String description)
851
                        throws NeedEditingModeException {
852
                checkInEditingMode();
853
                commands.startComplex(description);
854
        }
855

    
856
        public void endEditingGroup() throws NeedEditingModeException {
857
                checkInEditingMode();
858
                commands.endComplex();
859
        }
860

    
861
        public boolean isAppendModeSupported() {
862
                return this.provider.supportsAppendMode();
863
        }
864

    
865

    
866
        public void export(DataServerExplorer explorer, NewFeatureStoreParameters params)
867
                        throws DataException {
868

    
869
                if (this.getFeatureTypes().size() != 1) {
870
                        throw new NotYetImplemented(
871
                                        "export whith more than one type not yet implemented");
872
                }
873
                try {
874
                        FeatureType type = this.getDefaultFeatureType();
875
                        if (params.getDefaultFeatureType() == null) {
876
                                params.setDefaultFeatureType(type);
877
                        }
878
                        explorer.add(params, false);
879

    
880
                        DataManager manager = DALLocator.getDataManager();
881
                        FeatureStore target = (FeatureStore) manager
882
                                        .createStore(params);
883
                        target.edit(MODE_APPEND);
884

    
885
                        FeatureSet features = this.getFeatureSet();
886
                        Iterator it1 = features.iterator();
887
                        while (it1.hasNext()) {
888
                                Feature feature = (Feature) it1.next();
889
                                target.insert(target.createNewFeature(type, feature));
890
                        }
891
                        features.dispose();
892
                        target.finishEditing();
893
                        target.dispose();
894
                } catch (Exception e) {
895
                        throw new DataExportException(e, params.toString());
896
                }
897
        }
898

    
899
        //
900
        // ====================================================================
901
        // Obtencion de datos
902
        // getDataCollection, getFeatureCollection
903
        //
904

    
905
        public DataSet getDataSet() throws DataException {
906
                checkNotInAppendMode();
907
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
908
                return new DefaultFeatureSet(this, query);
909
        }
910

    
911
        public DataSet getDataSet(DataQuery dataQuery)
912
                        throws DataException {
913
                checkNotInAppendMode();
914
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
915
        }
916

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

    
922
        public void getDataSet(DataQuery dataQuery, Observer observer)
923
                        throws DataException {
924
                checkNotInAppendMode();
925
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
926
        }
927

    
928
        public FeatureSet getFeatureSet() throws DataException {
929
                checkNotInAppendMode();
930
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
931
                return new DefaultFeatureSet(this, query);
932
        }
933

    
934
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
935
                        throws DataException {
936
                checkNotInAppendMode();
937
                fixFeatureQuery(featureQuery);
938
                return new DefaultFeatureSet(this, featureQuery);
939
        }
940

    
941
        private void fixFeatureQuery(FeatureQuery featureQuery)
942
                        throws DataException {
943
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
944
                if (featureQuery.getAttributeNames() != null){
945
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
946
                                        .getFeatureType();
947
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
948
                                        .getAttributeNames()));
949
                }
950
        }
951

    
952
        public void getFeatureSet(Observer observer)
953
                        throws DataException {
954
                checkNotInAppendMode();
955
                this.getFeatureSet(null, observer);
956
        }
957

    
958
        public void getFeatureSet(FeatureQuery query, Observer observer)
959
                        throws DataException {
960
                class LoadInBackGround implements Runnable {
961
                        private FeatureStore store;
962
                        private FeatureQuery query;
963
                        private Observer observer;
964
                        private Executor executor;
965
                        private FeatureStoreNotification notification;
966

    
967
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
968
                                        Observer observer, Executor executor) {
969
                                this.store = store;
970
                                this.query = query;
971
                                this.observer = observer;
972
                                this.executor = executor;
973
                        }
974

    
975
                        void notify(FeatureStoreNotification theNotification) {
976
                                if (executor == null) {
977
                                        observer.update(store, theNotification);
978
                                        return;
979
                                }
980
                                this.notification = theNotification;
981
                                executor.execute(new Runnable() {
982
                                        public void run() {
983
                                                observer.update(store, notification);
984
                                        }
985
                                });
986

    
987
                        }
988

    
989
                        public void run() {
990
                                try {
991
                                        FeatureSet set = store.getFeatureSet(query);
992
                                        notify(new DefaultFeatureStoreNotification(store,
993
                                                        FeatureStoreNotification.LOAD_FINISHED, set));
994
                                } catch (Exception e) {
995
                                        notify(new DefaultFeatureStoreNotification(store,
996
                                                        FeatureStoreNotification.LOAD_FINISHED, e));
997
                                }
998
                        }
999
                }
1000

    
1001
                checkNotInAppendMode();
1002
                if (query == null) {
1003
                        query = new FeatureQuery(this.getDefaultFeatureType());
1004
                }
1005
                Executor executor = ToolsLocator.getTaskManager().getExecutor();
1006
                LoadInBackGround task = new LoadInBackGround(this, query, observer,
1007
                                executor);
1008
                Thread thread = new Thread(task);
1009
                thread.run();
1010
        }
1011

    
1012
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
1013
                checkNotInAppendMode();
1014
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
1015
        }
1016

    
1017
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
1018
                        throws DataException {
1019
                checkNotInAppendMode();
1020
                featureType = fixFeatureType((DefaultFeatureType) featureType);
1021
                // TODO comprobar que el id es de este store
1022

    
1023
                if (this.mode == MODE_FULLEDIT) {
1024
                        Feature f = featureManager.get(reference, this, featureType);
1025
                        if (f!=null) {
1026
                                return f;
1027
                        }
1028
                }
1029
                return new DefaultFeature(this, this.provider
1030
                                .getFeatureDataByReference((FeatureReferenceProviderServices) reference));
1031
        }
1032

    
1033
        //
1034
        // ====================================================================
1035
        // Gestion de features
1036
        //
1037

    
1038
        private FeatureType fixFeatureType(DefaultFeatureType type)
1039
                        throws DataException {
1040
                FeatureType defaultType = this.getDefaultFeatureType();
1041
                if (type == null || type.equals(defaultType)) {
1042
                        return defaultType;
1043
                }
1044
                if (type.isSubtypeOf(defaultType)) {
1045
                        return type;
1046
                }
1047
                Iterator iter = this.getFeatureTypes().iterator();
1048
                FeatureType tmpType;
1049
                while (iter.hasNext()) {
1050
                        tmpType = (FeatureType) iter.next();
1051
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
1052
                                return type;
1053
                        }
1054

    
1055
                }
1056
                throw new IllegalFeatureTypeException(getName());
1057
        }
1058

    
1059
        public void validateFeatures(int mode) throws DataException {
1060
                try {
1061
                        checkNotInAppendMode();
1062
                        FeatureSet collection = this.getFeatureSet();
1063
                        Iterator iter = collection.iterator();
1064
                        long previousVersionOfUpdate = currentVersionOfUpdate();
1065
                        while (iter.hasNext()) {
1066
                                ((DefaultFeature) iter.next()).validate(mode);
1067
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1068
                                        throw new ConcurrentDataModificationException(getName());
1069
                                }
1070
                        }
1071
                } catch (Exception e) {
1072
                        throw new ValidateFeaturesException(e, getName());
1073
                }
1074
        }
1075

    
1076
        public FeatureType getDefaultFeatureType() throws DataException {
1077
                try {
1078
                        if (isEditing()) {
1079
                                FeatureType auxFeatureType=featureTypeManager.getType(defaultFeatureType.getId());
1080
                                if (auxFeatureType!=null)
1081
                                        return auxFeatureType;
1082
                        }
1083
                        FeatureType type = this.transforms.getDefaultFeatureType();
1084
                        if (type != null) {
1085
                                return type;
1086
                        }
1087
                        return defaultFeatureType;
1088
                } catch (Exception e) {
1089
                        throw new GetFeatureTypeException(e, getName());
1090
                }
1091
        }
1092

    
1093
        public List getFeatureTypes() throws DataException {
1094
                try {
1095
                        List types;
1096
                        if (isEditing()) {
1097
                                types=new ArrayList();
1098
                                Iterator it=featureTypes.iterator();
1099
                                while (it.hasNext()) {
1100
                                        FeatureType type = (FeatureType) it.next();
1101
                                        type=featureTypeManager.getType(type.getId());
1102
                                        if (type!=null) {
1103
                                                types.add(type);
1104
                                        }
1105
                                }
1106
                                it = featureTypeManager.newsIterator();
1107
                                while (it.hasNext()) {
1108
                                        FeatureType type = (FeatureType) it.next();
1109
                                        types.add(type);
1110
                                }
1111
                        } else {
1112
                                types = this.transforms.getFeatureTypes();
1113
                                if (types == null) {
1114
                                        types = featureTypes;
1115
                                }
1116
                        }
1117
                        return Collections.unmodifiableList(types);
1118
                } catch (Exception e) {
1119
                        throw new GetFeatureTypeException(e, getName());
1120
                }
1121
        }
1122

    
1123
        public Feature createFeature(FeatureData data)
1124
                        throws DataException {
1125
                DefaultFeature feature = new DefaultFeature(this, data);
1126
                return feature;
1127
        }
1128

    
1129
        public Feature createFeature(FeatureData data, FeatureType type)
1130
                        throws DataException {
1131
                // FIXME: falta por implementar
1132
                // Comprobar si es un subtipo del feature de data
1133
                // y construir un feature usando el subtipo.
1134
                // Probablemente requiera generar una copia del data.
1135
                throw new NotYetImplemented();
1136
        }
1137

    
1138
        public EditableFeature createNewFeature(FeatureType type,
1139
                        Feature defaultValues)
1140
                        throws DataException {
1141
                try {
1142
                        type = this.fixFeatureType((DefaultFeatureType) type);
1143
                        FeatureData data = this.provider.createFeatureData(type);
1144
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1145
                                        data);
1146
                        feature.initializeValues(defaultValues);
1147
                        return feature;
1148
                } catch (Exception e) {
1149
                        throw new CreateFeatureException(e, getName());
1150
                }
1151
        }
1152

    
1153
        public EditableFeature createNewFeature(FeatureType type,
1154
                        boolean defaultValues)
1155
                        throws DataException {
1156
                try {
1157
                        type = this.fixFeatureType((DefaultFeatureType) type);
1158
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, type);
1159
                        if (defaultValues) {
1160
                                feature.initializeValues();
1161
                        }
1162
                        return feature;
1163
                } catch (Exception e) {
1164
                        throw new CreateFeatureException(e, getName());
1165
                }
1166
        }
1167

    
1168
        public EditableFeature createNewFeature(boolean defaultValues)
1169
                        throws DataException {
1170
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1171
        }
1172

    
1173
        public EditableFeature createNewFeature() throws DataException {
1174
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1175
        }
1176

    
1177
        public EditableFeatureType createFeatureType() {
1178
                return new DefaultEditableFeatureType();
1179
        }
1180

    
1181
        //
1182
        // ====================================================================
1183
        // Index related methods
1184
        //
1185

    
1186
        public FeatureIndexes getIndexes() {
1187
                return this.indexes;
1188
        }
1189

    
1190
        public FeatureIndex createIndex(FeatureType featureType,
1191
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1192
                checkNotInAppendMode();
1193
                FeatureIndexProviderServices index = null;
1194
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1195
                try {
1196
                        index.fill();
1197
                } catch (FeatureIndexException e) {
1198
                        throw new InitializeException(index.getName(), e);
1199
                }
1200
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1201
                return index;
1202
        }
1203

    
1204
        public FeatureIndex createIndex(FeatureType featureType,
1205
                        String attributeName, String indexName, Observer observer) {
1206
                // TODO Implement observer interaction
1207
                throw new UnsupportedOperationException();
1208
        }
1209

    
1210
        //
1211
        // ====================================================================
1212
        // Transforms related methods
1213
        //
1214

    
1215
        public FeatureStoreTransforms getTransforms() {
1216
                return this.transforms;
1217
        }
1218

    
1219
        public FeatureQuery createFeatureQuery() {
1220
        return new FeatureQuery();
1221
    }
1222

    
1223
    public boolean canRedo() {
1224
        return commands.canRedo();
1225
    }
1226

    
1227
    public boolean canUndo() {
1228
        return commands.canUndo();
1229
    }
1230

    
1231
    public void redo(int num) throws RedoException {
1232
        commands.redo(num);
1233
    }
1234

    
1235
    public void undo(int num) throws UndoException {
1236
        commands.undo(num);
1237
    }
1238
}