Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_data / src / org / gvsig / fmap / data / feature / impl / DefaultFeatureStore.java @ 23772

History | View | Annotate | Download (30.9 KB)

1
package org.gvsig.fmap.data.feature.impl;
2

    
3
import java.lang.ref.Reference;
4
import java.util.ArrayList;
5
import java.util.Collections;
6
import java.util.Iterator;
7
import java.util.List;
8

    
9
import org.gvsig.fmap.data.DALLocator;
10
import org.gvsig.fmap.data.DataCollection;
11
import org.gvsig.fmap.data.DataExplorer;
12
import org.gvsig.fmap.data.DataManager;
13
import org.gvsig.fmap.data.DataQuery;
14
import org.gvsig.fmap.data.DataStoreNotification;
15
import org.gvsig.fmap.data.DataStoreParameters;
16
import org.gvsig.fmap.data.ResourceNotification;
17
import org.gvsig.fmap.data.exceptions.CloseException;
18
import org.gvsig.fmap.data.exceptions.DataException;
19
import org.gvsig.fmap.data.exceptions.InitializeException;
20
import org.gvsig.fmap.data.exceptions.OpenException;
21
import org.gvsig.fmap.data.exceptions.ReadException;
22
import org.gvsig.fmap.data.exceptions.WriteException;
23
import org.gvsig.fmap.data.feature.Command;
24
import org.gvsig.fmap.data.feature.CommandsRecord;
25
import org.gvsig.fmap.data.feature.EditableFeature;
26
import org.gvsig.fmap.data.feature.EditableFeatureType;
27
import org.gvsig.fmap.data.feature.Feature;
28
import org.gvsig.fmap.data.feature.FeatureCollection;
29
import org.gvsig.fmap.data.feature.FeatureExplorer;
30
import org.gvsig.fmap.data.feature.FeatureID;
31
import org.gvsig.fmap.data.feature.FeatureQuery;
32
import org.gvsig.fmap.data.feature.FeatureStore;
33
import org.gvsig.fmap.data.feature.FeatureStoreNotification;
34
import org.gvsig.fmap.data.feature.FeatureType;
35
import org.gvsig.fmap.data.feature.exceptions.AlreadyEditingException;
36
import org.gvsig.fmap.data.feature.exceptions.ConcurrentDataModificationException;
37
import org.gvsig.fmap.data.feature.exceptions.CreateFeatureException;
38
import org.gvsig.fmap.data.feature.exceptions.DataExportException;
39
import org.gvsig.fmap.data.feature.exceptions.FeatureNotAllowedForThisStoreException;
40
import org.gvsig.fmap.data.feature.exceptions.FeatureTypeNotAllowedForThisStoreException;
41
import org.gvsig.fmap.data.feature.exceptions.FinishEditingException;
42
import org.gvsig.fmap.data.feature.exceptions.GetFeatureTypeException;
43
import org.gvsig.fmap.data.feature.exceptions.NeedEditingModeException;
44
import org.gvsig.fmap.data.feature.exceptions.NullFeatureTypeException;
45
import org.gvsig.fmap.data.feature.exceptions.SelectionNotAllowedException;
46
import org.gvsig.fmap.data.feature.exceptions.StoreCancelEditingException;
47
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteEditableFeatureException;
48
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteFeatureException;
49
import org.gvsig.fmap.data.feature.exceptions.StoreEditException;
50
import org.gvsig.fmap.data.feature.exceptions.StoreInsertFeatureException;
51
import org.gvsig.fmap.data.feature.exceptions.StoreRedoException;
52
import org.gvsig.fmap.data.feature.exceptions.StoreUndoException;
53
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureException;
54
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureTypeException;
55
import org.gvsig.fmap.data.feature.exceptions.ValidateFeaturesException;
56
import org.gvsig.fmap.data.feature.exceptions.WriteNotAllowedException;
57
import org.gvsig.fmap.data.feature.exceptions.XMLInitializeException;
58
import org.gvsig.fmap.data.feature.impl.commands.AbstractCommandsRecord;
59
import org.gvsig.fmap.data.feature.impl.commands.implementation.FeatureCommandsRecord;
60
import org.gvsig.fmap.data.feature.spi.DefaultFeatureData;
61
import org.gvsig.fmap.data.feature.spi.FeatureData;
62
import org.gvsig.fmap.data.feature.spi.FeatureLocks;
63
import org.gvsig.fmap.data.feature.spi.FeatureSelection;
64
import org.gvsig.fmap.data.feature.spi.FeatureStoreProvider;
65
import org.gvsig.fmap.data.feature.spi.TemporaryContainer;
66
import org.gvsig.fmap.data.impl.DefaultDataManager;
67
import org.gvsig.fmap.data.index.Index;
68
import org.gvsig.fmap.data.index.IndexException;
69
import org.gvsig.fmap.data.spi.AbstractResource;
70
import org.gvsig.fmap.geom.primitive.Envelope;
71
import org.gvsig.metadata.Metadata;
72
import org.gvsig.tools.exception.BaseException;
73
import org.gvsig.tools.observer.ComplexNotification;
74
import org.gvsig.tools.observer.DefaultObservable;
75
import org.gvsig.tools.observer.Observable;
76
import org.gvsig.tools.observer.Observer;
77
import org.gvsig.tools.operations.OperationContext;
78
import org.gvsig.tools.operations.OperationException;
79
import org.gvsig.tools.operations.OperationNotSupportedException;
80

    
81
import com.iver.utiles.XMLEntity;
82
import com.iver.utiles.XMLException;
83

    
84
final public class DefaultFeatureStore implements
85
                org.gvsig.fmap.data.feature.spi.FeatureStore, Observer {
86

    
87
        private DataStoreParameters parameters = null;
88
        private FeatureSelection selection;
89
        private FeatureLocks locks;
90

    
91
        private DefaultObservable observable = new DefaultObservable();
92

    
93
        private AbstractCommandsRecord commands;
94
        private FeatureTypeManager featureTypeManager;
95
        private FeatureManager featureManager;
96
        private SpatialManager spatialManager;
97

    
98
        private ArrayList resources = new ArrayList();
99

    
100
        private Observer selectionObserver = null; // TODO: No deberia haber
101
        // quedado obsoleto al ser el store el observer ?
102

    
103
        private FeatureType defaultFeatureType = null;
104
        private List featureTypes = new ArrayList();
105

    
106
        private boolean editingMode = false;
107
        private long versionOfUpdate = 0;
108
        private boolean hasStrongChanges = true;
109

    
110
        private DefaultDataManager dataManager = null;
111

    
112
        private FeatureStoreProvider provider = null;
113

    
114
        /*
115
         * TODO:
116
         *
117
         * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
118
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
119
         * featureType al que se le han cambiado las reglas de validacion cuando
120
         * hasStrongChanges=false.
121
         */
122

    
123
        public DefaultFeatureStore() {
124

    
125
        }
126

    
127
        public DefaultFeatureStore(DefaultDataManager manager,
128
                        DataStoreParameters parameters, FeatureStoreProvider provider) {
129
                initialize(manager, parameters, provider);
130
        }
131

    
132
        public DefaultFeatureStore(DefaultDataManager manager, XMLEntity xmlEntity)
133
                        throws XMLException {
134
                this.dataManager = manager;
135
                this.setXMLEntity(xmlEntity);
136
        }
137

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

    
146
        public String getName() {
147
                return this.parameters.getDataStoreName();
148
        }
149

    
150
        public String getClassName() {
151
                return this.getClass().getName();
152
        }
153

    
154
        public DataStoreParameters getParameters() {
155
                return parameters;
156
        }
157

    
158
        public DefaultDataManager getManager() {
159
                return this.dataManager;
160
        }
161

    
162
        public Iterator getChilds() {
163
                return provider.getChilds();
164
        }
165

    
166
        public void setFeatureTypes(List types, FeatureType defaultType) {
167
                this.featureTypes = types;
168
                this.defaultFeatureType = defaultType;
169
        }
170

    
171
        public void open() throws OpenException {
172
                // TODO: Se puede hacer un open estando en edicion ?
173
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
174
                this.provider.open();
175
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
176
        }
177

    
178
        public void refresh() throws OpenException, InitializeException {
179
                if (this.isEditing()) {
180
                        throw new IllegalStateException();
181
                }
182
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
183
                this.provider.refresh();
184
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
185
        }
186

    
187
        public void close() throws CloseException {
188
                // TODO: Se puede hacer un close estando en edicion ?
189
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
190
                this.provider.close();
191
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
192
        }
193

    
194
        public void dispose() throws CloseException {
195
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
196
                this.provider.dispose();
197
                if (this.selection != null) {
198
                        this.selection.dispose();
199
                        this.selection = null;
200
                }
201
                this.commands = null;
202

    
203
                if (this.locks != null) {
204
                        this.locks.dispose();
205
                        this.locks = null;
206
                }
207
                this.observable = null;
208
                this.featureManager = null;
209
                this.spatialManager = null;
210
                this.removeAllResources();
211
                this.resources = null;
212

    
213
                this.parameters = null;
214
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
215
        }
216

    
217
        public boolean allowWrite() {
218
                return this.provider.allowWrite();
219
        }
220

    
221
        public boolean canWriteGeometry(int geometryType) {
222
                return this.provider.canWriteGeometry(geometryType);
223
        }
224

    
225
        public DataExplorer getExplorer() throws ReadException {
226
                return this.provider.getExplorer();
227
        }
228

    
229
        public Metadata getMetadata() throws BaseException {
230
                // TODO:
231
                // Si el provider devuelbe null habria que ver de construir aqui
232
                // los metadatos basicos, como el Envelope y el SRS.
233
                return this.provider.getMetadata();
234
        }
235

    
236
        public Envelope getEnvelope() {
237
                return this.provider.getEnvelope();
238
        }
239

    
240
        public String getSRSDefaultGeometry() throws DataException {
241
                DefaultFeatureType type = (DefaultFeatureType) this
242
                                .getDefaultFeatureType();
243
                int index = type.getDefaultGeometryAttributeIndex();
244
                return type.getAttributeDescriptor(index).getSRS();
245
        }
246

    
247
        public FeatureLocks createDefaultFeatureLocks() throws DataException {
248
                return new DefaultFeatureLocks(this);
249
        }
250

    
251
        public FeatureSelection createDefaultFeatureSelection()
252
                        throws DataException {
253
                return new DefaultFeatureSelection(this);
254
        }
255

    
256
        public TemporaryContainer createDefaultTemporaryContainer()
257
                        throws DataException {
258
                return new MemoryTemporaryContainer();
259
        }
260

    
261
        public FeatureData createDefaultFeatureData(FeatureType type)
262
                        throws DataException {
263
                return new DefaultFeatureData((DefaultFeatureType) type);
264
        }
265

    
266
        //
267
        // ====================================================================
268
        // Persistencia
269
        // Interface IPersistence
270
        //
271

    
272
        public void setXMLEntity(XMLEntity xmlEntity) throws XMLException {
273

    
274
                XMLEntity paramsXML = xmlEntity.firstChild("type", "parameters");
275
                if (paramsXML == null) {
276
                        throw new XMLInitializeException("parameters not found", this
277
                                        .getName());
278
                }
279
                FeatureStoreProvider provider ;
280
                DataStoreParameters params ;
281
                XMLEntity providerXML = xmlEntity.firstChild("type", "provider");
282
                try {
283
                        params = this.getManager().createDataStoreParameters(paramsXML);
284
                } catch (Exception e) {
285
                        throw new XMLInitializeException("can't create parameters", this
286
                                        .getName());
287
                }
288
                try {
289
                        Class providerClass = Class.forName(providerXML.getStringProperty("className"));
290
                        provider = (FeatureStoreProvider) providerClass.newInstance();
291
                } catch (Exception e) {
292
                        throw new XMLInitializeException(
293
                                        "can't create provider",
294
                                        this.getName()
295
                                );
296
                }
297
                provider.setXMLEntity(providerXML);
298

    
299
                initialize(this.getManager(), params, provider);
300

    
301
                XMLEntity selectionXML = xmlEntity.firstChild("type", "selection");
302
                if (selectionXML != null) {
303
                        try {
304
                                selection = (DefaultFeatureSelection) createFeatureSelection();
305
                        } catch (Exception e) {
306
                                throw new XMLInitializeException("can't reload selection", this
307
                                                .getName());
308
                        }
309
                        selection.setXMLEntity(selectionXML);
310
                }
311

    
312
        }
313

    
314
        public XMLEntity getXMLEntity() throws XMLException {
315
                XMLEntity xml = new XMLEntity();
316
                xml.putProperty("dataStoreName", this.getName());
317

    
318
                XMLEntity paramsXML = this.parameters.getXMLEntity();
319
                paramsXML.putProperty("type", "parameters");
320
                xml.addChild(paramsXML);
321

    
322
                XMLEntity providerXML = this.provider.getXMLEntity();
323
                providerXML.putProperty("className", this.provider.getClassName());
324
                providerXML.putProperty("type", "provider");
325
                xml.addChild(providerXML);
326

    
327
                XMLEntity selectionXML = this.selection.getXMLEntity();
328
                selectionXML.putProperty("type", "selection");
329
                xml.addChild(selectionXML);
330

    
331
                return xml;
332
        }
333

    
334
        //
335
        // ====================================================================
336
        // Gestion de la seleccion
337
        //
338

    
339
        private void setSelectionObserver() {
340
                if (this.selection instanceof Observable) {
341
                        Observable obSelection = this.selection;
342
                        obSelection.addObserver(this.selectionObserver);
343
                }
344
        }
345

    
346
        private void unsetSelectionObserver() {
347
                if (this.selection instanceof Observable) {
348
                        Observable obSelection = this.selection;
349
                        obSelection.deleteObserver(this.selectionObserver);
350
                }
351
        }
352

    
353
        public void setSelection(DataCollection selection)
354
                        throws DataException {
355
                this.setSelection(selection);
356
        }
357

    
358
        public DataCollection createSelection() throws DataException {
359
                return createFeatureSelection();
360
        }
361

    
362
        public DataCollection getSelection() throws DataException {
363
                return this.getFeatureSelection();
364
        }
365

    
366
        public void setSelection(FeatureCollection selection)
367
                        throws DataException {
368
                if (selection.equals(this.selection)) {
369
                        return;
370
                }
371
                if (!selection.isFromStore(this)) {
372
                        throw new SelectionNotAllowedException(getName());
373
                }
374
                this.unsetSelectionObserver();
375
                if (this.getSelection().getClass().isInstance(selection)) {
376
                        this.selection = (DefaultFeatureSelection) selection;
377
                } else {
378
                        this.selection = null;
379
                        this.getFeatureSelection().addAll(selection);
380
                }
381
                this.setSelectionObserver();
382
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
383
        }
384

    
385
        public FeatureCollection createFeatureSelection() throws DataException {
386
                return this.provider.createFeatureSelection();
387
        }
388

    
389
        public FeatureCollection getFeatureSelection() throws DataException {
390
                if (selection == null) {
391
                        this.selection = (DefaultFeatureSelection) createFeatureSelection();
392
                        this.setSelectionObserver();
393
                }
394
                return selection;
395
        }
396

    
397
        //
398
        // ====================================================================
399
        // Gestion de notificaciones
400
        //
401

    
402
        public void notifyChange(String notification) {
403
                this.observable.notifyObservers(this,
404
                                new DefaultFeatureStoreNotification(this, notification));
405

    
406
        }
407

    
408
        public void notifyChange(String notification, Feature feature) {
409
                this.observable
410
                                .notifyObservers(this, new DefaultFeatureStoreNotification(
411
                                                this, notification, feature));
412
        }
413

    
414
        public void notifyChange(String notification, Command command) {
415
                this.observable
416
                                .notifyObservers(this, new DefaultFeatureStoreNotification(
417
                                                this, notification, command));
418
        }
419

    
420
        public void notifyChange(String notification, EditableFeatureType type) {
421
                this.observable.notifyObservers(this,
422
                                new DefaultFeatureStoreNotification(this, notification, type));
423
        }
424

    
425

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

    
431

    
432
        public FeatureCollection getLocks() throws DataException {
433
                if (locks == null) {
434
                        this.locks = this.provider.createFeatureLocks();
435
                }
436
                return locks;
437
        }
438

    
439
        //
440
        // ====================================================================
441
        // Gestion de recursos
442
        //
443

    
444
        public void removeAllResources() {
445
                Iterator iter = this.resources.iterator();
446
                while (iter.hasNext()) {
447
                        ((AbstractResource) iter.next()).deleteObserver(this);
448
                }
449
                this.resources.clear();
450
        }
451

    
452
        public void addResource(AbstractResource resource) {
453
                if (!this.resources.contains(resource)) {
454
                        resource.addObserver(this);
455
                        this.resources.add(resource);
456
                }
457

    
458
        }
459

    
460
        //
461
        // ====================================================================
462
        // Gestion de observers
463
        //
464

    
465
        public void disableNotifications() {
466
                this.observable.diableNotifications();
467

    
468
        }
469

    
470
        public void enableNotifications() {
471
                this.observable.enableNotifications();
472
        }
473

    
474
        public void beginComplexNotification() {
475
                this.observable.beginComplexNotification(new ComplexNotification());
476

    
477
        }
478

    
479
        public void endComplexNotification() {
480
                this.observable.endComplexNotification(this);
481

    
482
        }
483

    
484
        public void addObserver(Observer o) {
485
                this.observable.addObserver(o);
486

    
487
        }
488

    
489
        public void addObserver(Reference ref) {
490
                this.observable.addObserver(ref);
491
        }
492

    
493
        public void deleteObserver(Observer o) {
494
                this.observable.deleteObserver(o);
495
        }
496

    
497
        public void deleteObserver(Reference ref) {
498
                this.observable.deleteObserver(ref);
499
        }
500

    
501
        public void deleteObservers() {
502
                this.observable.deleteObservers();
503

    
504
        }
505

    
506
        //
507
        // ====================================================================
508
        // Interface Observer
509
        //
510
        // Usado para observar:
511
        // - su seleccion
512
        // - sus bloqueos
513
        // - sus recursos
514
        //
515

    
516
        public void update(Observable observable, Object notification) {
517
                if (notification instanceof ResourceNotification) {
518
                        if (((ResourceNotification) notification).getStore() == this) {
519
                                return;
520
                        }
521

    
522
                        if (((ResourceNotification) notification).getType().equals(
523
                                        ResourceNotification.CHANGED)) {
524
                                this.notifyChange(FeatureStoreNotification.RESOURCE_CHANGED);
525
                        }
526
                } else if (observable instanceof FeatureCollection) {
527
                        if (observable == this.selection) {
528
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
529
                        } else if (observable == this.locks) {
530
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
531
                        }
532

    
533
                }
534
        }
535

    
536

    
537
        //
538
        // ====================================================================
539
        // Gestion de operaciones
540
        // Interface ExtendedOperations
541
        //
542
        public Object invokeOperation(int code, OperationContext context)
543
                        throws OperationException, OperationNotSupportedException {
544

    
545
                return this.getManager().invokeDataStoreOperation(this, code, context);
546
        }
547

    
548
        public Object invokeOperation(String name, OperationContext context)
549
                        throws OperationException, OperationNotSupportedException {
550
                return this.getManager().invokeDataStoreOperation(this, name, context);
551
        }
552

    
553
        public boolean implementsOperation(int code) {
554
                return this.getManager().implementsDataStoreOperation(this.getName(),
555
                                code);
556
        }
557

    
558
        public boolean implementsOperation(String name) {
559
                return this.getManager().implementsDataStoreOperation(this.getName(),
560
                                name);
561
        }
562

    
563
        // TODO: Y la implementacion de esto ?
564

    
565
        public Object getOperation(int code) throws OperationException {
566
                return null;
567
        }
568

    
569
        public Object getOperation(String name) throws OperationException {
570
                return null;
571
        }
572

    
573
        //
574
        // ====================================================================
575
        // Edicion
576
        //
577

    
578
        private void newVersionOfUpdate() {
579
                this.versionOfUpdate++;
580
        }
581

    
582
        private long currentVersionOfUpdate() {
583
                return this.versionOfUpdate;
584
        }
585

    
586
        private void checkInEditingMode()
587
                        throws NeedEditingModeException {
588
                if (!editingMode) {
589
                        throw new NeedEditingModeException(this.getName());
590
                }
591
        }
592

    
593
        private void checkIsOwnFeature(Feature feature)
594
                        throws FeatureNotAllowedForThisStoreException {
595
                if (((DefaultFeature) feature).getStore() != this) {
596
                        throw new FeatureNotAllowedForThisStoreException(this.getName());
597
                }
598
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
599
                // fixFeatureType((DefaultFeatureType) feature.getType());
600
        }
601

    
602
        private void exitEditingMode() {
603
                commands.clear();
604
                featureManager = null;
605
                spatialManager = null;
606
                featureTypeManager = null;
607
                commands = null;
608

    
609
                editingMode = false;
610
                hasStrongChanges = true; // Lo deja a true por si las moscas
611
        }
612

    
613
        synchronized public void edit() throws DataException {
614
                try {
615
                        if (isEditing()) {
616
                                throw new AlreadyEditingException(this.getName());
617
                        }
618
                        notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
619

    
620
                        featureManager = new FeatureManager(this.provider
621
                                        .createTemporaryContainer());
622
                        featureTypeManager = new FeatureTypeManager(this.provider
623
                                        .createTemporaryContainer());
624
                        spatialManager = new SpatialManager();
625

    
626
                        commands = new FeatureCommandsRecord(featureManager,
627
                                        spatialManager, featureTypeManager);
628
                        editingMode = true;
629
                        hasStrongChanges = false;
630
                        notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
631
                } catch (Exception e) {
632
                        throw new StoreEditException(e, this.getName());
633
                }
634
        }
635

    
636
        public boolean isEditing() {
637
                return editingMode;
638
        }
639

    
640
        synchronized public void update(EditableFeatureType type)
641
                        throws DataException {
642
                try {
643
                        checkInEditingMode();
644
                        if (type == null) {
645
                                throw new NullFeatureTypeException(getName());
646
                        }
647
                        // FIXME: Comprobar que es un featureType aceptable.
648
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
649
                        newVersionOfUpdate();
650

    
651
                        FeatureType oldt = type.getSource().getCopy();
652
                        FeatureType newt = type.getNotEditableCopy();
653
                        commands.update(newt, oldt);
654

    
655
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
656
                                hasStrongChanges = true;
657
                        }
658
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
659
                } catch (Exception e) {
660
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
661
                }
662
        }
