Statistics
| Revision:

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

History | View | Annotate | Download (42.7 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.AbstractPersistenceManager;
89
import org.gvsig.tools.persistence.PersistenceException;
90
import org.gvsig.tools.persistence.PersistenceValueNotFoundException;
91
import org.gvsig.tools.persistence.PersistentState;
92
import org.gvsig.tools.task.Executor;
93
import org.gvsig.tools.undo.RedoException;
94
import org.gvsig.tools.undo.UndoException;
95
import org.gvsig.tools.undo.command.Command;
96
import org.slf4j.Logger;
97
import org.slf4j.LoggerFactory;
98

    
99
final public class DefaultFeatureStore implements
100
FeatureStoreProviderServices,
101
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 dynObject;
134

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

    
144
        public DefaultFeatureStore() {
145

    
146
        }
147

    
148
        public DefaultFeatureStore(DefaultDataManager manager,
149
                        DataStoreParameters parameters, FeatureStoreProvider provider)
150
        throws InitializeException {
151
                initialize(manager, parameters, provider);
152
        }
153

    
154
        private void initialize(DefaultDataManager manager,
155
                        DataStoreParameters parameters, FeatureStoreProvider provider)
156
        throws InitializeException {
157

    
158
                DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
159

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

    
176
        public Logger getLogger() {
177
                return DefaultFeatureStore.logger;
178
        }
179

    
180
        public String getName() {
181
                return this.parameters.getDataStoreName();
182
        }
183

    
184
        public DataStoreParameters getParameters() {
185
                return parameters;
186
        }
187

    
188
        public int getMode() {
189
                return this.mode;
190
        }
191

    
192
        public DefaultDataManager getManager() {
193
                return this.dataManager;
194
        }
195

    
196
        public Iterator getChildren() {
197
                return this.provider.getChilds();
198
        }
199

    
200
        public FeatureStoreProvider getProvider() {
201
                return this.provider;
202
        }
203

    
204
        public FeatureManager getFeatureManager() {
205
                return this.featureManager;
206
        }
207

    
208
        public void setFeatureTypes(List types, FeatureType defaultType) {
209
                this.featureTypes = types;
210
                this.defaultFeatureType = defaultType;
211
        }
212

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

    
220
        public void refresh() throws OpenException, InitializeException {
221
                if (this.mode != MODE_QUERY) {
222
                        throw new IllegalStateException();
223
                }
224
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
225
                this.provider.refresh();
226
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
227
        }
228

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

    
236
        public void dispose() throws CloseException {
237
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
238
                this.provider.dispose();
239
                if (this.selection != null) {
240
                        this.selection.dispose();
241
                        this.selection = null;
242
                }
243
                this.commands = null;
244

    
245
                if (this.locks != null) {
246
                        //this.locks.dispose();
247
                        this.locks = null;
248
                }
249

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

    
255
                this.featureManager = null;
256
                this.spatialManager = null;
257

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

    
264
        public boolean allowWrite() {
265
                return this.provider.allowWrite();
266
        }
267

    
268
        public boolean canWriteGeometry(int geometryType) throws DataException {
269
                return this.provider.canWriteGeometry(geometryType);
270
        }
271

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

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

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

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

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

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

    
308
        public FeatureData createDefaultFeatureData(FeatureType type)
309
        throws DataException {
310
                if( type.hasOID() ) {
311
                        return new DefaultFeatureData(type, this.provider.createNewOID());
312
                }
313
                return new DefaultFeatureData(type);
314
        }
315
        public PersistentState getState()
316
        throws PersistenceException {
317
                return AbstractPersistenceManager.getState(this);
318
        }
319

    
320
        public void loadState(PersistentState state) throws PersistenceException {
321
                state.setTheClass(this);
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 setState(PersistentState state) throws PersistenceException {
331
                if (this.provider != null) {
332
                        throw new PersistenceException(null);
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.getManager(), 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
                mode = MODE_QUERY;
609
                hasStrongChanges = true; // Lo deja a true por si las moscas
610
                hasInserts = true;
611
        }
612

    
613
        synchronized public void edit() throws DataException {
614
                edit(MODE_FULLEDIT);
615
        }
616

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

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

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

    
662
        public boolean isEditing() {
663
                return mode == MODE_FULLEDIT;
664
        }
665

    
666
        public boolean isAppending() {
667
                return mode == MODE_APPEND;
668
        }
669

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

    
681
                        FeatureType oldt = type.getSource().getCopy();
682
                        FeatureType newt = type.getNotEditableCopy();
683
                        commands.update(newt, oldt);
684

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

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

    
711
        private static EditableFeature lastChangedFeature = null;
712

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

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

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

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

    
773
                        Feature oldf = feature.getSource();
774
                        Feature newf = feature.getNotEditableCopy();
775
                        commands.update(newf, oldf);
776

    
777
                        hasStrongChanges = true;
778
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
779
                } catch (Exception e) {
780
                        throw new StoreUpdateFeatureException(e, this.getName());
781
                }
782
        }
783

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

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

    
812
        public List getRedoInfos() {
813
                if (isEditing() && commands != null) {
814
                        return commands.getRedoInfos();
815
                } else {
816
                        return null;
817
                }
818
        }
819

    
820
        public List getUndoInfos() {
821
                if (isEditing() && commands != null) {
822
                        return commands.getUndoInfos();
823
                } else {
824
                        return null;
825
                }
826
        }
827

    
828
        public synchronized FeatureCommandsStack getCommandsStack()
829
        throws DataException {
830
                checkInEditingMode();
831
                return commands;
832
        }
833

    
834
        synchronized public void cancelEditing() throws DataException {
835
                spatialManager.cancelModifies();
836
                try {
837
                        checkInEditingMode();
838

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

    
854
        synchronized public void finishEditing() throws DataException {
855
                try {
856
                        switch (mode) {
857
                        case MODE_QUERY:
858
                                throw new NeedEditingModeException(this.getName());
859

    
860
                        case MODE_APPEND:
861
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
862
                                provider.endAppend();
863
                                exitEditingMode();
864
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
865
                                break;
866

    
867
                        case MODE_FULLEDIT:
868
                                if (!hasStrongChanges) {
869
                                        performLightEditing();
870
                                        return;
871
                                }
872
                                if (!this.allowWrite()) {
873
                                        throw new WriteNotAllowedException(getName());
874
                                }
875

    
876
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
877
                                validateFeatures(Feature.FINISH_EDITING);
878
                                provider.performEditing(featureManager.getInserted(),
879
                                                featureManager.getUpdated(), featureManager
880
                                                .getDeleted());
881
                                exitEditingMode();
882
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
883
                                break;
884
                        }
885
                } catch (Exception e) {
886
                        throw new FinishEditingException(e);
887
                }
888
        }
889

    
890
        private void performLightEditing() throws DataException {
891
                throw new NotYetImplemented(
892
                "lightFinishEdition not yet implemented");
893

    
894
                // TODO: implementar
895
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
896
                // exitEditingMode();
897
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
898
        }
899

    
900

    
901
        public void beginEditingGroup(String description)
902
        throws NeedEditingModeException {
903
                checkInEditingMode();
904
                commands.startComplex(description);
905
        }
906

    
907
        public void endEditingGroup() throws NeedEditingModeException {
908
                checkInEditingMode();
909
                commands.endComplex();
910
        }
911

    
912
        public boolean isAppendModeSupported() {
913
                return this.provider.supportsAppendMode();
914
        }
915

    
916

    
917
        public void export(DataServerExplorer explorer, NewFeatureStoreParameters params)
918
        throws DataException {
919

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

    
932
                        }
933
                        explorer.add(params, true);
934

    
935
                        DataManager manager = DALLocator.getDataManager();
936
                        FeatureStore target = (FeatureStore) manager
937
                        .createStore(params);
938
                        FeatureType targetType = target.getDefaultFeatureType();
939

    
940
                        target.edit(MODE_APPEND);
941
                        FeatureSet features=null;
942
                        if (featureSelection.getSize()>0){
943
                                features = this.getFeatureSelection();
944
                        }else{
945
                                features = this.getFeatureSet();
946
                        }
947
                        Iterator it1 = features.iterator();
948
                        while (it1.hasNext()) {
949
                                Feature feature = (Feature) it1.next();
950
                                target.insert(target.createNewFeature(targetType, feature));
951
                        }
952
                        features.dispose();
953
                        target.finishEditing();
954
                        target.dispose();
955
                } catch (Exception e) {
956
                        throw new DataExportException(e, params.toString());
957
                }
958
        }
959

    
960
        //
961
        // ====================================================================
962
        // Obtencion de datos
963
        // getDataCollection, getFeatureCollection
964
        //
965

    
966
        public DataSet getDataSet() throws DataException {
967
                checkNotInAppendMode();
968
                FeatureQuery query = new DefaultFeatureQuery(this
969
                                .getDefaultFeatureType());
970
                return new DefaultFeatureSet(this, query);
971
        }
972

    
973
        public DataSet getDataSet(DataQuery dataQuery)
974
        throws DataException {
975
                checkNotInAppendMode();
976
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
977
        }
978

    
979
        public void getDataSet(Observer observer) throws DataException {
980
                checkNotInAppendMode();
981
                this.getFeatureSet(null, observer);
982
        }
983

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

    
990
        public FeatureSet getFeatureSet() throws DataException {
991
                checkNotInAppendMode();
992
                FeatureQuery query = new DefaultFeatureQuery(this
993
                                .getDefaultFeatureType());
994
                return new DefaultFeatureSet(this, query);
995
        }
996

    
997
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
998
        throws DataException {
999
                checkNotInAppendMode();
1000
                return new DefaultFeatureSet(this, featureQuery);
1001
        }
1002

    
1003

    
1004
        public FeatureType getFeatureType(FeatureQuery featureQuery)
1005
                        throws DataException {
1006
                DefaultFeatureType fType = (DefaultFeatureType) this
1007
                                .getFeatureType(featureQuery.getFeatureTypeId());
1008
                if (featureQuery.getAttributeNames() != null){
1009
                        return fType.getSubtype(featureQuery.getAttributeNames());
1010
                }
1011
                return fType;
1012
        }
1013

    
1014
        public void getFeatureSet(Observer observer)
1015
        throws DataException {
1016
                checkNotInAppendMode();
1017
                this.getFeatureSet(null, observer);
1018
        }
1019

    
1020
        public void getFeatureSet(FeatureQuery query, Observer observer)
1021
        throws DataException {
1022
                class LoadInBackGround implements Runnable {
1023
                        private FeatureStore store;
1024
                        private FeatureQuery query;
1025
                        private Observer observer;
1026
                        private Executor executor;
1027
                        private FeatureStoreNotification notification;
1028

    
1029
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
1030
                                        Observer observer, Executor executor) {
1031
                                this.store = store;
1032
                                this.query = query;
1033
                                this.observer = observer;
1034
                                this.executor = executor;
1035
                        }
1036

    
1037
                        void notify(FeatureStoreNotification theNotification) {
1038
                                if (executor == null) {
1039
                                        observer.update(store, theNotification);
1040
                                        return;
1041
                                }
1042
                                this.notification = theNotification;
1043
                                executor.execute(new Runnable() {
1044
                                        public void run() {
1045
                                                observer.update(store, notification);
1046
                                        }
1047
                                });
1048

    
1049
                        }
1050

    
1051
                        public void run() {
1052
                                try {
1053
                                        FeatureSet set = store.getFeatureSet(query);
1054
                                        notify(new DefaultFeatureStoreNotification(store,
1055
                                                        FeatureStoreNotification.LOAD_FINISHED, set));
1056
                                } catch (Exception e) {
1057
                                        notify(new DefaultFeatureStoreNotification(store,
1058
                                                        FeatureStoreNotification.LOAD_FINISHED, e));
1059
                                }
1060
                        }
1061
                }
1062

    
1063
                checkNotInAppendMode();
1064
                if (query == null) {
1065
                        query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1066
                }
1067
                Executor executor = ToolsLocator.getTaskManager().getExecutor();
1068
                LoadInBackGround task = new LoadInBackGround(this, query, observer,
1069
                                executor);
1070
                Thread thread = new Thread(task);
1071
                thread.run();
1072
        }
1073

    
1074
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
1075
                checkNotInAppendMode();
1076
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
1077
        }
1078

    
1079
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
1080
        throws DataException {
1081
                checkNotInAppendMode();
1082
                featureType = fixFeatureType((DefaultFeatureType) featureType);
1083
                if (!this.transforms.isEmpty()) {
1084

    
1085
                        featureType = this.transforms
1086
                        .getSourceFeatureTypeFrom(featureType);
1087

    
1088
                }
1089
                // TODO comprobar que el id es de este store
1090

    
1091
                if (this.mode == MODE_FULLEDIT) {
1092
                        Feature f = featureManager.get(reference, this, featureType);
1093
                        if (f!=null) {
1094
                                return f;
1095
                        }
1096
                }
1097
                DefaultFeature feature = new DefaultFeature(
1098
                                this,
1099
                                this.provider
1100
                                .getFeatureDataByReference(
1101
                                                (FeatureReferenceProviderServices) reference,
1102
                                                featureType));
1103

    
1104
                if (!this.transforms.isEmpty()) {
1105
                        return this.transforms.applyTransform(feature, featureType);
1106
                }
1107
                return feature;
1108
        }
1109

    
1110
        //
1111
        // ====================================================================
1112
        // Gestion de features
1113
        //
1114

    
1115
        private FeatureType fixFeatureType(DefaultFeatureType type)
1116
        throws DataException {
1117
                FeatureType original = this.getDefaultFeatureType();
1118

    
1119
                if (type == null || type.equals(original)) {
1120
                        return original;
1121
                } else {
1122
                        if (!type.isSubtypeOf(original)) {
1123
                                Iterator iter = this.getFeatureTypes().iterator();
1124
                                FeatureType tmpType;
1125
                                boolean found = false;
1126
                                while (iter.hasNext()) {
1127
                                        tmpType = (FeatureType) iter.next();
1128
                                        if (type.equals(tmpType)) {
1129
                                                return type;
1130

    
1131
                                        }else if (type.isSubtypeOf(tmpType)) {
1132
                                                found = true;
1133
                                                original = tmpType;
1134
                                                break;
1135
                                        }
1136

    
1137
                                }
1138
                                if (!found) {
1139
                                        throw new IllegalFeatureTypeException(getName());
1140
                                }
1141
                        }
1142
                }
1143

    
1144
                // Checks that type has all fields of pk
1145
                // else add the missing attributes at the end.
1146
                if (!original.hasOID()) {
1147
                        // Gets original pk attributes
1148
                        DefaultEditableFeatureType edOriginal = (DefaultEditableFeatureType) original
1149
                                        .getEditable();
1150
                        FeatureAttributeDescriptor orgAttr;
1151
                        Iterator edOriginalIter = edOriginal.iterator();
1152
                        while (edOriginalIter.hasNext()) {
1153
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1154
                                if (!orgAttr.isPrimaryKey()) {
1155
                                        edOriginalIter.remove();
1156
                                }
1157
                        }
1158

    
1159
                        // Checks if all pk attributes are in type
1160
                        Iterator typeIterator;
1161
                        edOriginalIter = edOriginal.iterator();
1162
                        FeatureAttributeDescriptor attr;
1163
                        while (edOriginalIter.hasNext()) {
1164
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1165
                                typeIterator = type.iterator();
1166
                                while (typeIterator.hasNext()) {
1167
                                        attr = (FeatureAttributeDescriptor) typeIterator.next();
1168
                                        if (attr.getName().equals(orgAttr.getName())) {
1169
                                                edOriginalIter.remove();
1170
                                                break;
1171
                                        }
1172
                                }
1173
                        }
1174

    
1175
                        // add missing pk attributes if any
1176
                        if (edOriginal.size() > 0) {
1177
                                boolean isEditable = type instanceof DefaultEditableFeatureType;
1178
                                DefaultEditableFeatureType edType = (DefaultEditableFeatureType) original
1179
                                                .getEditable();
1180
                                edType.clear();
1181
                                edType.addAll(type);
1182
                                edType.addAll(edOriginal);
1183
                                if (!isEditable) {
1184
                                        type = (DefaultFeatureType) edType.getNotEditableCopy();
1185
                                }
1186
                        }
1187

    
1188
                }
1189

    
1190

    
1191
                return type;
1192
        }
1193

    
1194
        public void validateFeatures(int mode) throws DataException {
1195
                try {
1196
                        checkNotInAppendMode();
1197
                        FeatureSet collection = this.getFeatureSet();
1198
                        Iterator iter = collection.iterator();
1199
                        long previousVersionOfUpdate = currentVersionOfUpdate();
1200
                        while (iter.hasNext()) {
1201
                                ((DefaultFeature) iter.next()).validate(mode);
1202
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1203
                                        throw new ConcurrentDataModificationException(getName());
1204
                                }
1205
                        }
1206
                } catch (Exception e) {
1207
                        throw new ValidateFeaturesException(e, getName());
1208
                }
1209
        }
