Statistics
| Revision:

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

History | View | Annotate | Download (44.2 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
import java.util.Set;
8

    
9
import org.cresques.cts.IProjection;
10
import org.gvsig.fmap.dal.DALLocator;
11
import org.gvsig.fmap.dal.DataManager;
12
import org.gvsig.fmap.dal.DataQuery;
13
import org.gvsig.fmap.dal.DataServerExplorer;
14
import org.gvsig.fmap.dal.DataSet;
15
import org.gvsig.fmap.dal.DataStore;
16
import org.gvsig.fmap.dal.DataStoreNotification;
17
import org.gvsig.fmap.dal.DataStoreParameters;
18
import org.gvsig.fmap.dal.exception.CloseException;
19
import org.gvsig.fmap.dal.exception.DataException;
20
import org.gvsig.fmap.dal.exception.InitializeException;
21
import org.gvsig.fmap.dal.exception.OpenException;
22
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
23
import org.gvsig.fmap.dal.exception.ReadException;
24
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
25
import org.gvsig.fmap.dal.feature.EditableFeature;
26
import org.gvsig.fmap.dal.feature.EditableFeatureType;
27
import org.gvsig.fmap.dal.feature.Feature;
28
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
29
import org.gvsig.fmap.dal.feature.FeatureIndex;
30
import org.gvsig.fmap.dal.feature.FeatureIndexes;
31
import org.gvsig.fmap.dal.feature.FeatureLocks;
32
import org.gvsig.fmap.dal.feature.FeatureQuery;
33
import org.gvsig.fmap.dal.feature.FeatureReference;
34
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
35
import org.gvsig.fmap.dal.feature.FeatureSelection;
36
import org.gvsig.fmap.dal.feature.FeatureSet;
37
import org.gvsig.fmap.dal.feature.FeatureStore;
38
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
39
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
40
import org.gvsig.fmap.dal.feature.FeatureType;
41
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
42
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
43
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
44
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
45
import org.gvsig.fmap.dal.feature.exception.DataExportException;
46
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
47
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
48
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
49
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
50
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
51
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
52
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
53
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
54
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
55
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
56
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
57
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
58
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
59
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
60
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
61
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
62
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
63
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
64
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
65
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
66
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
67
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
68
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureData;
69
import org.gvsig.fmap.dal.feature.spi.FeatureData;
70
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
71
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
72
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
73
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
74
import org.gvsig.fmap.dal.impl.DefaultDataManager;
75
import org.gvsig.fmap.dal.resource.Resource;
76
import org.gvsig.fmap.geom.primitive.Envelope;
77
import org.gvsig.tools.ToolsLocator;
78
import org.gvsig.tools.dynobject.DelegatedDynObject;
79
import org.gvsig.tools.dynobject.DynClass;
80
import org.gvsig.tools.dynobject.DynObject;
81
import org.gvsig.tools.dynobject.DynObjectManager;
82
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
83
import org.gvsig.tools.dynobject.exception.DynMethodException;
84
import org.gvsig.tools.exception.NotYetImplemented;
85
import org.gvsig.tools.observer.Observable;
86
import org.gvsig.tools.observer.Observer;
87
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
88
import org.gvsig.tools.persistence.PersistenceException;
89
import org.gvsig.tools.persistence.PersistenceValueNotFoundException;
90
import org.gvsig.tools.persistence.PersistentState;
91
import org.gvsig.tools.task.Executor;
92
import org.gvsig.tools.undo.RedoException;
93
import org.gvsig.tools.undo.UndoException;
94
import org.gvsig.tools.undo.command.Command;
95
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97

    
98
final public class DefaultFeatureStore implements
99
FeatureStoreProviderServices,
100
Observer {
101

    
102
        final static private Logger logger = LoggerFactory
103
        .getLogger(DefaultFeatureStore.class);
104

    
105
        private DataStoreParameters parameters = null;
106
        private FeatureSelection selection;
107
        private FeatureLocks locks;
108

    
109
        private DelegateWeakReferencingObservable delegateObservable = new DelegateWeakReferencingObservable(this);
110

    
111
        private FeatureCommandsStack commands;
112
        private FeatureTypeManager featureTypeManager;
113
        private FeatureManager featureManager;
114
        private SpatialManager spatialManager;
115

    
116
        private FeatureType defaultFeatureType = null;
117
        private List featureTypes = new ArrayList();
118

    
119
        private int mode = MODE_QUERY;
120
        private long versionOfUpdate = 0;
121
        private boolean hasStrongChanges = true;
122
        private boolean hasInserts = true;
123

    
124
        private DefaultDataManager dataManager = null;
125

    
126
        private FeatureStoreProvider provider = null;
127

    
128
        private DefaultFeatureIndexes indexes;
129

    
130
        private DefaultFeatureStoreTransforms transforms;
131

    
132
        private DelegatedDynObject dynObject;
133

    
134
        private Long featureCount = null;
135

    
136
        private long temporalOid = 0;
137

    
138
        /*
139
         * TODO:
140
         *
141
         * - Comprobar que solo se pueden a�adir reglas de validacion sobre un
142
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
143
         * featureType al que se le han cambiado las reglas de validacion cuando
144
         * hasStrongChanges=false.
145
         */
146

    
147
        public DefaultFeatureStore() {
148

    
149
        }
150

    
151
        public DefaultFeatureStore(DefaultDataManager manager,
152
                        DataStoreParameters parameters, FeatureStoreProvider provider)
153
        throws InitializeException {
154
                initialize(manager, parameters, provider);
155
        }
156

    
157
        private void initialize(DefaultDataManager manager,
158
                        DataStoreParameters parameters, FeatureStoreProvider provider)
159
        throws InitializeException {
160

    
161
                DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
162

    
163
                this.dynObject = (DelegatedDynObject) dynManager
164
                .createDynObject(dynManager
165
                                .get(DataStore.DYNCLASS_NAME));
166
                this.dataManager = manager;
167
                this.provider = provider;
168
                this.parameters = parameters;
169
                this.transforms = new DefaultFeatureStoreTransforms(this);
170
                this.provider.initialize(this);
171
                try {
172
                        indexes=new DefaultFeatureIndexes(this);
173
                } catch (DataException e) {
174
                        throw new InitializeException(e);
175
                }
176
                this.delegate(provider);
177
        }
178

    
179
        public Logger getLogger() {
180
                return DefaultFeatureStore.logger;
181
        }
182

    
183
        public String getName() {
184
                return this.parameters.getDataStoreName();
185
        }
186

    
187
        public DataStoreParameters getParameters() {
188
                return parameters;
189
        }
190

    
191
        public int getMode() {
192
                return this.mode;
193
        }
194

    
195
        public DataManager getManager() {
196
                return this.dataManager;
197
        }
198

    
199
        public Iterator getChildren() {
200
                return this.provider.getChilds();
201
        }
202

    
203
        public FeatureStoreProvider getProvider() {
204
                return this.provider;
205
        }
206

    
207
        public FeatureManager getFeatureManager() {
208
                return this.featureManager;
209
        }
210

    
211
        public void setFeatureTypes(List types, FeatureType defaultType) {
212
                this.featureTypes = types;
213
                this.defaultFeatureType = defaultType;
214
        }
215

    
216
        public void open() throws OpenException {
217
                // TODO: Se puede hacer un open estando en edicion ?
218
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
219
                this.provider.open();
220
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
221
        }
222

    
223
        public void refresh() throws OpenException, InitializeException {
224
                if (this.mode != MODE_QUERY) {
225
                        throw new IllegalStateException();
226
                }
227
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
228
                this.featureCount = null;
229
                this.provider.refresh();
230
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
231
        }
232

    
233
        public void close() throws CloseException {
234
                // TODO: Se puede hacer un close estando en edicion ?
235
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
236
                this.featureCount = null;
237
                this.provider.close();
238
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
239
        }
240

    
241
        public void dispose() throws CloseException {
242
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
243
                this.provider.dispose();
244
                if (this.selection != null) {
245
                        this.selection.dispose();
246
                        this.selection = null;
247
                }
248
                this.commands = null;
249
                this.featureCount = null;
250
                if (this.locks != null) {
251
                        //this.locks.dispose();
252
                        this.locks = null;
253
                }
254

    
255
                if (this.featureTypeManager != null) {
256
                        this.featureTypeManager.dispose();
257
                        this.featureTypeManager = null;
258
                }
259

    
260
                this.featureManager = null;
261
                this.spatialManager = null;
262

    
263
                this.parameters = null;
264
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
265
                this.delegateObservable.deleteObservers();
266
                this.delegateObservable = null;
267
        }
268

    
269
        public boolean allowWrite() {
270
                return this.provider.allowWrite();
271
        }
272

    
273
        public boolean canWriteGeometry(int geometryType) throws DataException {
274
                return this.provider.canWriteGeometry(geometryType);
275
        }
276

    
277
        public DataServerExplorer getExplorer() throws ReadException,
278
                        ValidateDataParametersException {
279
                return this.provider.getExplorer();
280
        }
281

    
282
        /*
283
        public Metadata getMetadata() throws MetadataNotFoundException {
284
                // TODO:
285
                // Si el provider devuelbe null habria que ver de construir aqui
286
                // los metadatos basicos, como el Envelope y el SRS.
287

288
                // TODO: Estando en edicion el Envelope deberia de
289
                // actualizarse usando el spatialManager
290
                return this.provider.getMetadata();
291
        }
292
         */
293

    
294
        public Envelope getEnvelope() throws DataException {
295
                if (this.mode == MODE_FULLEDIT) {
296
                        return this.spatialManager.getEnvelope();
297
                }
298
                return this.provider.getEnvelope();
299
        }
300

    
301
        /**
302
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
303
         */
304
        public IProjection getSRSDefaultGeometry() throws DataException {
305
                return this.getDefaultFeatureType().getDefaultSRS();
306
        }
307

    
308
        public FeatureSelection createDefaultFeatureSelection()
309
        throws DataException {
310
                return new DefaultFeatureSelection(this);
311
        }
312

    
313
        public FeatureData createDefaultFeatureData(FeatureType type)
314
        throws DataException {
315
                if( type.hasOID() ) {
316
                        return new DefaultFeatureData(type, this.provider.createNewOID());
317
                }
318
                return new DefaultFeatureData(type);
319
        }
320

    
321
        public void saveToState(PersistentState state) throws PersistenceException {
322
                state.set("dataStoreName", this.getName());
323
                state.set("parameters", this.parameters);
324
                state.set("provider", this.provider);
325
                if (this.selection != null) {
326
                        state.set("selection", this.selection);
327
                }
328
        }
329

    
330
        public void loadFromState(PersistentState state) throws PersistenceException {
331
                if (this.provider != null) {
332
                        throw new PersistenceException("Provider not set");
333
                }
334
                if (this.getManager() == null) {
335
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
336
                }
337

    
338
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
339
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
340

    
341
                try {
342

    
343
                        initialize(this.dataManager, params, provider);
344
                        try {
345
                                setSelection((FeatureSelection) state.get("selection"));
346
                        } catch (PersistenceValueNotFoundException e) {
347
                                setSelection(null);
348
                        }
349

    
350
                } catch (InitializeException e) {
351
                        throw new PersistenceException(e);
352
                } catch (DataException e) {
353
                        throw new PersistenceException(e);
354
                }
355

    
356
        }
357

    
358
        //
359
        // ====================================================================
360
        // Gestion de la seleccion
361
        //
362

    
363
        public void setSelection(DataSet selection)
364
        throws DataException {
365
                this.setSelection((FeatureSet) selection);
366
        }
367

    
368
        public DataSet createSelection() throws DataException {
369
                return createFeatureSelection();
370
        }
371

    
372
        public DataSet getSelection() throws DataException {
373
                return this.getFeatureSelection();
374
        }
375

    
376
    public void setSelection(FeatureSet selection) throws DataException {
377
        setSelection(selection, true);
378
    }
379

    
380
    /**
381
     * @see #setSelection(FeatureSet)
382
     * @param undoable
383
     *            if the action must be undoable
384
     */
385
    public void setSelection(FeatureSet selection, boolean undoable)
386
        throws DataException {
387
                if (selection.equals(this.selection)) {
388
                        return;
389
                }
390
                if (!selection.isFromStore(this)) {
391
                        throw new SelectionNotAllowedException(getName());
392
                }
393

    
394
                this.selection.deleteObserver(this);
395
                if (selection instanceof FeatureSelection) {
396
                        if (undoable && isEditing()) {
397
                                commands.selectionSet(this, this.selection,
398
                                                (FeatureSelection) selection);
399
                        }
400
                        this.selection = (FeatureSelection) selection;
401
                } else {
402
                        if (undoable && isEditing()) {
403
                                commands.startComplex("_selectionSet");
404
                        }
405
                        if (selection instanceof DefaultFeatureSelection) {
406
                DefaultFeatureSelection defSelection = (DefaultFeatureSelection) selection;
407
                defSelection.deselectAll(undoable);
408
                defSelection.select(selection, undoable);
409
            } else {
410
                this.selection.deselectAll();
411
                this.selection.select(selection);
412
            }
413
                        if (undoable && isEditing()) {
414
                                commands.endComplex();
415
                        }
416
                }
417
                this.selection.addObserver(this);
418

    
419
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
420
        }
421

    
422
        public FeatureSelection createFeatureSelection() throws DataException {
423
                return this.provider.createFeatureSelection();
424
        }
425

    
426
        public FeatureSelection getFeatureSelection() throws DataException {
427
                if (selection == null) {
428
                        this.selection = createFeatureSelection();
429
                        this.selection.addObserver(this);
430
                }
431
                return selection;
432
        }
433

    
434
        //
435
        // ====================================================================
436
        // Gestion de notificaciones
437
        //
438

    
439
        public void notifyChange(String notification) {
440
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
441
                                notification));
442

    
443
        }
