Statistics
| Revision:

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

History | View | Annotate | Download (44.1 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.DefaultFeatureProvider;
69
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
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.DataStoreImplementation;
75
import org.gvsig.fmap.dal.impl.DefaultDataManager;
76
import org.gvsig.fmap.dal.resource.Resource;
77
import org.gvsig.fmap.dal.spi.DataStoreProvider;
78
import org.gvsig.fmap.geom.primitive.Envelope;
79
import org.gvsig.tools.ToolsLocator;
80
import org.gvsig.tools.dynobject.DelegatedDynObject;
81
import org.gvsig.tools.dynobject.DynClass;
82
import org.gvsig.tools.dynobject.DynObject;
83
import org.gvsig.tools.dynobject.DynObjectManager;
84
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
85
import org.gvsig.tools.dynobject.exception.DynMethodException;
86
import org.gvsig.tools.exception.NotYetImplemented;
87
import org.gvsig.tools.observer.Observable;
88
import org.gvsig.tools.observer.Observer;
89
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
90
import org.gvsig.tools.persistence.PersistenceException;
91
import org.gvsig.tools.persistence.PersistenceValueNotFoundException;
92
import org.gvsig.tools.persistence.PersistentState;
93
import org.gvsig.tools.task.Executor;
94
import org.gvsig.tools.undo.RedoException;
95
import org.gvsig.tools.undo.UndoException;
96
import org.gvsig.tools.undo.command.Command;
97
import org.slf4j.Logger;
98
import org.slf4j.LoggerFactory;
99

    
100
final public class DefaultFeatureStore implements DataStoreImplementation,
101
                FeatureStoreProviderServices, FeatureStore, Observer {
102

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

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

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

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

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

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

    
125
        private DefaultDataManager dataManager = null;
126

    
127
        private FeatureStoreProvider provider = null;
128

    
129
        private DefaultFeatureIndexes indexes;
130

    
131
        private DefaultFeatureStoreTransforms transforms;
132

    
133
        private DelegatedDynObject metadata;
134

    
135
        private Long featureCount = null;
136

    
137
        private long temporalOid = 0;
138

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

    
148
        public DefaultFeatureStore() {
149

    
150
        }
151

    
152
        public void intializePhase1(DefaultDataManager dataManager,
153
                        DataStoreParameters parameters) throws InitializeException {
154

    
155
                DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
156

    
157
                this.metadata = (DelegatedDynObject) dynManager
158
                                .createDynObject(dynManager.get(DataStore.DYNCLASS_NAME));
159
                this.dataManager = dataManager;
160

    
161
                this.parameters = parameters;
162
                this.transforms = new DefaultFeatureStoreTransforms(this);
163
                try {
164
                        indexes = new DefaultFeatureIndexes(this);
165
                } catch (DataException e) {
166
                        throw new InitializeException(e);
167
                }
168

    
169
        }
170

    
171
        public void intializePhase2(DataStoreProvider provider) {
172
                this.provider = (FeatureStoreProvider) provider;
173
                this.delegate(provider);
174
        }
175

    
176
        public String getName() {
177
                return this.parameters.getDataStoreName();
178
        }
179

    
180
        public DataStoreParameters getParameters() {
181
                return parameters;
182
        }
183

    
184
        public int getMode() {
185
                return this.mode;
186
        }
187

    
188
        public DataManager getManager() {
189
                return this.dataManager;
190
        }
191

    
192
        public Iterator getChildren() {
193
                return this.provider.getChilds();
194
        }
195

    
196
        public FeatureStoreProvider getProvider() {
197
                return this.provider;
198
        }
199

    
200
        public FeatureManager getFeatureManager() {
201
                return this.featureManager;
202
        }
203

    
204
        public void setFeatureTypes(List types, FeatureType defaultType) {
205
                this.featureTypes = types;
206
                this.defaultFeatureType = defaultType;
207
        }
208

    
209
        public void open() throws OpenException {
210
                // TODO: Se puede hacer un open estando en edicion ?
211
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
212
                this.provider.open();
213
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
214
        }
215

    
216
        public void refresh() throws OpenException, InitializeException {
217
                if (this.mode != MODE_QUERY) {
218
                        throw new IllegalStateException();
219
                }
220
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
221
                this.featureCount = null;
222
                this.provider.refresh();
223
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
224
        }
225

    
226
        public void close() throws CloseException {
227
                // TODO: Se puede hacer un close estando en edicion ?
228
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
229
                this.featureCount = null;
230
                this.provider.close();
231
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
232
        }
233

    
234
        public void dispose() throws CloseException {
235
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
236
                this.provider.dispose();
237
                if (this.selection != null) {
238
                        this.selection.dispose();
239
                        this.selection = null;
240
                }
241
                this.commands = null;
242
                this.featureCount = null;
243
                if (this.locks != null) {
244
                        //this.locks.dispose();
245
                        this.locks = null;
246
                }
247

    
248
                if (this.featureTypeManager != null) {
249
                        this.featureTypeManager.dispose();
250
                        this.featureTypeManager = null;
251
                }
252

    
253
                this.featureManager = null;
254
                this.spatialManager = null;
255

    
256
                this.parameters = null;
257
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
258
                this.delegateObservable.deleteObservers();
259
                this.delegateObservable = null;
260
        }
261

    
262
        public boolean allowWrite() {
263
                return this.provider.allowWrite();
264
        }
265

    
266
        public boolean canWriteGeometry(int geometryType) throws DataException {
267
                return this.provider.canWriteGeometry(geometryType, 0);
268
        }
269

    
270
        public DataServerExplorer getExplorer() throws ReadException,
271
                        ValidateDataParametersException {
272
                return this.provider.getExplorer();
273
        }
274

    
275
        /*
276
        public Metadata getMetadata() throws MetadataNotFoundException {
277
                // TODO:
278
                // Si el provider devuelbe null habria que ver de construir aqui
279
                // los metadatos basicos, como el Envelope y el SRS.
280

281
                // TODO: Estando en edicion el Envelope deberia de
282
                // actualizarse usando el spatialManager
283
                return this.provider.getMetadata();
284
        }
285
         */
286

    
287
        public Envelope getEnvelope() throws DataException {
288
                if (this.mode == MODE_FULLEDIT) {
289
                        return this.spatialManager.getEnvelope();
290
                }
291
                return this.provider.getEnvelope();
292
        }
293

    
294
        /**
295
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
296
         */
297
        public IProjection getSRSDefaultGeometry() throws DataException {
298
                return this.getDefaultFeatureType().getDefaultSRS();
299
        }
300

    
301
        public FeatureSelection createDefaultFeatureSelection()
302
        throws DataException {
303
                return new DefaultFeatureSelection(this);
304
        }
305

    
306
        public FeatureProvider createDefaultFeatureProvider(FeatureType type)
307
        throws DataException {
308
                if( type.hasOID() ) {
309
                        return new DefaultFeatureProvider(type, this.provider.createNewOID());
310
                }
311
                return new DefaultFeatureProvider(type);
312
        }
313

    
314
        public void saveToState(PersistentState state) throws PersistenceException {
315
                state.set("dataStoreName", this.getName());
316
                state.set("parameters", this.parameters);
317
                state.set("provider", this.provider);
318
                if (this.selection != null) {
319
                        state.set("selection", this.selection);
320
                }
321
        }
322

    
323
        public void loadFromState(PersistentState state) throws PersistenceException {
324
                if (this.provider != null) {
325
                        throw new PersistenceException("Provider not set");
326
                }
327
                if (this.getManager() == null) {
328
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
329
                }
330

    
331
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
332

    
333
                try {
334

    
335
                        this.dataManager.intializeDataStore(this, params);
336
                        try {
337
                                setSelection((FeatureSelection) state.get("selection"));
338
                        } catch (PersistenceValueNotFoundException e) {
339
                                setSelection(null);
340
                        }
341

    
342
                } catch (InitializeException e) {
343
                        throw new PersistenceException(e);
344
                } catch (DataException e) {
345
                        throw new PersistenceException(e);
346
                }
347

    
348
        }
349

    
350
        //
351
        // ====================================================================
352
        // Gestion de la seleccion
353
        //
354

    
355
        public void setSelection(DataSet selection)
356
        throws DataException {
357
                this.setSelection((FeatureSet) selection);
358
        }
359

    
360
        public DataSet createSelection() throws DataException {
361
                return createFeatureSelection();
362
        }
363

    
364
        public DataSet getSelection() throws DataException {
365
                return this.getFeatureSelection();
366
        }
367

    
368
    public void setSelection(FeatureSet selection) throws DataException {
369
        setSelection(selection, true);
370
    }
371

    
372
    /**
373
     * @see #setSelection(FeatureSet)
374
     * @param undoable
375
     *            if the action must be undoable
376
     */
377
    public void setSelection(FeatureSet selection, boolean undoable)
378
        throws DataException {
379
                if (selection.equals(this.selection)) {
380
                        return;
381
                }
382
                if (!selection.isFromStore(this)) {
383
                        throw new SelectionNotAllowedException(getName());
384
                }
385

    
386
                this.selection.deleteObserver(this);
387
                if (selection instanceof FeatureSelection) {
388
                        if (undoable && isEditing()) {
389
                                commands.selectionSet(this, this.selection,
390
                                                (FeatureSelection) selection);
391
                        }
392
                        this.selection = (FeatureSelection) selection;
393
                } else {
394
                        if (undoable && isEditing()) {
395
                                commands.startComplex("_selectionSet");
396
                        }
397
                        if (selection instanceof DefaultFeatureSelection) {
398
                DefaultFeatureSelection defSelection = (DefaultFeatureSelection) selection;
399
                defSelection.deselectAll(undoable);
400
                defSelection.select(selection, undoable);
401
            } else {
402
                this.selection.deselectAll();
403
                this.selection.select(selection);
404
            }
405
                        if (undoable && isEditing()) {
406
                                commands.endComplex();
407
                        }
408
                }
409
                this.selection.addObserver(this);
410

    
411
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
412
        }
413

    
414
        public FeatureSelection createFeatureSelection() throws DataException {
415
                return this.provider.createFeatureSelection();
416
        }
417

    
418
        public FeatureSelection getFeatureSelection() throws DataException {
419
                if (selection == null) {
420
                        this.selection = createFeatureSelection();
421
                        this.selection.addObserver(this);
422
                }
423
                return selection;
424
        }
425

    
426
        //
427
        // ====================================================================
428
        // Gestion de notificaciones
429
        //
430

    
431
        public void notifyChange(String notification) {
432
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
433
                                notification));
434

    
435
        }