663

    
664
        synchronized public void delete(Feature feature) throws DataException {
665
                try {
666
                        checkInEditingMode();
667
                        checkIsOwnFeature(feature);
668
                        if (feature instanceof EditableFeature) {
669
                                throw new StoreDeleteEditableFeatureException(getName());
670
                        }
671
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
672
                        this.commands.delete(feature);
673
                        newVersionOfUpdate();
674
                        hasStrongChanges = true;
675
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
676
                } catch (Exception e) {
677
                        throw new StoreDeleteFeatureException(e, this.getName());
678
                }
679
        }
680

    
681
        private static EditableFeature lastChangedFeature = null;
682

    
683
        synchronized public void insert(EditableFeature feature)
684
                        throws DataException {
685
                try {
686
                        checkInEditingMode();
687
                        checkIsOwnFeature(feature);
688
                        if (feature.getSource() != null) {
689
                                throw new WriteException("Can't insert feature, not is new.",
690
                                                this.getName());
691
                        }
692
                        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
693
                        newVersionOfUpdate();
694
                        if (lastChangedFeature.getSource() != feature.getSource()) {
695
                                lastChangedFeature = feature;
696
                                feature.validate(Feature.UPDATE);
697
                                lastChangedFeature = null;
698
                        }
699
                        commands.insert(feature.getNotEditableCopy());
700
                        hasStrongChanges = true;
701
                        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
702
                } catch (Exception e) {
703
                        throw new StoreInsertFeatureException(e, this.getName());
704
                }
705
        }