444

    
445
        public void notifyChange(String notification, Feature feature) {
446
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
447
                                this, notification, feature));
448
        }
449

    
450
        public void notifyChange(String notification, Command command) {
451
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
452
                                this, notification, command));
453
        }
454

    
455
        public void notifyChange(String notification, EditableFeatureType type) {
456
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
457
                                notification, type));
458
        }
459

    
460
        /*
461
         * (non-Javadoc)
462
         *
463
         * @see
464
         * org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices#notifyChange
465
         * (java.lang.String, org.gvsig.fmap.dal.resource.Resource)
466
         */
467
        public void notifyChange(String notification, Resource resource) {
468
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
469
                                FeatureStoreNotification.RESOURCE_CHANGED));
470
        }
471

    
472

    
473
        //
474
        // ====================================================================
475
        // Gestion de bloqueos
476
        //
477

    
478
        public boolean isLocksSupported() {
479
                return this.provider.isLocksSupported();
480
        }
481

    
482
        public FeatureLocks getLocks() throws DataException {
483
                if (!this.provider.isLocksSupported()) {
484
                        getLogger().warn("Locks not supporteds");
485
                        return null;
486
                }
487
                if (locks == null) {
488
                        this.locks = this.provider.createFeatureLocks();
489
                }
490
                return locks;
491
        }