1210

    
1211
        public FeatureType getDefaultFeatureType() throws DataException {
1212
                try {
1213
                        if (isEditing()) {
1214
                                FeatureType auxFeatureType=featureTypeManager.getType(defaultFeatureType.getId());
1215
                                if (auxFeatureType!=null) {
1216
                                        return auxFeatureType;
1217
                                }
1218
                        }
1219
                        FeatureType type = this.transforms.getDefaultFeatureType();
1220
                        if (type != null) {
1221
                                return type;
1222
                        }
1223
                        return defaultFeatureType;
1224
                } catch (Exception e) {
1225
                        throw new GetFeatureTypeException(e, getName());
1226
                }
1227
        }
1228

    
1229
        public FeatureType getFeatureType(String featureTypeId)
1230
                        throws DataException {
1231
                if (featureTypeId == null) {
1232
                        return this.getDefaultFeatureType();
1233
                }
1234
                try {
1235
                        if (isEditing()) {
1236
                                FeatureType auxFeatureType = featureTypeManager
1237
                                                .getType(featureTypeId);
1238
                                if (auxFeatureType != null) {
1239
                                        return auxFeatureType;
1240
                                }
1241
                        }
1242
                        FeatureType type = this.transforms.getFeatureType(featureTypeId);
1243
                        if (type != null) {
1244
                                return type;
1245
                        }
1246
                        Iterator iter = this.featureTypes.iterator();
1247
                        while (iter.hasNext()){
1248
                                type = (FeatureType) iter.next();
1249
                                if (type.getId().equals(featureTypeId)) {
1250
                                        return type;
1251
                                }
1252
                        }
1253
                        return null;
1254
                } catch (Exception e) {
1255
                        throw new GetFeatureTypeException(e, getName());
1256
                }
1257
        }