706

    
707
        synchronized public void update(EditableFeature feature)
708
                        throws DataException {
709
                try {
710
                        if ((feature).getSource() == null) {
711
                                insert(feature);
712
                                return;
713
                        }
714
                        checkInEditingMode();
715
                        checkIsOwnFeature(feature);
716
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
717
                        newVersionOfUpdate();
718
                        if (lastChangedFeature.getSource() != feature.getSource()) {
719
                                lastChangedFeature = feature;
720
                                feature.validate(Feature.UPDATE);
721
                                lastChangedFeature = null;
722
                        }
723

    
724
                        Feature oldf = feature.getSource();
725
                        Feature newf = feature.getNotEditableCopy();
726
                        commands.update(newf, oldf);
727

    
728
                        hasStrongChanges = true;
729
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
730
                } catch (Exception e) {
731
                        throw new StoreUpdateFeatureException(e, this.getName());
732
                }
733
        }
734

    
735
        synchronized public void redo() throws DataException {
736
                try {
737
                        checkInEditingMode();
738
                        Command redo = commands.getNextRedoCommand();
739
                        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
740
                        newVersionOfUpdate();
741
                        commands.redo();
742
                        hasStrongChanges = true;
743
                        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
744
                } catch (Exception e) {
745
                        throw new StoreRedoException(e, this.getName());
746
                }
747
        }