492

    
493
        //
494
        // ====================================================================
495
        // Interface Observable
496
        //
497

    
498
        public void disableNotifications() {
499
                this.delegateObservable.disableNotifications();
500

    
501
        }
502

    
503
        public void enableNotifications() {
504
                this.delegateObservable.enableNotifications();
505
        }
506

    
507
        public void beginComplexNotification() {
508
                this.delegateObservable.beginComplexNotification();
509

    
510
        }
511

    
512
        public void endComplexNotification() {
513
                this.delegateObservable.endComplexNotification();
514

    
515
        }
516

    
517
        public void addObserver(Observer observer) {
518
                this.delegateObservable.addObserver(observer);
519

    
520
        }
521

    
522
        public void deleteObserver(Observer observer) {
523
                this.delegateObservable.deleteObserver(observer);
524
        }
525

    
526
        public void deleteObservers() {
527
                this.delegateObservable.deleteObservers();
528

    
529
        }
530

    
531
        //
532
        // ====================================================================
533
        // Interface Observer
534
        //
535
        // Usado para observar:
536
        // - su seleccion
537
        // - sus bloqueos
538
        // - sus recursos
539
        //
540

    
541
        public void update(Observable observable, Object notification) {
542
                if (observable instanceof FeatureSet) {
543
                        if (observable == this.selection) {
544
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
545
                        } else if (observable == this.locks) {
546
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
547
                        }
548

    
549
                } else if (observable instanceof FeatureStoreProvider) {
550
                        if (observable == this.provider) {
551

    
552
                        }
553

    
554
                }
555
        }
556

    
557
        //
558
        // ====================================================================
559
        // Edicion
560
        //
561

    
562
        private void newVersionOfUpdate() {
563
                this.versionOfUpdate++;
564
        }
565

    
566
        private long currentVersionOfUpdate() {
567
                return this.versionOfUpdate;
568
        }
569

    
570
        private void checkInEditingMode()
571
        throws NeedEditingModeException {
572
                if (mode != MODE_FULLEDIT) {
573
                        throw new NeedEditingModeException(this.getName());
574
                }
575
        }
576

    
577
        private void checkNotInAppendMode() throws IllegalStateException {
578
                if (mode == MODE_APPEND) {
579
                        throw new IllegalStateException(this.getName());
580
                }
581
        }
582

    
583
        private void checkIsOwnFeature(Feature feature)
584
        throws IllegalFeatureException {
585
                if (((DefaultFeature) feature).getStore() != this) {
586
                        throw new IllegalFeatureException(this.getName());
587
                }
588
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
589
                // fixFeatureType((DefaultFeatureType) feature.getType());
590
        }
591

    
592
        private void exitEditingMode() {
593
                if (commands != null) {
594
                        commands.clear();
595
                        commands = null;
596
                }
597

    
598
                if (featureTypeManager != null) {
599
                        featureTypeManager.dispose();
600
                        featureTypeManager = null;
601

    
602
                }
603

    
604
                // TODO implementar un dispose para estos dos
605
                featureManager = null;
606
                spatialManager = null;
607

    
608
                featureCount = null;
609

    
610
                mode = MODE_QUERY;
611
                hasStrongChanges = true; // Lo deja a true por si las moscas
612
                hasInserts = true;
613
        }
614

    
615
        synchronized public void edit() throws DataException {
616
                edit(MODE_FULLEDIT);
617
        }