1258

    
1259

    
1260
        public FeatureType getProviderDefaultFeatureType() {
1261
                return defaultFeatureType;
1262
        }
1263

    
1264
        public List getFeatureTypes() throws DataException {
1265
                try {
1266
                        List types;
1267
                        if (isEditing()) {
1268
                                types=new ArrayList();
1269
                                Iterator it=featureTypes.iterator();
1270
                                while (it.hasNext()) {
1271
                                        FeatureType type = (FeatureType) it.next();
1272
                                        FeatureType typeaux = featureTypeManager.getType(type.getId());
1273
                                        if (typeaux!=null) {
1274
                                                types.add(typeaux);
1275
                                        }else{
1276
                                                types.add(type);
1277
                                        }
1278
                                }
1279
                                it = featureTypeManager.newsIterator();
1280
                                while (it.hasNext()) {
1281
                                        FeatureType type = (FeatureType) it.next();
1282
                                        types.add(type);
1283
                                }
1284
                        } else {
1285
                                types = this.transforms.getFeatureTypes();
1286
                                if (types == null) {
1287
                                        types = featureTypes;
1288
                                }
1289
                        }
1290
                        return Collections.unmodifiableList(types);
1291
                } catch (Exception e) {
1292
                        throw new GetFeatureTypeException(e, getName());
1293
                }
1294
        }