436

    
437
        public void notifyChange(String notification, Feature feature) {
438
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
439
                                this, notification, feature));
440
        }
441

    
442
        public void notifyChange(String notification, Command command) {
443
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
444
                                this, notification, command));
445
        }
446

    
447
        public void notifyChange(String notification, EditableFeatureType type) {
448
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
449
                                notification, type));
450
        }
451

    
452
        /*
453
         * (non-Javadoc)
454
         *
455
         * @see
456
         * org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices#notifyChange
457
         * (java.lang.String, org.gvsig.fmap.dal.resource.Resource)
458
         */
459
        public void notifyChange(String notification, Resource resource) {
460
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
461
                                FeatureStoreNotification.RESOURCE_CHANGED));
462
        }
463

    
464

    
465
        //
466
        // ====================================================================
467
        // Gestion de bloqueos
468
        //
469

    
470
        public boolean isLocksSupported() {
471
                return this.provider.isLocksSupported();
472
        }
473

    
474
        public FeatureLocks getLocks() throws DataException {
475
                if (!this.provider.isLocksSupported()) {
476
                        logger.warn("Locks not supporteds");
477
                        return null;
478
                }
479
                if (locks == null) {
480
                        this.locks = this.provider.createFeatureLocks();
481
                }
482
                return locks;
483
        }