618

    
619
        synchronized public void edit(int mode) throws DataException {
620
                try {
621
                        if ( this.mode != MODE_QUERY ) {
622
                                throw new AlreadyEditingException(this.getName());
623
                        }
624
                        if (!this.provider.supportsAppendMode()) {
625
                                mode = MODE_FULLEDIT;
626
                        }
627
                        switch (mode) {
628
                        case MODE_QUERY:
629
                                throw new IllegalStateException(this.getName());
630

    
631
                        case MODE_FULLEDIT:
632
                                if (!this.transforms.isEmpty()) {
633
                                        throw new IllegalStateException(this.getName());
634
                                }
635
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
636
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
637
                                featureTypeManager = new FeatureTypeManager(this,
638
                                                new MemoryExpansionAdapter());
639
                                spatialManager = new SpatialManager(this, provider
640
                                                .getEnvelope());
641

    
642
                                commands = new DefaultFeatureCommandsStack(featureManager,
643
                                                spatialManager, featureTypeManager);
644
                                this.mode = MODE_FULLEDIT;
645
                                hasStrongChanges = false;
646
                                hasInserts = false;
647
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
648
                                break;
649
                        case MODE_APPEND:
650
                                if (!this.transforms.isEmpty()) {
651
                                        throw new IllegalStateException(this.getName());
652
                                }
653
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
654
                                this.provider.beginAppend();
655
                                this.mode = MODE_APPEND;
656
                                hasInserts = false;
657
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
658
                                break;
659
                        }
660
                } catch (Exception e) {
661
                        throw new StoreEditException(e, this.getName());
662
                }
663
        }
664

    
665
        public boolean isEditing() {
666
                return mode == MODE_FULLEDIT;
667
        }
668

    
669
        public boolean isAppending() {
670
                return mode == MODE_APPEND;
671
        }
672

    
673
        synchronized public void update(EditableFeatureType type)
674
        throws DataException {
675
                try {
676
                        checkInEditingMode();
677
                        if (type == null) {
678
                                throw new NullFeatureTypeException(getName());
679
                        }
680
                        // FIXME: Comprobar que es un featureType aceptable.
681
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
682
                        newVersionOfUpdate();
683

    
684
                        FeatureType oldt = type.getSource().getCopy();
685
                        FeatureType newt = type.getNotEditableCopy();
686
                        commands.update(newt, oldt);
687

    
688
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
689
                                hasStrongChanges = true;
690
                        }
691
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
692
                } catch (Exception e) {
693
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
694
                }
695
        }
696

    
697
        synchronized public void delete(Feature feature) throws DataException {
698
                try {
699
                        checkInEditingMode();
700
                        checkIsOwnFeature(feature);
701
                        if (feature instanceof EditableFeature) {
702
                                throw new StoreDeleteEditableFeatureException(getName());
703
                        }
704
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
705
                        this.commands.delete(feature);
706
                        newVersionOfUpdate();
707
                        hasStrongChanges = true;
708
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
709
                } catch (Exception e) {
710
                        throw new StoreDeleteFeatureException(e, this.getName());
711
                }
712
        }
713

    
714
        private static EditableFeature lastChangedFeature = null;
715

    
716
        synchronized public void insert(EditableFeature feature)
717
        throws DataException {
718
                try {
719
                        switch (mode) {
720
                        case MODE_QUERY:
721
                                throw new NeedEditingModeException(this.getName());
722

    
723
                        case MODE_APPEND:
724
                                checkIsOwnFeature(feature);
725
                                if (feature.getSource() != null) {
726
                                        throw new NoNewFeatureInsertException(this.getName());
727
                                }
728
                                this.featureCount = null;
729
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
730
                                feature.validate(Feature.UPDATE);
731
                                provider.append(((DefaultEditableFeature) feature).getData());
732
                                hasStrongChanges = true;
733
                                hasInserts = true;
734
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
735
                                break;
736

    
737
                        case MODE_FULLEDIT:
738
                                checkIsOwnFeature(feature);
739
                                if (feature.getSource() != null) {
740
                                        throw new NoNewFeatureInsertException(this.getName());
741
                                }
742
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
743
                                newVersionOfUpdate();
744
                                if (lastChangedFeature ==null || lastChangedFeature.getSource() != feature.getSource()) {
745
                                        lastChangedFeature = feature;
746
                                        feature.validate(Feature.UPDATE);
747
                                        lastChangedFeature = null;
748
                                }
749
                                commands.insert(feature.getNotEditableCopy());
750
                                hasStrongChanges = true;
751
                                hasInserts = true;
752
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
753
                                break;
754
                        }
755
                } catch (Exception e) {
756
                        throw new StoreInsertFeatureException(e, this.getName());
757
                }
758
        }
759

    
760
        synchronized public void update(EditableFeature feature)
761
        throws DataException {
762
                try {
763
                        if ((feature).getSource() == null) {
764
                                insert(feature);
765
                                return;
766
                        }
767
                        checkInEditingMode();
768
                        checkIsOwnFeature(feature);
769
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
770
                        newVersionOfUpdate();
771
                        if (lastChangedFeature==null || lastChangedFeature.getSource() != feature.getSource()) {
772
                                lastChangedFeature = feature;
773
                                feature.validate(Feature.UPDATE);
774
                                lastChangedFeature = null;
775
                        }
776

    
777
                        Feature oldf = feature.getSource();
778
                        Feature newf = feature.getNotEditableCopy();
779
                        commands.update(newf, oldf);
780

    
781
                        hasStrongChanges = true;
782
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
783
                } catch (Exception e) {
784
                        throw new StoreUpdateFeatureException(e, this.getName());
785
                }
786
        }
787

    
788
        synchronized public void redo() throws RedoException {
789
                Command redo = commands.getNextRedoCommand();
790
                try {
791
                        checkInEditingMode();
792
                } catch (NeedEditingModeException ex) {
793
                        throw new RedoException(redo, ex);
794
                }
795
                notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
796
                newVersionOfUpdate();
797
                commands.redo();
798
                hasStrongChanges = true;
799
                notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
800
        }
801

    
802
        synchronized public void undo() throws UndoException {
803
                Command undo = commands.getNextUndoCommand();
804
                try {
805
                        checkInEditingMode();
806
                } catch (NeedEditingModeException ex) {
807
                        throw new UndoException(undo, ex);
808
                }
809
                notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
810
                newVersionOfUpdate();
811
                commands.undo();
812
                hasStrongChanges = true;
813
                notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
814
        }