748

    
749
        synchronized public void undo() throws DataException {
750
                try {
751
                        checkInEditingMode();
752
                        Command undo = commands.getNextUndoCommand();
753
                        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
754
                        newVersionOfUpdate();
755
                        commands.undo();
756
                        hasStrongChanges = true;
757
                        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
758
                } catch (Exception e) {
759
                        throw new StoreUndoException(e, this.getName());
760
                }
761
        }
762

    
763
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
764
                checkInEditingMode();
765
                return commands;
766
        }
767

    
768
        synchronized public void cancelEditing() throws DataException {
769
                try {
770
                        checkInEditingMode();
771
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
772
                        exitEditingMode();
773
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
774
                } catch (Exception e) {
775
                        throw new StoreCancelEditingException(e, this.getName());
776
                }
777
        }
778

    
779
        synchronized public void finishEditing() throws DataException {
780
                try {
781
                        checkInEditingMode();
782
                        if (!hasStrongChanges) {
783
                                performLightEditing();
784
                                return;
785
                        }
786
                        if (!this.allowWrite()) {
787
                                throw new WriteNotAllowedException(getName());
788
                        }
789

    
790
                        notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
791
                        validateFeatures(Feature.FINISH_EDITING);
792
                        provider.performEditing();
793
                        exitEditingMode();
794
                        notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
795
                } catch (Exception e) {
796
                        throw new FinishEditingException(e);
797
                }
798
        }