1295

    
1296
        public List getProviderFeatureTypes() throws DataException {
1297
                return Collections.unmodifiableList(this.featureTypes);
1298
        }
1299

    
1300
        public Feature createFeature(FeatureData data)
1301
        throws DataException {
1302
                DefaultFeature feature = new DefaultFeature(this, data);
1303
                return feature;
1304
        }
1305

    
1306
        public Feature createFeature(FeatureData data, FeatureType type)
1307
        throws DataException {
1308
                // FIXME: falta por implementar
1309
                // Comprobar si es un subtipo del feature de data
1310
                // y construir un feature usando el subtipo.
1311
                // Probablemente requiera generar una copia del data.
1312
                throw new NotYetImplemented();
1313
        }
1314

    
1315
        public EditableFeature createNewFeature(FeatureType type,
1316
                        Feature defaultValues)
1317
        throws DataException {
1318
                try {
1319
                        type = this.fixFeatureType((DefaultFeatureType) type);
1320
                        FeatureData data = this.provider.createFeatureData(type);
1321
                        data.setNew(true);
1322
                        if (type.hasOID() && data.getOID() == null) {
1323
                                data.setOID(this.provider.createNewOID());
1324
                        }
1325
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1326
                        feature.initializeValues(defaultValues);
1327
                        return feature;
1328
                } catch (Exception e) {
1329
                        throw new CreateFeatureException(e, getName());
1330
                }
1331
        }