484

    
485
        //
486
        // ====================================================================
487
        // Interface Observable
488
        //
489

    
490
        public void disableNotifications() {
491
                this.delegateObservable.disableNotifications();
492

    
493
        }
494

    
495
        public void enableNotifications() {
496
                this.delegateObservable.enableNotifications();
497
        }
498

    
499
        public void beginComplexNotification() {
500
                this.delegateObservable.beginComplexNotification();
501

    
502
        }
503

    
504
        public void endComplexNotification() {
505
                this.delegateObservable.endComplexNotification();
506

    
507
        }
508

    
509
        public void addObserver(Observer observer) {
510
                this.delegateObservable.addObserver(observer);
511

    
512
        }
513

    
514
        public void deleteObserver(Observer observer) {
515
                this.delegateObservable.deleteObserver(observer);
516
        }
517

    
518
        public void deleteObservers() {
519
                this.delegateObservable.deleteObservers();
520

    
521
        }
522

    
523
        //
524
        // ====================================================================
525
        // Interface Observer
526
        //
527
        // Usado para observar:
528
        // - su seleccion
529
        // - sus bloqueos
530
        // - sus recursos
531
        //
532

    
533
        public void update(Observable observable, Object notification) {
534
                if (observable instanceof FeatureSet) {
535
                        if (observable == this.selection) {
536
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
537
                        } else if (observable == this.locks) {
538
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
539
                        }
540

    
541
                } else if (observable instanceof FeatureStoreProvider) {
542
                        if (observable == this.provider) {
543

    
544
                        }
545

    
546
                }
547
        }
548

    
549
        //
550
        // ====================================================================
551
        // Edicion
552
        //
553

    
554
        private void newVersionOfUpdate() {
555
                this.versionOfUpdate++;
556
        }
557

    
558
        private long currentVersionOfUpdate() {
559
                return this.versionOfUpdate;
560
        }
561

    
562
        private void checkInEditingMode()
563
        throws NeedEditingModeException {
564
                if (mode != MODE_FULLEDIT) {
565
                        throw new NeedEditingModeException(this.getName());
566
                }
567
        }
568

    
569
        private void checkNotInAppendMode() throws IllegalStateException {
570
                if (mode == MODE_APPEND) {
571
                        throw new IllegalStateException(this.getName());
572
                }
573
        }
574

    
575
        private void checkIsOwnFeature(Feature feature)
576
        throws IllegalFeatureException {
577
                if (((DefaultFeature) feature).getStore() != this) {
578
                        throw new IllegalFeatureException(this.getName());
579
                }
580
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
581
                // fixFeatureType((DefaultFeatureType) feature.getType());
582
        }
583

    
584
        private void exitEditingMode() {
585
                if (commands != null) {
586
                        commands.clear();
587
                        commands = null;
588
                }
589

    
590
                if (featureTypeManager != null) {
591
                        featureTypeManager.dispose();
592
                        featureTypeManager = null;
593

    
594
                }
595

    
596
                // TODO implementar un dispose para estos dos
597
                featureManager = null;
598
                spatialManager = null;
599

    
600
                featureCount = null;
601

    
602
                mode = MODE_QUERY;
603
                hasStrongChanges = true; // Lo deja a true por si las moscas
604
                hasInserts = true;
605
        }
606

    
607
        synchronized public void edit() throws DataException {
608
                edit(MODE_FULLEDIT);
609
        }
610

    
611
        synchronized public void edit(int mode) throws DataException {
612
                try {
613
                        if ( this.mode != MODE_QUERY ) {
614
                                throw new AlreadyEditingException(this.getName());
615
                        }
616
                        if (!this.provider.supportsAppendMode()) {
617
                                mode = MODE_FULLEDIT;
618
                        }
619
                        switch (mode) {
620
                        case MODE_QUERY:
621
                                throw new IllegalStateException(this.getName());
622

    
623
                        case MODE_FULLEDIT:
624
                                if (!this.transforms.isEmpty()) {
625
                                        throw new IllegalStateException(this.getName());
626
                                }
627
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
628
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
629
                                featureTypeManager = new FeatureTypeManager(this,
630
                                                new MemoryExpansionAdapter());
631
                                spatialManager = new SpatialManager(this, provider
632
                                                .getEnvelope());
633

    
634
                                commands = new DefaultFeatureCommandsStack(featureManager,
635
                                                spatialManager, featureTypeManager);
636
                                this.mode = MODE_FULLEDIT;
637
                                hasStrongChanges = false;
638
                                hasInserts = false;
639
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
640
                                break;
641
                        case MODE_APPEND:
642
                                if (!this.transforms.isEmpty()) {
643
                                        throw new IllegalStateException(this.getName());
644
                                }
645
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
646
                                this.provider.beginAppend();
647
                                this.mode = MODE_APPEND;
648
                                hasInserts = false;
649
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
650
                                break;
651
                        }
652
                } catch (Exception e) {
653
                        throw new StoreEditException(e, this.getName());
654
                }
655
        }
656

    
657
        public boolean isEditing() {
658
                return mode == MODE_FULLEDIT;
659
        }
660

    
661
        public boolean isAppending() {
662
                return mode == MODE_APPEND;
663
        }
664

    
665
        synchronized public void update(EditableFeatureType type)