799

    
800
        private void performLightEditing() throws DataException {
801
                throw new UnsupportedOperationException(
802
                                "lightFinishEdition not yet implemented");
803

    
804
                // TODO: implementar
805
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
806
                // exitEditingMode();
807
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
808
        }
809

    
810
        public void export(FeatureExplorer explorer, DataStoreParameters params)
811
                        throws DataException {
812

    
813
                if (this.getFeatureTypes().size() != 1) {
814
                        throw new UnsupportedOperationException(
815
                                        "export whith more than one type not yet implemented");
816
                }
817
                try {
818
                        FeatureType type = this.getDefaultFeatureType();
819
                        explorer.add(params, type);
820

    
821
                        DataManager manager = DALLocator.getDataManager();
822
                        FeatureStore target = (FeatureStore) manager
823
                                        .createDataStore(params);
824
                        target.edit();
825

    
826
                        FeatureCollection features = this.getFeatureCollection();
827
                        Iterator it1 = features.iterator();
828
                        while (it1.hasNext()) {
829
                                Feature feature = (Feature) it1.next();
830
                                target.insert(target.createFeature(type, feature));
831
                        }
832
                        features.dispose();
833
                        target.finishEditing();
834
                        target.dispose();
835
                } catch (Exception e) {
836
                        throw new DataExportException(e, params.toString());
837
                }
838
        }