1332

    
1333
        public EditableFeature createNewFeature(FeatureType type,
1334
                        boolean defaultValues)
1335
        throws DataException {
1336
                try {
1337
                        type = this.fixFeatureType((DefaultFeatureType) type);
1338
                        FeatureData data = this.provider.createFeatureData(type);
1339
                        data.setNew(true);
1340
                        if (type.hasOID() && data.getOID() == null) {
1341
                                data.setOID(this.provider.createNewOID());
1342
                        }
1343
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1344
                        if (defaultValues) {
1345
                                feature.initializeValues();
1346
                        }
1347
                        return feature;
1348
                } catch (Exception e) {
1349
                        throw new CreateFeatureException(e, getName());
1350
                }
1351
        }
1352

    
1353
        public EditableFeature createNewFeature(boolean defaultValues)
1354
        throws DataException {
1355
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1356
        }
1357

    
1358
        public EditableFeature createNewFeature() throws DataException {
1359
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1360
        }
1361

    
1362
        public EditableFeatureType createFeatureType() {
1363
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1364
                ftype.setAllowAutomaticValues(this.provider.allowAutomaticValues());
1365
                return ftype;
1366
        }
1367

    
1368
        public EditableFeatureType createFeatureType(String id) {
1369
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1370
                ftype.setAllowAutomaticValues(this.provider.allowAutomaticValues());
1371
                return ftype;
1372
        }