666
        throws DataException {
667
                try {
668
                        checkInEditingMode();
669
                        if (type == null) {
670
                                throw new NullFeatureTypeException(getName());
671
                        }
672
                        // FIXME: Comprobar que es un featureType aceptable.
673
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
674
                        newVersionOfUpdate();
675

    
676
                        FeatureType oldt = type.getSource().getCopy();
677
                        FeatureType newt = type.getNotEditableCopy();
678
                        commands.update(newt, oldt);
679

    
680
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
681
                                hasStrongChanges = true;
682
                        }
683
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
684
                } catch (Exception e) {
685
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
686
                }
687
        }
688

    
689
        synchronized public void delete(Feature feature) throws DataException {
690
                try {
691
                        checkInEditingMode();
692
                        checkIsOwnFeature(feature);
693
                        if (feature instanceof EditableFeature) {
694
                                throw new StoreDeleteEditableFeatureException(getName());
695
                        }
696
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
697
                        this.commands.delete(feature);
698
                        newVersionOfUpdate();
699
                        hasStrongChanges = true;
700
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
701
                } catch (Exception e) {
702
                        throw new StoreDeleteFeatureException(e, this.getName());
703
                }
704
        }
705

    
706
        private static EditableFeature lastChangedFeature = null;
707

    
708
        synchronized public void insert(EditableFeature feature)
709
        throws DataException {
710
                try {
711
                        switch (mode) {
712
                        case MODE_QUERY:
713
                                throw new NeedEditingModeException(this.getName());
714

    
715
                        case MODE_APPEND:
716
                                checkIsOwnFeature(feature);
717
                                if (feature.getSource() != null) {
718
                                        throw new NoNewFeatureInsertException(this.getName());
719
                                }
720
                                this.featureCount = null;
721
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
722
                                feature.validate(Feature.UPDATE);
723
                                provider.append(((DefaultEditableFeature) feature).getData());
724
                                hasStrongChanges = true;
725
                                hasInserts = true;
726
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
727
                                break;
728

    
729
                        case MODE_FULLEDIT:
730
                                checkIsOwnFeature(feature);
731
                                if (feature.getSource() != null) {
732
                                        throw new NoNewFeatureInsertException(this.getName());
733
                                }
734
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
735
                                newVersionOfUpdate();
736
                                if (lastChangedFeature ==null || lastChangedFeature.getSource() != feature.getSource()) {
737
                                        lastChangedFeature = feature;
738
                                        feature.validate(Feature.UPDATE);
739
                                        lastChangedFeature = null;
740
                                }
741
                                commands.insert(feature.getNotEditableCopy());
742
                                hasStrongChanges = true;
743
                                hasInserts = true;
744
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
745
                                break;
746
                        }
747
                } catch (Exception e) {
748
                        throw new StoreInsertFeatureException(e, this.getName());
749
                }
750
        }
751

    
752
        synchronized public void update(EditableFeature feature)
753
        throws DataException {
754
                try {
755
                        if ((feature).getSource() == null) {
756
                                insert(feature);
757
                                return;
758
                        }
759
                        checkInEditingMode();
760
                        checkIsOwnFeature(feature);
761
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
762
                        newVersionOfUpdate();
763
                        if (lastChangedFeature==null || lastChangedFeature.getSource() != feature.getSource()) {
764
                                lastChangedFeature = feature;
765
                                feature.validate(Feature.UPDATE);
766
                                lastChangedFeature = null;
767
                        }
768

    
769
                        Feature oldf = feature.getSource();
770
                        Feature newf = feature.getNotEditableCopy();
771
                        commands.update(newf, oldf);
772

    
773
                        hasStrongChanges = true;
774
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
775
                } catch (Exception e) {
776
                        throw new StoreUpdateFeatureException(e, this.getName());
777
                }
778
        }
779

    
780
        synchronized public void redo() throws RedoException {
781
                Command redo = commands.getNextRedoCommand();
782
                try {
783
                        checkInEditingMode();
784
                } catch (NeedEditingModeException ex) {
785
                        throw new RedoException(redo, ex);
786
                }
787
                notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
788
                newVersionOfUpdate();
789
                commands.redo();
790
                hasStrongChanges = true;
791
                notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
792
        }
793

    
794
        synchronized public void undo() throws UndoException {
795
                Command undo = commands.getNextUndoCommand();
796
                try {
797
                        checkInEditingMode();
798
                } catch (NeedEditingModeException ex) {
799
                        throw new UndoException(undo, ex);
800
                }
801
                notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
802
                newVersionOfUpdate();
803
                commands.undo();
804
                hasStrongChanges = true;
805
                notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
806
        }
807

    
808
        public List getRedoInfos() {
809
                if (isEditing() && commands != null) {
810
                        return commands.getRedoInfos();
811
                } else {
812
                        return null;
813
                }
814
        }
815

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

    
824
        public synchronized FeatureCommandsStack getCommandsStack()
825
        throws DataException {
826
                checkInEditingMode();
827
                return commands;
828
        }
829

    
830
        synchronized public void cancelEditing() throws DataException {
831
                spatialManager.cancelModifies();
832
                try {
833
                        checkInEditingMode();
834

    
835
                        boolean clearSelection = this.hasStrongChanges;
836
                        if (this.selection instanceof FeatureReferenceSelection) {
837
                                clearSelection = this.hasInserts;
838
                        }
839
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
840
                        exitEditingMode();
841
                        if (clearSelection) {
842
                                ((FeatureSelection) this.getSelection()).deselectAll();
843
                        }
844
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
845
                } catch (Exception e) {
846
                        throw new StoreCancelEditingException(e, this.getName());
847
                }
848
        }