839

    
840
        //
841
        // ====================================================================
842
        // Obtencion de datos
843
        // getDataCollection, getFeatureCollection
844
        //
845

    
846
        public DataCollection getDataCollection() throws DataException {
847
                return this.provider.getFeatureCollection(new FeatureQuery(this
848
                                .getDefaultFeatureType()));
849
        }
850

    
851
        public DataCollection getDataCollection(DataQuery dataQuery)
852
                        throws ReadException {
853
                return this.provider.getFeatureCollection((FeatureQuery) dataQuery);
854
        }
855

    
856
        public void getDataCollection(Observer observer) throws DataException {
857
                this.getFeatureCollection(null, observer);
858
        }
859

    
860
        public void getDataCollection(DataQuery dataQuery, Observer observer)
861
                        throws DataException {
862
                this.getFeatureCollection((FeatureQuery) dataQuery, observer);
863
        }
864

    
865
        public FeatureCollection getFeatureCollection() throws DataException {
866
                return this.provider.getFeatureCollection(new FeatureQuery(this
867
                                .getDefaultFeatureType()));
868
        }
869

    
870
        public FeatureCollection getFeatureCollection(FeatureQuery featureQuery)
871
                        throws ReadException {
872
                return this.provider.getFeatureCollection(featureQuery);
873
        }