815

    
816
        public List getRedoInfos() {
817
                if (isEditing() && commands != null) {
818
                        return commands.getRedoInfos();
819
                } else {
820
                        return null;
821
                }
822
        }
823

    
824
        public List getUndoInfos() {
825
                if (isEditing() && commands != null) {
826
                        return commands.getUndoInfos();
827
                } else {
828
                        return null;
829
                }
830
        }
831

    
832
        public synchronized FeatureCommandsStack getCommandsStack()
833
        throws DataException {
834
                checkInEditingMode();
835
                return commands;
836
        }
837

    
838
        synchronized public void cancelEditing() throws DataException {
839
                spatialManager.cancelModifies();
840
                try {
841
                        checkInEditingMode();
842

    
843
                        boolean clearSelection = this.hasStrongChanges;
844
                        if (this.selection instanceof FeatureReferenceSelection) {
845
                                clearSelection = this.hasInserts;
846
                        }
847
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
848
                        exitEditingMode();
849
                        if (clearSelection) {
850
                                ((FeatureSelection) this.getSelection()).deselectAll();
851
                        }
852
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
853
                } catch (Exception e) {
854
                        throw new StoreCancelEditingException(e, this.getName());
855
                }
856
        }
857

    
858
        synchronized public void finishEditing() throws DataException {
859
                try {
860
                        switch (mode) {
861
                        case MODE_QUERY:
862
                                throw new NeedEditingModeException(this.getName());
863

    
864
                        case MODE_APPEND:
865
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
866
                                provider.endAppend();
867
                                exitEditingMode();
868
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
869
                                break;
870

    
871
                        case MODE_FULLEDIT:
872
                                if (!hasStrongChanges) {
873
                                        performLightEditing();
874
                                        return;
875
                                }
876
                                if (!this.allowWrite()) {
877
                                        throw new WriteNotAllowedException(getName());
878
                                }
879

    
880
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
881
                                validateFeatures(Feature.FINISH_EDITING);
882
                                provider.performEditing(featureManager.getDeleted(),
883
                                                featureManager.getInserted(),
884
                                                featureManager.getUpdated(),
885
                                                featureTypeManager.getOriginalsFeatureTypesUpdated());
886
                                exitEditingMode();
887
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
888
                                break;
889
                        }
890
                } catch (Exception e) {
891
                        throw new FinishEditingException(e);
892
                }
893
        }
894

    
895
        private void performLightEditing() throws DataException {
896
                throw new NotYetImplemented(
897
                "lightFinishEdition not yet implemented");
898

    
899
                // TODO: implementar
900
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
901
                // exitEditingMode();
902
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
903
        }
904

    
905

    
906
        public void beginEditingGroup(String description)
907
        throws NeedEditingModeException {
908
                checkInEditingMode();
909
                commands.startComplex(description);
910
        }
911

    
912
        public void endEditingGroup() throws NeedEditingModeException {
913
                checkInEditingMode();
914
                commands.endComplex();
915
        }
916

    
917
        public boolean isAppendModeSupported() {
918
                return this.provider.supportsAppendMode();
919
        }
920

    
921

    
922
        public void export(DataServerExplorer explorer, NewFeatureStoreParameters params)
923
        throws DataException {
924

    
925
                if (this.getFeatureTypes().size() != 1) {
926
                        throw new NotYetImplemented(
927
                        "export whith more than one type not yet implemented");
928
                }
929
                FeatureSelection featureSelection=(FeatureSelection)getSelection();
930
                try {
931
                        FeatureType type = this.getDefaultFeatureType();
932
                        if (params.getDefaultFeatureType() == null
933
                                        || params.getDefaultFeatureType().size() == 0) {
934
                                params.setDefaultFeatureType(new DefaultEditableFeatureType(
935
                                                (DefaultFeatureType) type));
936

    
937
                        }
938
                        explorer.add(params, true);
939

    
940
                        DataManager manager = DALLocator.getDataManager();
941
                        FeatureStore target = (FeatureStore) manager
942
                        .createStore(params);
943
                        FeatureType targetType = target.getDefaultFeatureType();
944

    
945
                        target.edit(MODE_APPEND);
946
                        FeatureSet features=null;
947
                        FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
948
                        if (featureSelection.getSize()>0){
949
                                features = this.getFeatureSelection();
950
                        }else{
951
                                if (pk != null && pk.length > 0){
952
                                        FeatureQuery query = createFeatureQuery();
953
                                        for (int i = 0; i < pk.length; i++) {
954
                                                query.getOrder().add(pk[i].getName(), true);
955
                                        }
956
                                        features = this.getFeatureSet(query);
957
                                } else {
958
                                        features = this.getFeatureSet();
959
                                }
960
                        }
961
                        Iterator it1 = features.iterator();
962
                        while (it1.hasNext()) {
963
                                DefaultFeature feature = (DefaultFeature) it1.next();
964
                                target.insert(target.createNewFeature(targetType, feature));
965
                        }
966
                        features.dispose();
967
                        target.finishEditing();
968
                        target.dispose();
969
                } catch (Exception e) {
970
                        throw new DataExportException(e, params.toString());
971
                }
972
        }
973

    
974
        //
975
        // ====================================================================
976
        // Obtencion de datos
977
        // getDataCollection, getFeatureCollection
978
        //
979

    
980
        public DataSet getDataSet() throws DataException {
981
                checkNotInAppendMode();
982
                FeatureQuery query = new DefaultFeatureQuery(this
983
                                .getDefaultFeatureType());
984
                return new DefaultFeatureSet(this, query);
985
        }
986

    
987
        public DataSet getDataSet(DataQuery dataQuery)
988
        throws DataException {
989
                checkNotInAppendMode();
990
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
991
        }
992

    
993
        public void getDataSet(Observer observer) throws DataException {
994
                checkNotInAppendMode();
995
                this.getFeatureSet(null, observer);
996
        }
997

    
998
        public void getDataSet(DataQuery dataQuery, Observer observer)
999
        throws DataException {
1000
                checkNotInAppendMode();
1001
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
1002
        }
1003

    
1004
        public FeatureSet getFeatureSet() throws DataException {
1005
                checkNotInAppendMode();
1006
                FeatureQuery query = new DefaultFeatureQuery(this
1007
                                .getDefaultFeatureType());
1008
                return new DefaultFeatureSet(this, query);
1009
        }