849

    
850
        synchronized public void finishEditing() throws DataException {
851
                try {
852
                        switch (mode) {
853
                        case MODE_QUERY:
854
                                throw new NeedEditingModeException(this.getName());
855

    
856
                        case MODE_APPEND:
857
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
858
                                provider.endAppend();
859
                                exitEditingMode();
860
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
861
                                break;
862

    
863
                        case MODE_FULLEDIT:
864
                                if (!hasStrongChanges) {
865
                                        performLightEditing();
866
                                        return;
867
                                }
868
                                if (!this.allowWrite()) {
869
                                        throw new WriteNotAllowedException(getName());
870
                                }
871

    
872
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
873
                                validateFeatures(Feature.FINISH_EDITING);
874
                                provider.performChanges(featureManager.getDeleted(),
875
                                                featureManager.getInserted(),
876
                                                featureManager.getUpdated(),
877
                                                featureTypeManager.getFeatureTypesChanged());
878
                                exitEditingMode();
879
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
880
                                break;
881
                        }
882
                } catch (Exception e) {
883
                        throw new FinishEditingException(e);
884
                }
885
        }
886

    
887
        private void performLightEditing() throws DataException {
888
                throw new NotYetImplemented(
889
                "lightFinishEdition not yet implemented");
890

    
891
                // TODO: implementar
892
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
893
                // exitEditingMode();
894
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
895
        }
896

    
897

    
898
        public void beginEditingGroup(String description)
899
        throws NeedEditingModeException {
900
                checkInEditingMode();
901
                commands.startComplex(description);
902
        }
903

    
904
        public void endEditingGroup() throws NeedEditingModeException {
905
                checkInEditingMode();
906
                commands.endComplex();
907
        }
908

    
909
        public boolean isAppendModeSupported() {
910
                return this.provider.supportsAppendMode();
911
        }
912

    
913

    
914
        public void export(DataServerExplorer explorer, NewFeatureStoreParameters params)
915
        throws DataException {
916

    
917
                if (this.getFeatureTypes().size() != 1) {
918
                        throw new NotYetImplemented(
919
                        "export whith more than one type not yet implemented");
920
                }
921
                FeatureSelection featureSelection=(FeatureSelection)getSelection();
922
                try {
923
                        FeatureType type = this.getDefaultFeatureType();
924
                        if (params.getDefaultFeatureType() == null
925
                                        || params.getDefaultFeatureType().size() == 0) {
926
                                params.setDefaultFeatureType(type.getEditable());
927

    
928
                        }
929
                        explorer.add(params, true);
930

    
931
                        DataManager manager = DALLocator.getDataManager();
932
                        FeatureStore target = (FeatureStore) manager
933
                        .createStore(params);
934
                        FeatureType targetType = target.getDefaultFeatureType();
935

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

    
965
        //
966
        // ====================================================================
967
        // Obtencion de datos
968
        // getDataCollection, getFeatureCollection
969
        //
970

    
971
        public DataSet getDataSet() throws DataException {
972
                checkNotInAppendMode();
973
                FeatureQuery query = new DefaultFeatureQuery(this
974
                                .getDefaultFeatureType());
975
                return new DefaultFeatureSet(this, query);
976
        }
977

    
978
        public DataSet getDataSet(DataQuery dataQuery)
979
        throws DataException {
980
                checkNotInAppendMode();
981
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
982
        }
983

    
984
        public void getDataSet(Observer observer) throws DataException {
985
                checkNotInAppendMode();
986
                this.getFeatureSet(null, observer);
987
        }
988

    
989
        public void getDataSet(DataQuery dataQuery, Observer observer)
990
        throws DataException {
991
                checkNotInAppendMode();
992
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
993
        }
994

    
995
        public FeatureSet getFeatureSet() throws DataException {
996
                checkNotInAppendMode();
997
                FeatureQuery query = new DefaultFeatureQuery(this
998
                                .getDefaultFeatureType());
999
                return new DefaultFeatureSet(this, query);
1000
        }
1001

    
1002
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1003
        throws DataException {
1004
                checkNotInAppendMode();
1005
                return new DefaultFeatureSet(this, featureQuery);
1006
        }
1007

    
1008

    
1009
        public FeatureType getFeatureType(FeatureQuery featureQuery)
1010
                        throws DataException {
1011
                DefaultFeatureType fType = (DefaultFeatureType) this
1012
                                .getFeatureType(featureQuery.getFeatureTypeId());
1013
                if (featureQuery.getAttributeNames() != null){
1014
                        return fType.getSubtype(featureQuery.getAttributeNames());
1015
                }
1016
                return fType;
1017
        }
1018

    
1019
        public void getFeatureSet(Observer observer)
1020
        throws DataException {
1021
                checkNotInAppendMode();
1022
                this.getFeatureSet(null, observer);
1023
        }
1024

    
1025
        public void getFeatureSet(FeatureQuery query, Observer observer)
1026
        throws DataException {
1027
                class LoadInBackGround implements Runnable {
1028
                        private FeatureStore store;
1029
                        private FeatureQuery query;
1030
                        private Observer observer;
1031
                        private Executor executor;
1032
                        private FeatureStoreNotification notification;
1033

    
1034
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
1035
                                        Observer observer, Executor executor) {
1036
                                this.store = store;
1037
                                this.query = query;
1038
                                this.observer = observer;
1039
                                this.executor = executor;
1040
                        }
1041

    
1042
                        void notify(FeatureStoreNotification theNotification) {
1043
                                if (executor == null) {
1044
                                        observer.update(store, theNotification);
1045
                                        return;
1046
                                }
1047
                                this.notification = theNotification;
1048
                                executor.execute(new Runnable() {
1049
                                        public void run() {
1050
                                                observer.update(store, notification);
1051
                                        }
1052
                                });
1053

    
1054
                        }
1055

    
1056
                        public void run() {
1057
                                try {
1058
                                        FeatureSet set = store.getFeatureSet(query);
1059
                                        notify(new DefaultFeatureStoreNotification(store,
1060
                                                        FeatureStoreNotification.LOAD_FINISHED, set));
1061
                                } catch (Exception e) {
1062
                                        notify(new DefaultFeatureStoreNotification(store,
1063
                                                        FeatureStoreNotification.LOAD_FINISHED, e));
1064
                                }
1065
                        }
1066
                }
1067

    
1068
                checkNotInAppendMode();
1069
                if (query == null) {
1070
                        query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1071
                }
1072
                Executor executor = ToolsLocator.getTaskManager().getExecutor();
1073
                LoadInBackGround task = new LoadInBackGround(this, query, observer,
1074
                                executor);
1075
                Thread thread = new Thread(task);
1076
                thread.run();
1077
        }
1078

    
1079
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
1080
                checkNotInAppendMode();
1081
                DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1082
                FeatureType featureType;
1083
                if (ref.getFeatureTypeId() == null) {
1084
                        featureType = this.getDefaultFeatureType();
1085
                } else {
1086
                        featureType = this.getFeatureType(ref.getFeatureTypeId());
1087
                }
1088
                return this.getFeatureByReference(reference, featureType);
1089
        }