1373

    
1374

    
1375
        //
1376
        // ====================================================================
1377
        // Index related methods
1378
        //
1379

    
1380
        public FeatureIndexes getIndexes() {
1381
                return this.indexes;
1382
        }
1383

    
1384
        public FeatureIndex createIndex(FeatureType featureType,
1385
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1386
                checkNotInAppendMode();
1387
                FeatureIndexProviderServices index = null;
1388
                index = getManager().createFeatureIndexProvider(null, this, featureType, indexName, featureType.getAttributeDescriptor(attributeName));
1389
                try {
1390
                        index.fill();
1391
                } catch (FeatureIndexException e) {
1392
                        throw new InitializeException(index.getName(), e);
1393
                }
1394
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1395
                return index;
1396
        }
1397

    
1398
        public FeatureIndex createIndex(FeatureType featureType,
1399
                        String attributeName, String indexName, Observer observer) {
1400
                // TODO Implement observer interaction
1401
                throw new UnsupportedOperationException();
1402
        }
1403

    
1404
        //
1405
        // ====================================================================
1406
        // Transforms related methods
1407
        //
1408

    
1409
        public FeatureStoreTransforms getTransforms() {
1410
                return this.transforms;
1411
        }
1412

    
1413
        public FeatureQuery createFeatureQuery() {
1414
                return new DefaultFeatureQuery();
1415
        }