1010

    
1011
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1012
        throws DataException {
1013
                checkNotInAppendMode();
1014
                return new DefaultFeatureSet(this, featureQuery);
1015
        }
1016

    
1017

    
1018
        public FeatureType getFeatureType(FeatureQuery featureQuery)
1019
                        throws DataException {
1020
                DefaultFeatureType fType = (DefaultFeatureType) this
1021
                                .getFeatureType(featureQuery.getFeatureTypeId());
1022
                if (featureQuery.getAttributeNames() != null){
1023
                        return fType.getSubtype(featureQuery.getAttributeNames());
1024
                }
1025
                return fType;
1026
        }
1027

    
1028
        public void getFeatureSet(Observer observer)
1029
        throws DataException {
1030
                checkNotInAppendMode();
1031
                this.getFeatureSet(null, observer);
1032
        }
1033

    
1034
        public void getFeatureSet(FeatureQuery query, Observer observer)
1035
        throws DataException {
1036
                class LoadInBackGround implements Runnable {
1037
                        private FeatureStore store;
1038
                        private FeatureQuery query;
1039
                        private Observer observer;
1040
                        private Executor executor;
1041
                        private FeatureStoreNotification notification;
1042

    
1043
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
1044
                                        Observer observer, Executor executor) {
1045
                                this.store = store;
1046
                                this.query = query;
1047
                                this.observer = observer;
1048
                                this.executor = executor;
1049
                        }
1050

    
1051
                        void notify(FeatureStoreNotification theNotification) {
1052
                                if (executor == null) {
1053
                                        observer.update(store, theNotification);
1054
                                        return;
1055
                                }
1056
                                this.notification = theNotification;
1057
                                executor.execute(new Runnable() {
1058
                                        public void run() {
1059
                                                observer.update(store, notification);
1060
                                        }
1061
                                });
1062

    
1063
                        }
1064

    
1065
                        public void run() {
1066
                                try {
1067
                                        FeatureSet set = store.getFeatureSet(query);
1068
                                        notify(new DefaultFeatureStoreNotification(store,
1069
                                                        FeatureStoreNotification.LOAD_FINISHED, set));
1070
                                } catch (Exception e) {
1071
                                        notify(new DefaultFeatureStoreNotification(store,
1072
                                                        FeatureStoreNotification.LOAD_FINISHED, e));
1073
                                }
1074
                        }
1075
                }
1076

    
1077
                checkNotInAppendMode();
1078
                if (query == null) {
1079
                        query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1080
                }
1081
                Executor executor = ToolsLocator.getTaskManager().getExecutor();
1082
                LoadInBackGround task = new LoadInBackGround(this, query, observer,
1083
                                executor);
1084
                Thread thread = new Thread(task);
1085
                thread.run();
1086
        }
1087

    
1088
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
1089
                checkNotInAppendMode();
1090
                DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1091
                FeatureType featureType;
1092
                if (ref.getFeatureTypeId() == null) {
1093
                        featureType = this.getDefaultFeatureType();
1094
                } else {
1095
                        featureType = this.getFeatureType(ref.getFeatureTypeId());
1096
                }
1097
                return this.getFeatureByReference(reference, featureType);
1098
        }
1099

    
1100
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
1101
        throws DataException {
1102
                checkNotInAppendMode();
1103
                featureType = fixFeatureType((DefaultFeatureType) featureType);
1104
                if (!this.transforms.isEmpty()) {
1105

    
1106
                        featureType = this.transforms
1107
                        .getSourceFeatureTypeFrom(featureType);
1108

    
1109
                }
1110
                // TODO comprobar que el id es de este store
1111

    
1112
                if (this.mode == MODE_FULLEDIT) {
1113
                        Feature f = featureManager.get(reference, this, featureType);
1114
                        if (f!=null) {
1115
                                return f;
1116
                        }
1117
                }
1118
                DefaultFeature feature = new DefaultFeature(
1119
                                this,
1120
                                this.provider
1121
                                .getFeatureDataByReference(
1122
                                                (FeatureReferenceProviderServices) reference,
1123
                                                featureType));
1124

    
1125
                if (!this.transforms.isEmpty()) {
1126
                        return this.transforms.applyTransform(feature, featureType);
1127
                }
1128
                return feature;
1129
        }
1130

    
1131
        //
1132
        // ====================================================================
1133
        // Gestion de features
1134
        //
1135

    
1136
        private FeatureType fixFeatureType(DefaultFeatureType type)
1137
        throws DataException {
1138
                FeatureType original = this.getDefaultFeatureType();
1139

    
1140
                if (type == null || type.equals(original)) {
1141
                        return original;
1142
                } else {
1143
                        if (!type.isSubtypeOf(original)) {
1144
                                Iterator iter = this.getFeatureTypes().iterator();
1145
                                FeatureType tmpType;
1146
                                boolean found = false;
1147
                                while (iter.hasNext()) {
1148
                                        tmpType = (FeatureType) iter.next();
1149
                                        if (type.equals(tmpType)) {
1150
                                                return type;
1151

    
1152
                                        }else if (type.isSubtypeOf(tmpType)) {
1153
                                                found = true;
1154
                                                original = tmpType;
1155
                                                break;
1156
                                        }
1157

    
1158
                                }
1159
                                if (!found) {
1160
                                        throw new IllegalFeatureTypeException(getName());
1161
                                }
1162
                        }
1163
                }
1164

    
1165
                // Checks that type has all fields of pk
1166
                // else add the missing attributes at the end.
1167
                if (!original.hasOID()) {
1168
                        // Gets original pk attributes
1169
                        DefaultEditableFeatureType edOriginal = (DefaultEditableFeatureType) original
1170
                                        .getEditable();
1171
                        FeatureAttributeDescriptor orgAttr;
1172
                        Iterator edOriginalIter = edOriginal.iterator();
1173
                        while (edOriginalIter.hasNext()) {
1174
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1175
                                if (!orgAttr.isPrimaryKey()) {
1176
                                        edOriginalIter.remove();
1177
                                }
1178
                        }
1179

    
1180
                        // Checks if all pk attributes are in type
1181
                        Iterator typeIterator;
1182
                        edOriginalIter = edOriginal.iterator();
1183
                        FeatureAttributeDescriptor attr;
1184
                        while (edOriginalIter.hasNext()) {
1185
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1186
                                typeIterator = type.iterator();
1187
                                while (typeIterator.hasNext()) {
1188
                                        attr = (FeatureAttributeDescriptor) typeIterator.next();
1189
                                        if (attr.getName().equals(orgAttr.getName())) {
1190
                                                edOriginalIter.remove();
1191
                                                break;
1192
                                        }
1193
                                }
1194
                        }
1195

    
1196
                        // add missing pk attributes if any
1197
                        if (edOriginal.size() > 0) {
1198
                                boolean isEditable = type instanceof DefaultEditableFeatureType;
1199
                                DefaultEditableFeatureType edType = (DefaultEditableFeatureType) original
1200
                                                .getEditable();
1201
                                edType.clear();
1202
                                edType.addAll(type);
1203
                                edType.addAll(edOriginal);
1204
                                if (!isEditable) {
1205
                                        type = (DefaultFeatureType) edType.getNotEditableCopy();
1206
                                }
1207
                        }
1208

    
1209
                }
1210

    
1211

    
1212
                return type;
1213
        }