1090

    
1091
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
1092
        throws DataException {
1093
                checkNotInAppendMode();
1094
                featureType = fixFeatureType((DefaultFeatureType) featureType);
1095
                if (!this.transforms.isEmpty()) {
1096

    
1097
                        featureType = this.transforms
1098
                        .getSourceFeatureTypeFrom(featureType);
1099

    
1100
                }
1101
                // TODO comprobar que el id es de este store
1102

    
1103
                if (this.mode == MODE_FULLEDIT) {
1104
                        Feature f = featureManager.get(reference, this, featureType);
1105
                        if (f!=null) {
1106
                                return f;
1107
                        }
1108
                }
1109
                DefaultFeature feature = new DefaultFeature(
1110
                                this,
1111
                                this.provider
1112
                                .getFeatureProviderByReference(
1113
                                                (FeatureReferenceProviderServices) reference,
1114
                                                featureType));
1115

    
1116
                if (!this.transforms.isEmpty()) {
1117
                        return this.transforms.applyTransform(feature, featureType);
1118
                }
1119
                return feature;
1120
        }
1121

    
1122
        //
1123
        // ====================================================================
1124
        // Gestion de features
1125
        //
1126

    
1127
        private FeatureType fixFeatureType(DefaultFeatureType type)
1128
        throws DataException {
1129
                FeatureType original = this.getDefaultFeatureType();
1130

    
1131
                if (type == null || type.equals(original)) {
1132
                        return original;
1133
                } else {
1134
                        if (!type.isSubtypeOf(original)) {
1135
                                Iterator iter = this.getFeatureTypes().iterator();
1136
                                FeatureType tmpType;
1137
                                boolean found = false;
1138
                                while (iter.hasNext()) {
1139
                                        tmpType = (FeatureType) iter.next();
1140
                                        if (type.equals(tmpType)) {
1141
                                                return type;
1142

    
1143
                                        }else if (type.isSubtypeOf(tmpType)) {
1144
                                                found = true;
1145
                                                original = tmpType;
1146
                                                break;
1147
                                        }
1148

    
1149
                                }
1150
                                if (!found) {
1151
                                        throw new IllegalFeatureTypeException(getName());
1152
                                }
1153
                        }
1154
                }
1155

    
1156
                // Checks that type has all fields of pk
1157
                // else add the missing attributes at the end.
1158
                if (!original.hasOID()) {
1159
                        // Gets original pk attributes
1160
                        DefaultEditableFeatureType edOriginal = (DefaultEditableFeatureType) original
1161
                                        .getEditable();
1162
                        FeatureAttributeDescriptor orgAttr;
1163
                        Iterator edOriginalIter = edOriginal.iterator();
1164
                        while (edOriginalIter.hasNext()) {
1165
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1166
                                if (!orgAttr.isPrimaryKey()) {
1167
                                        edOriginalIter.remove();
1168
                                }
1169
                        }
1170

    
1171
                        // Checks if all pk attributes are in type
1172
                        Iterator typeIterator;
1173
                        edOriginalIter = edOriginal.iterator();
1174
                        FeatureAttributeDescriptor attr;
1175
                        while (edOriginalIter.hasNext()) {
1176
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1177
                                typeIterator = type.iterator();
1178
                                while (typeIterator.hasNext()) {
1179
                                        attr = (FeatureAttributeDescriptor) typeIterator.next();
1180
                                        if (attr.getName().equals(orgAttr.getName())) {
1181
                                                edOriginalIter.remove();
1182
                                                break;
1183
                                        }
1184
                                }
1185
                        }
1186

    
1187
                        // add missing pk attributes if any
1188
                        if (edOriginal.size() > 0) {
1189
                                boolean isEditable = type instanceof DefaultEditableFeatureType;
1190
                                DefaultEditableFeatureType edType = (DefaultEditableFeatureType) original
1191
                                                .getEditable();
1192
                                edType.clear();
1193
                                edType.addAll(type);
1194
                                edType.addAll(edOriginal);
1195
                                if (!isEditable) {
1196
                                        type = (DefaultFeatureType) edType.getNotEditableCopy();
1197
                                }
1198
                        }
1199

    
1200
                }
1201

    
1202

    
1203
                return type;
1204
        }