874

    
875
        public void getFeatureCollection(Observer observer)
876
                        throws DataException {
877
                this.getFeatureCollection(null, observer);
878
        }
879

    
880
        public void getFeatureCollection(FeatureQuery query, Observer observer)
881
                        throws DataException {
882
                class LoadInBackGround implements Runnable {
883
                        private FeatureStore store;
884
                        private FeatureQuery query;
885
                        private Observer observer;
886

    
887
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
888
                                        Observer observer) {
889
                                this.store = store;
890
                                this.query = query;
891
                                this.observer = observer;
892
                        }
893

    
894
                        public void run() {
895
                                try {
896
                                        FeatureCollection collection = store.getFeatureCollection(query);
897
                                        observer.update(
898
                                                        store,
899
                                                        new DefaultFeatureStoreNotification(
900
                                                                        store,
901
                                                                        FeatureStoreNotification.LOAD_FINISHED,
902
                                                                        collection
903
                                                                )
904
                                                );
905
                                } catch (Exception e) {
906
                                        observer.update(
907
                                                        store,
908
                                                        new DefaultFeatureStoreNotification(
909
                                                                        store,
910
                                                                        FeatureStoreNotification.LOAD_FINISHED,
911
                                                                        e
912
                                                                )
913
                                                );
914
                                }
915
                        }
916
                }
917

    
918
                if (query == null) {
919
                        query = new FeatureQuery(this.getDefaultFeatureType());
920
                }
921
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
922
                Thread thread = new Thread(task);
923
                thread.run();
924
        }
925

    
926
        public Feature getFeatureByID(FeatureID id) throws DataException {
927
                return this.provider.getFeatureByID(id, this.getDefaultFeatureType());
928
        }