1214

    
1215
        public void validateFeatures(int mode) throws DataException {
1216
                try {
1217
                        checkNotInAppendMode();
1218
                        FeatureSet collection = this.getFeatureSet();
1219
                        Iterator iter = collection.iterator();
1220
                        long previousVersionOfUpdate = currentVersionOfUpdate();
1221
                        while (iter.hasNext()) {
1222
                                ((DefaultFeature) iter.next()).validate(mode);
1223
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1224
                                        throw new ConcurrentDataModificationException(getName());
1225
                                }
1226
                        }
1227
                } catch (Exception e) {
1228
                        throw new ValidateFeaturesException(e, getName());
1229
                }
1230
        }
1231

    
1232
        public FeatureType getDefaultFeatureType() throws DataException {
1233
                try {
1234
                        if (isEditing()) {
1235
                                FeatureType auxFeatureType=featureTypeManager.getType(defaultFeatureType.getId());
1236
                                if (auxFeatureType!=null) {
1237
                                        return auxFeatureType;
1238
                                }
1239
                        }
1240
                        FeatureType type = this.transforms.getDefaultFeatureType();
1241
                        if (type != null) {
1242
                                return type;
1243
                        }
1244
                        return defaultFeatureType;
1245
                } catch (Exception e) {
1246
                        throw new GetFeatureTypeException(e, getName());
1247
                }
1248
        }
1249

    
1250
        public FeatureType getFeatureType(String featureTypeId)
1251
                        throws DataException {
1252
                if (featureTypeId == null) {
1253
                        return this.getDefaultFeatureType();
1254
                }
1255
                try {
1256
                        if (isEditing()) {
1257
                                FeatureType auxFeatureType = featureTypeManager
1258
                                                .getType(featureTypeId);
1259
                                if (auxFeatureType != null) {
1260
                                        return auxFeatureType;
1261
                                }
1262
                        }
1263
                        FeatureType type = this.transforms.getFeatureType(featureTypeId);
1264
                        if (type != null) {
1265
                                return type;
1266
                        }
1267
                        Iterator iter = this.featureTypes.iterator();
1268
                        while (iter.hasNext()){
1269
                                type = (FeatureType) iter.next();
1270
                                if (type.getId().equals(featureTypeId)) {
1271
                                        return type;
1272
                                }
1273
                        }
1274
                        return null;
1275
                } catch (Exception e) {
1276
                        throw new GetFeatureTypeException(e, getName());
1277
                }
1278
        }
1279

    
1280

    
1281
        public FeatureType getProviderDefaultFeatureType() {
1282
                return defaultFeatureType;
1283
        }
1284

    
1285
        public List getFeatureTypes() throws DataException {
1286
                try {
1287
                        List types;
1288
                        if (isEditing()) {
1289
                                types=new ArrayList();
1290
                                Iterator it=featureTypes.iterator();
1291
                                while (it.hasNext()) {
1292
                                        FeatureType type = (FeatureType) it.next();
1293
                                        FeatureType typeaux = featureTypeManager.getType(type.getId());
1294
                                        if (typeaux!=null) {
1295
                                                types.add(typeaux);
1296
                                        }else{
1297
                                                types.add(type);
1298
                                        }
1299
                                }
1300
                                it = featureTypeManager.newsIterator();
1301
                                while (it.hasNext()) {
1302
                                        FeatureType type = (FeatureType) it.next();
1303
                                        types.add(type);
1304
                                }
1305
                        } else {
1306
                                types = this.transforms.getFeatureTypes();
1307
                                if (types == null) {
1308
                                        types = featureTypes;
1309
                                }
1310
                        }
1311
                        return Collections.unmodifiableList(types);
1312
                } catch (Exception e) {
1313
                        throw new GetFeatureTypeException(e, getName());
1314
                }
1315
        }
1316

    
1317
        public List getProviderFeatureTypes() throws DataException {
1318
                return Collections.unmodifiableList(this.featureTypes);
1319
        }
1320

    
1321
        public Feature createFeature(FeatureData data)
1322
        throws DataException {
1323
                DefaultFeature feature = new DefaultFeature(this, data);
1324
                return feature;
1325
        }
1326

    
1327
        public Feature createFeature(FeatureData data, FeatureType type)
1328
        throws DataException {
1329
                // FIXME: falta por implementar
1330
                // Comprobar si es un subtipo del feature de data
1331
                // y construir un feature usando el subtipo.
1332
                // Probablemente requiera generar una copia del data.
1333
                throw new NotYetImplemented();
1334
        }
1335

    
1336
        public EditableFeature createNewFeature(FeatureType type,
1337
                        Feature defaultValues)
1338
        throws DataException {
1339
                try {
1340
                        FeatureData data = createNewFeatureData(type);
1341
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1342
                        feature.initializeValues(defaultValues);
1343
                        return feature;
1344
                } catch (Exception e) {
1345
                        throw new CreateFeatureException(e, getName());
1346
                }
1347
        }
1348

    
1349
        private FeatureData createNewFeatureData(FeatureType type)
1350
                        throws DataException {
1351
                type = this.fixFeatureType((DefaultFeatureType) type);
1352
                FeatureData data = this.provider.createFeatureData(type);
1353
                data.setNew(true);
1354
                if (type.hasOID() && data.getOID() == null) {
1355
                        data.setOID(this.provider.createNewOID());
1356
                } else {
1357
                        data.setOID(this.getTemporalOID());
1358
                }
1359
                return data;
1360

    
1361
        }