1205

    
1206
        public void validateFeatures(int mode) throws DataException {
1207
                try {
1208
                        checkNotInAppendMode();
1209
                        FeatureSet collection = this.getFeatureSet();
1210
                        Iterator iter = collection.iterator();
1211
                        long previousVersionOfUpdate = currentVersionOfUpdate();
1212
                        while (iter.hasNext()) {
1213
                                ((DefaultFeature) iter.next()).validate(mode);
1214
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1215
                                        throw new ConcurrentDataModificationException(getName());
1216
                                }
1217
                        }
1218
                } catch (Exception e) {
1219
                        throw new ValidateFeaturesException(e, getName());
1220
                }
1221
        }
1222

    
1223
        public FeatureType getDefaultFeatureType() throws DataException {
1224
                try {
1225
                        if (isEditing()) {
1226
                                FeatureType auxFeatureType=featureTypeManager.getType(defaultFeatureType.getId());
1227
                                if (auxFeatureType!=null) {
1228
                                        return auxFeatureType;
1229
                                }
1230
                        }
1231
                        FeatureType type = this.transforms.getDefaultFeatureType();
1232
                        if (type != null) {
1233
                                return type;
1234
                        }
1235
                        return defaultFeatureType;
1236
                } catch (Exception e) {
1237
                        throw new GetFeatureTypeException(e, getName());
1238
                }
1239
        }
1240

    
1241
        public FeatureType getFeatureType(String featureTypeId)
1242
                        throws DataException {
1243
                if (featureTypeId == null) {
1244
                        return this.getDefaultFeatureType();
1245
                }
1246
                try {
1247
                        if (isEditing()) {
1248
                                FeatureType auxFeatureType = featureTypeManager
1249
                                                .getType(featureTypeId);
1250
                                if (auxFeatureType != null) {
1251
                                        return auxFeatureType;
1252
                                }
1253
                        }
1254
                        FeatureType type = this.transforms.getFeatureType(featureTypeId);
1255
                        if (type != null) {
1256
                                return type;
1257
                        }
1258
                        Iterator iter = this.featureTypes.iterator();
1259
                        while (iter.hasNext()){
1260
                                type = (FeatureType) iter.next();
1261
                                if (type.getId().equals(featureTypeId)) {
1262
                                        return type;
1263
                                }
1264
                        }
1265
                        return null;
1266
                } catch (Exception e) {
1267
                        throw new GetFeatureTypeException(e, getName());
1268
                }
1269
        }
1270

    
1271

    
1272
        public FeatureType getProviderDefaultFeatureType() {
1273
                return defaultFeatureType;
1274
        }
1275

    
1276
        public List getFeatureTypes() throws DataException {
1277
                try {
1278
                        List types;
1279
                        if (isEditing()) {
1280
                                types=new ArrayList();
1281
                                Iterator it=featureTypes.iterator();
1282
                                while (it.hasNext()) {
1283
                                        FeatureType type = (FeatureType) it.next();
1284
                                        FeatureType typeaux = featureTypeManager.getType(type.getId());
1285
                                        if (typeaux!=null) {
1286
                                                types.add(typeaux);
1287
                                        }else{
1288
                                                types.add(type);
1289
                                        }
1290
                                }
1291
                                it = featureTypeManager.newsIterator();
1292
                                while (it.hasNext()) {
1293
                                        FeatureType type = (FeatureType) it.next();
1294
                                        types.add(type);
1295
                                }
1296
                        } else {
1297
                                types = this.transforms.getFeatureTypes();
1298
                                if (types == null) {
1299
                                        types = featureTypes;
1300
                                }
1301
                        }
1302
                        return Collections.unmodifiableList(types);
1303
                } catch (Exception e) {
1304
                        throw new GetFeatureTypeException(e, getName());
1305
                }
1306
        }
1307

    
1308
        public List getProviderFeatureTypes() throws DataException {
1309
                return Collections.unmodifiableList(this.featureTypes);
1310
        }
1311

    
1312
        public Feature createFeature(FeatureProvider data)
1313
        throws DataException {
1314
                DefaultFeature feature = new DefaultFeature(this, data);
1315
                return feature;
1316
        }
1317

    
1318
        public Feature createFeature(FeatureProvider data, FeatureType type)
1319
        throws DataException {
1320
                // FIXME: falta por implementar
1321
                // Comprobar si es un subtipo del feature de data
1322
                // y construir un feature usando el subtipo.
1323
                // Probablemente requiera generar una copia del data.
1324
                throw new NotYetImplemented();
1325
        }
1326

    
1327
        public EditableFeature createNewFeature(FeatureType type,
1328
                        Feature defaultValues)
1329
        throws DataException {
1330
                try {
1331
                        FeatureProvider data = createNewFeatureProvider(type);
1332
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1333
                        feature.initializeValues(defaultValues);
1334
                        return feature;
1335
                } catch (Exception e) {
1336
                        throw new CreateFeatureException(e, getName());
1337
                }
1338
        }
1339

    
1340
        private FeatureProvider createNewFeatureProvider(FeatureType type)
1341
                        throws DataException {
1342
                type = this.fixFeatureType((DefaultFeatureType) type);
1343
                FeatureProvider data = this.provider.createFeatureProvider(type);
1344
                data.setNew(true);
1345
                if (type.hasOID() && data.getOID() == null) {
1346
                        data.setOID(this.provider.createNewOID());
1347
                } else {
1348
                        data.setOID(this.getTemporalOID());
1349
                }
1350
                return data;
1351

    
1352
        }
1353

    
1354
        public EditableFeature createNewFeature(FeatureType type,
1355
                        boolean defaultValues)
1356
        throws DataException {
1357
                try {
1358
                        FeatureProvider data = createNewFeatureProvider(type);
1359
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1360
                        if (defaultValues) {
1361
                                feature.initializeValues();
1362
                        }
1363
                        return feature;
1364
                } catch (Exception e) {
1365
                        throw new CreateFeatureException(e, getName());
1366
                }
1367
        }
1368

    
1369
        public EditableFeature createNewFeature(boolean defaultValues)