1416

    
1417
        public DataQuery createQuery() {
1418
                return createFeatureQuery();
1419
        }
1420

    
1421
        //
1422
        // ====================================================================
1423
        // UndoRedo related methods
1424
        //
1425

    
1426
        public boolean canRedo() {
1427
                return commands.canRedo();
1428
        }
1429

    
1430
        public boolean canUndo() {
1431
                return commands.canUndo();
1432
        }
1433

    
1434
        public void redo(int num) throws RedoException {
1435
                commands.redo(num);
1436
        }
1437

    
1438
        public void undo(int num) throws UndoException {
1439
                commands.undo(num);
1440
        }
1441

    
1442
        //
1443
        // ====================================================================
1444
        // Metadata related methods
1445
        //
1446

    
1447
        public Object getMetadataID() {
1448
                return this.provider.getSourceId();
1449
        }
1450

    
1451
        public void delegate(DynObject dynObject) {
1452
                this.dynObject.delegate(dynObject);
1453
        }
1454

    
1455
        public DynClass getDynClass() {
1456
                return this.dynObject.getDynClass();
1457
        }
1458

    
1459
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1460
                return this.dynObject.getDynValue(name);
1461
        }
1462

    
1463
        public boolean hasDynValue(String name) {
1464
                return this.dynObject.hasDynValue(name);
1465
        }
1466

    
1467
        public void implement(DynClass dynClass) {
1468
                this.dynObject.implement(dynClass);
1469
        }
1470

    
1471
        public Object invokeDynMethod(String name, DynObject context)
1472
        throws DynMethodException {
1473
                return this.dynObject.invokeDynMethod(this, name, context);
1474
        }
1475

    
1476
        public Object invokeDynMethod(int code, DynObject context)
1477
        throws DynMethodException {
1478
                return this.dynObject.invokeDynMethod(this, code, context);
1479
        }
1480

    
1481
        public void setDynValue(String name, Object value)
1482
        throws DynFieldNotFoundException {
1483
                this.setDynValue(name, value);
1484

    
1485
        }
1486

    
1487
        /*
1488
         * (non-Javadoc)
1489
         *
1490
         * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1491
         */
1492
        public Set getMetadataChildren() {
1493
                return null;
1494
        }
1495

    
1496
        /*
1497
         * (non-Javadoc)
1498
         *
1499
         * @see org.gvsig.metadata.Metadata#getMetadataName()
1500
         */
1501
        public String getMetadataName() {
1502
                return this.provider.getName();
1503
        }
1504

    
1505
        public FeatureTypeManager getFeatureTypeManager() {
1506
                return this.featureTypeManager;
1507
        }
1508

    
1509

    
1510
}