1362

    
1363
        public EditableFeature createNewFeature(FeatureType type,
1364
                        boolean defaultValues)
1365
        throws DataException {
1366
                try {
1367
                        FeatureData data = createNewFeatureData(type);
1368
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1369
                        if (defaultValues) {
1370
                                feature.initializeValues();
1371
                        }
1372
                        return feature;
1373
                } catch (Exception e) {
1374
                        throw new CreateFeatureException(e, getName());
1375
                }
1376
        }
1377

    
1378
        public EditableFeature createNewFeature(boolean defaultValues)
1379
        throws DataException {
1380
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1381
        }
1382

    
1383
        public EditableFeature createNewFeature() throws DataException {
1384
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1385
        }
1386

    
1387
        public EditableFeatureType createFeatureType() {
1388
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1389
                ftype.setAllowAutomaticValues(this.provider.allowAutomaticValues());
1390
                return ftype;
1391
        }
1392

    
1393
        public EditableFeatureType createFeatureType(String id) {
1394
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1395
                ftype.setAllowAutomaticValues(this.provider.allowAutomaticValues());
1396
                return ftype;
1397
        }
1398

    
1399

    
1400
        //
1401
        // ====================================================================
1402
        // Index related methods
1403
        //
1404

    
1405
        public FeatureIndexes getIndexes() {
1406
                return this.indexes;
1407
        }
1408

    
1409
        public FeatureIndex createIndex(FeatureType featureType,
1410
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1411
                checkNotInAppendMode();
1412
                FeatureIndexProviderServices index = null;
1413
                index = dataManager.createFeatureIndexProvider(null, this, featureType,
1414
                indexName, featureType.getAttributeDescriptor(attributeName));
1415
                try {
1416
                        index.fill();
1417
                } catch (FeatureIndexException e) {
1418
                        throw new InitializeException(index.getName(), e);
1419
                }
1420
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1421
                return index;
1422
        }
1423

    
1424
        public FeatureIndex createIndex(FeatureType featureType,
1425
                        String attributeName, String indexName, Observer observer) {
1426
                // TODO Implement observer interaction
1427
                throw new UnsupportedOperationException();
1428
        }
1429

    
1430
        //
1431
        // ====================================================================
1432
        // Transforms related methods
1433
        //
1434

    
1435
        public FeatureStoreTransforms getTransforms() {
1436
                return this.transforms;
1437
        }
1438

    
1439
        public FeatureQuery createFeatureQuery() {
1440
                return new DefaultFeatureQuery();
1441
        }
1442

    
1443
        public DataQuery createQuery() {
1444
                return createFeatureQuery();
1445
        }
1446

    
1447
        //
1448
        // ====================================================================
1449
        // UndoRedo related methods
1450
        //
1451

    
1452
        public boolean canRedo() {
1453
                return commands.canRedo();
1454
        }
1455

    
1456
        public boolean canUndo() {
1457
                return commands.canUndo();
1458
        }
1459

    
1460
        public void redo(int num) throws RedoException {
1461
                commands.redo(num);
1462
        }
1463

    
1464
        public void undo(int num) throws UndoException {
1465
                commands.undo(num);
1466
        }
1467

    
1468
        //
1469
        // ====================================================================
1470
        // Metadata related methods
1471
        //
1472

    
1473
        public Object getMetadataID() {
1474
                return this.provider.getSourceId();
1475
        }
1476

    
1477
        public void delegate(DynObject dynObject) {
1478
                this.dynObject.delegate(dynObject);
1479
        }
1480

    
1481
        public DynClass getDynClass() {
1482
                return this.dynObject.getDynClass();
1483
        }
1484

    
1485
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1486
                return this.dynObject.getDynValue(name);
1487
        }
1488

    
1489
        public boolean hasDynValue(String name) {
1490
                return this.dynObject.hasDynValue(name);
1491
        }
1492

    
1493
        public void implement(DynClass dynClass) {
1494
                this.dynObject.implement(dynClass);
1495
        }
1496

    
1497
        public Object invokeDynMethod(String name, DynObject context)
1498
        throws DynMethodException {
1499
                return this.dynObject.invokeDynMethod(this, name, context);
1500
        }
1501

    
1502
        public Object invokeDynMethod(int code, DynObject context)
1503
        throws DynMethodException {
1504
                return this.dynObject.invokeDynMethod(this, code, context);
1505
        }
1506

    
1507
        public void setDynValue(String name, Object value)
1508
        throws DynFieldNotFoundException {
1509
                this.setDynValue(name, value);
1510

    
1511
        }
1512

    
1513
        /*
1514
         * (non-Javadoc)
1515
         *
1516
         * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1517
         */
1518
        public Set getMetadataChildren() {
1519
                return null;
1520
        }
1521

    
1522
        /*
1523
         * (non-Javadoc)
1524
         *
1525
         * @see org.gvsig.metadata.Metadata#getMetadataName()
1526
         */
1527
        public String getMetadataName() {
1528
                return this.provider.getName();
1529
        }
1530

    
1531
        public FeatureTypeManager getFeatureTypeManager() {
1532
                return this.featureTypeManager;
1533
        }
1534

    
1535
        public long getFeatureCount() throws DataException {
1536
                if (featureCount == null) {
1537
                        featureCount = new Long(this.provider.getFeatureCount());
1538
                }
1539
                if (this.isEditing() && !this.isAppending()) {
1540
                        return featureCount.longValue()
1541
                                        - this.featureManager.getDeltaSize();
1542
                }
1543
                return featureCount.longValue();
1544
        }
1545

    
1546
        private Long getTemporalOID() {
1547
                return new Long(this.temporalOid++);
1548
        }
1549

    
1550
        public FeatureType getProviderFeatureType(String featureTypeId) {
1551
                if (featureTypeId == null) {
1552
                        return this.defaultFeatureType;
1553
                }
1554
                FeatureType type;
1555
                Iterator iter = this.featureTypes.iterator();
1556
                while (iter.hasNext()) {
1557
                        type = (FeatureType) iter.next();
1558
                        if (type.getId().equals(featureTypeId)) {
1559
                                return type;
1560
                        }
1561
                }
1562
                return null;
1563
        }
1564

    
1565

    
1566
}