1370
        throws DataException {
1371
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1372
        }
1373

    
1374
        public EditableFeature createNewFeature() throws DataException {
1375
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1376
        }
1377

    
1378
        public EditableFeatureType createFeatureType() {
1379
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1380
                return ftype;
1381
        }
1382

    
1383
        public EditableFeatureType createFeatureType(String id) {
1384
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1385
                return ftype;
1386
        }
1387

    
1388

    
1389
        //
1390
        // ====================================================================
1391
        // Index related methods
1392
        //
1393

    
1394
        public FeatureIndexes getIndexes() {
1395
                return this.indexes;
1396
        }
1397

    
1398
        public FeatureIndex createIndex(FeatureType featureType,
1399
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1400
                checkNotInAppendMode();
1401
                FeatureIndexProviderServices index = null;
1402
                index = dataManager.createFeatureIndexProvider(null, this, featureType,
1403
                indexName, featureType.getAttributeDescriptor(attributeName));
1404
                try {
1405
                        index.fill();
1406
                } catch (FeatureIndexException e) {
1407
                        throw new InitializeException(index.getName(), e);
1408
                }
1409
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1410
                return index;
1411
        }
1412

    
1413
        public FeatureIndex createIndex(FeatureType featureType,
1414
                        String attributeName, String indexName, Observer observer) {
1415
                // TODO Implement observer interaction
1416
                throw new UnsupportedOperationException();
1417
        }
1418

    
1419
        //
1420
        // ====================================================================
1421
        // Transforms related methods
1422
        //
1423

    
1424
        public FeatureStoreTransforms getTransforms() {
1425
                return this.transforms;
1426
        }
1427

    
1428
        public FeatureQuery createFeatureQuery() {
1429
                return new DefaultFeatureQuery();
1430
        }
1431

    
1432
        public DataQuery createQuery() {
1433
                return createFeatureQuery();
1434
        }
1435

    
1436
        //
1437
        // ====================================================================
1438
        // UndoRedo related methods
1439
        //
1440

    
1441
        public boolean canRedo() {
1442
                return commands.canRedo();
1443
        }
1444

    
1445
        public boolean canUndo() {
1446
                return commands.canUndo();
1447
        }
1448

    
1449
        public void redo(int num) throws RedoException {
1450
                commands.redo(num);
1451
        }
1452

    
1453
        public void undo(int num) throws UndoException {
1454
                commands.undo(num);
1455
        }
1456

    
1457
        //
1458
        // ====================================================================
1459
        // Metadata related methods
1460
        //
1461

    
1462
        public Object getMetadataID() {
1463
                return this.provider.getSourceId();
1464
        }
1465

    
1466
        public void delegate(DynObject dynObject) {
1467
                this.metadata.delegate(dynObject);
1468
        }
1469

    
1470
        public DynClass getDynClass() {
1471
                return this.metadata.getDynClass();
1472
        }
1473

    
1474
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1475
                return this.metadata.getDynValue(name);
1476
        }
1477

    
1478
        public boolean hasDynValue(String name) {
1479
                return this.metadata.hasDynValue(name);
1480
        }
1481

    
1482
        public void implement(DynClass dynClass) {
1483
                this.metadata.implement(dynClass);
1484
        }
1485

    
1486
        public Object invokeDynMethod(String name, DynObject context)
1487
        throws DynMethodException {
1488
                return this.metadata.invokeDynMethod(this, name, context);
1489
        }
1490

    
1491
        public Object invokeDynMethod(int code, DynObject context)
1492
        throws DynMethodException {
1493
                return this.metadata.invokeDynMethod(this, code, context);
1494
        }
1495

    
1496
        public void setDynValue(String name, Object value)
1497
        throws DynFieldNotFoundException {
1498
                this.setDynValue(name, value);
1499

    
1500
        }
1501

    
1502
        /*
1503
         * (non-Javadoc)
1504
         *
1505
         * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1506
         */
1507
        public Set getMetadataChildren() {
1508
                return null;
1509
        }
1510

    
1511
        /*
1512
         * (non-Javadoc)
1513
         *
1514
         * @see org.gvsig.metadata.Metadata#getMetadataName()
1515
         */
1516
        public String getMetadataName() {
1517
                return this.provider.getName();
1518
        }
1519

    
1520
        public FeatureTypeManager getFeatureTypeManager() {
1521
                return this.featureTypeManager;
1522
        }
1523

    
1524
        public long getFeatureCount() throws DataException {
1525
                if (featureCount == null) {
1526
                        featureCount = new Long(this.provider.getFeatureCount());
1527
                }
1528
                if (this.isEditing() && !this.isAppending()) {
1529
                        return featureCount.longValue()
1530
                                        - this.featureManager.getDeltaSize();
1531
                }
1532
                return featureCount.longValue();
1533
        }
1534

    
1535
        private Long getTemporalOID() {
1536
                return new Long(this.temporalOid++);
1537
        }
1538

    
1539
        public FeatureType getProviderFeatureType(String featureTypeId) {
1540
                if (featureTypeId == null) {
1541
                        return this.defaultFeatureType;
1542
                }
1543
                FeatureType type;
1544
                Iterator iter = this.featureTypes.iterator();
1545
                while (iter.hasNext()) {
1546
                        type = (FeatureType) iter.next();
1547
                        if (type.getId().equals(featureTypeId)) {
1548
                                return type;
1549
                        }
1550
                }
1551
                return null;
1552
        }
1553

    
1554
        public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1555
                return ((DefaultFeature) feature).getData();
1556
        }
1557

    
1558
        public DataStore getStore() {
1559
                return this;
1560
        }
1561

    
1562
        public FeatureStore getFeatureStore() {
1563
                return this;
1564
        }
1565

    
1566
}