929

    
930
        public Feature getFeatureByID(FeatureID id, FeatureType featureType)
931
                        throws ReadException {
932
                return this.provider.getFeatureByID(id, featureType);
933
        }
934

    
935
        //
936
        // ====================================================================
937
        // Gestion de features
938
        //
939

    
940
        private FeatureType fixFeatureType(DefaultFeatureType type)
941
                        throws DataException {
942
                FeatureType defaultType = this.getDefaultFeatureType();
943
                if (type == null || type.equals(defaultType)) {
944
                        return defaultType;
945
                }
946
                if (type.isSubtypeOf(defaultType)) {
947
                        return type;
948
                }
949
                Iterator iter = this.getFeatureTypes().iterator();
950
                FeatureType tmpType;
951
                while (iter.hasNext()) {
952
                        tmpType = (FeatureType) iter.next();
953
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
954
                                return type;
955
                        }
956

    
957
                }
958
                throw new FeatureTypeNotAllowedForThisStoreException(getName());
959
        }
960

    
961
        public void validateFeatures(int mode) throws DataException {
962
                try {
963
                        FeatureCollection collection = this.getFeatureCollection();
964
                        Iterator iter = collection.iterator();
965
                        long previousVersionOfUpdate = currentVersionOfUpdate();
966
                        while (iter.hasNext()) {
967
                                ((DefaultFeature) iter.next()).validate(mode);
968
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
969
                                        throw new ConcurrentDataModificationException(getName());
970
                                }
971
                        }
972
                } catch (Exception e) {
973
                        throw new ValidateFeaturesException(e, getName());
974
                }
975
        }
976

    
977
        public FeatureType getDefaultFeatureType() throws DataException {
978
                try {
979
                        if (isEditing()) {
980
                                return featureTypeManager.getFeatureType();
981
                        }
982
                        return defaultFeatureType;
983
                } catch (Exception e) {
984
                        throw new GetFeatureTypeException(e, getName());
985
                }
986
        }
987

    
988
        public List getFeatureTypes() throws DataException {
989
                try {
990
                        List types;
991
                        if (isEditing()) {
992
                                types = featureTypeManager.getFeatureTypes();
993
                        } else {
994
                                types = featureTypes;
995
                        }
996
                        return Collections.unmodifiableList(types);
997
                } catch (Exception e) {
998
                        throw new GetFeatureTypeException(e, getName());
999
                }
1000
        }
1001

    
1002
        public Feature createFeature(FeatureType type, FeatureData data)
1003
                        throws DataException {
1004
                DefaultFeature feature = new DefaultFeature(this, data);
1005
                return feature;
1006
        }
1007

    
1008
        public EditableFeature createFeature(FeatureType type,
1009
                        Feature defaultValues)
1010
                        throws DataException {
1011
                try {
1012
                        type = this.fixFeatureType((DefaultFeatureType) type);
1013
                        FeatureData data = this.provider.createFeatureData(type);
1014
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1015
                                        data);
1016
                        feature.initializeValues(defaultValues);
1017
                        return feature;
1018
                } catch (Exception e) {
1019
                        throw new CreateFeatureException(e, getName());
1020
                }
1021
        }
1022

    
1023
        public EditableFeature createFeature(FeatureType type,
1024
                        boolean defaultValues)
1025
                        throws DataException {
1026
                try {
1027
                        type = this.fixFeatureType((DefaultFeatureType) type);
1028
                        FeatureData data = this.provider.createFeatureData(type);
1029
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1030
                                        data);
1031
                        if (defaultValues) {
1032
                                feature.initializeValues();
1033
                        }
1034
                        return feature;
1035
                } catch (Exception e) {
1036
                        throw new CreateFeatureException(e, getName());
1037
                }
1038
        }
1039

    
1040
        public EditableFeature createFeature(boolean defaultValues)
1041
                        throws DataException {
1042
                return this.createFeature(this.getDefaultFeatureType(), defaultValues);
1043
        }
1044

    
1045
        public EditableFeature createFeature() throws DataException {
1046
                return this.createFeature(this.getDefaultFeatureType(), true);
1047
        }
1048

    
1049
        public Index createIndex(FeatureType type,
1050
                        String colName) throws IndexException {
1051
                // TODO Auto-generated method stub
1052
                return null;
1053
        }
1054

    
1055
        public boolean hasIndex(FeatureType type, String attributeName) {
1056
                // TODO Auto-generated method stub
1057
                return false;
1058
        }
1059

    
1060

    
1061

    
1062
}