Statistics
| Revision:

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

History | View | Annotate | Download (32.3 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.DataExplorer;
11
import org.gvsig.fmap.data.DataManager;
12
import org.gvsig.fmap.data.DataQuery;
13
import org.gvsig.fmap.data.DataSet;
14
import org.gvsig.fmap.data.DataStoreNotification;
15
import org.gvsig.fmap.data.DataStoreParameters;
16
import org.gvsig.fmap.data.exceptions.CloseException;
17
import org.gvsig.fmap.data.exceptions.DataException;
18
import org.gvsig.fmap.data.exceptions.InitializeException;
19
import org.gvsig.fmap.data.exceptions.OpenException;
20
import org.gvsig.fmap.data.exceptions.ReadException;
21
import org.gvsig.fmap.data.feature.Command;
22
import org.gvsig.fmap.data.feature.CommandsRecord;
23
import org.gvsig.fmap.data.feature.EditableFeature;
24
import org.gvsig.fmap.data.feature.EditableFeatureType;
25
import org.gvsig.fmap.data.feature.Feature;
26
import org.gvsig.fmap.data.feature.FeatureExplorer;
27
import org.gvsig.fmap.data.feature.FeatureQuery;
28
import org.gvsig.fmap.data.feature.FeatureReference;
29
import org.gvsig.fmap.data.feature.FeatureSet;
30
import org.gvsig.fmap.data.feature.FeatureStore;
31
import org.gvsig.fmap.data.feature.FeatureStoreNotification;
32
import org.gvsig.fmap.data.feature.FeatureType;
33
import org.gvsig.fmap.data.feature.exceptions.AlreadyEditingException;
34
import org.gvsig.fmap.data.feature.exceptions.ConcurrentDataModificationException;
35
import org.gvsig.fmap.data.feature.exceptions.CreateFeatureException;
36
import org.gvsig.fmap.data.feature.exceptions.DataExportException;
37
import org.gvsig.fmap.data.feature.exceptions.FeatureNotAllowedForThisStoreException;
38
import org.gvsig.fmap.data.feature.exceptions.FeatureTypeNotAllowedForThisStoreException;
39
import org.gvsig.fmap.data.feature.exceptions.FinishEditingException;
40
import org.gvsig.fmap.data.feature.exceptions.GetFeatureTypeException;
41
import org.gvsig.fmap.data.feature.exceptions.NeedEditingModeException;
42
import org.gvsig.fmap.data.feature.exceptions.NoNewFeatureInsertException;
43
import org.gvsig.fmap.data.feature.exceptions.NullFeatureTypeException;
44
import org.gvsig.fmap.data.feature.exceptions.SelectionNotAllowedException;
45
import org.gvsig.fmap.data.feature.exceptions.StoreCancelEditingException;
46
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteEditableFeatureException;
47
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteFeatureException;
48
import org.gvsig.fmap.data.feature.exceptions.StoreEditException;
49
import org.gvsig.fmap.data.feature.exceptions.StoreInsertFeatureException;
50
import org.gvsig.fmap.data.feature.exceptions.StoreRedoException;
51
import org.gvsig.fmap.data.feature.exceptions.StoreUndoException;
52
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureException;
53
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureTypeException;
54
import org.gvsig.fmap.data.feature.exceptions.ValidateFeaturesException;
55
import org.gvsig.fmap.data.feature.exceptions.WriteNotAllowedException;
56
import org.gvsig.fmap.data.feature.exceptions.XMLInitializeException;
57
import org.gvsig.fmap.data.feature.impl.commands.AbstractCommandsRecord;
58
import org.gvsig.fmap.data.feature.impl.commands.implementation.FeatureCommandsRecord;
59
import org.gvsig.fmap.data.feature.impl.featureSet.DefaultFeatureSet;
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.FeatureStoreProviderServices;
66
import org.gvsig.fmap.data.feature.spi.TemporaryContainer;
67
import org.gvsig.fmap.data.impl.DefaultDataManager;
68
import org.gvsig.fmap.data.index.Index;
69
import org.gvsig.fmap.data.index.IndexException;
70
import org.gvsig.fmap.data.resource.ResourceNotification;
71
import org.gvsig.fmap.geom.primitive.Envelope;
72
import org.gvsig.metadata.Metadata;
73
import org.gvsig.tools.exception.BaseException;
74
import org.gvsig.tools.observer.ComplexNotification;
75
import org.gvsig.tools.observer.DefaultObservable;
76
import org.gvsig.tools.observer.Observable;
77
import org.gvsig.tools.observer.Observer;
78
import org.gvsig.tools.operations.OperationContext;
79
import org.gvsig.tools.operations.OperationException;
80
import org.gvsig.tools.operations.OperationNotSupportedException;
81
import org.slf4j.Logger;
82
import org.slf4j.LoggerFactory;
83

    
84
import com.iver.utiles.XMLEntity;
85
import com.iver.utiles.XMLException;
86

    
87
final public class DefaultFeatureStore implements
88
                FeatureStoreProviderServices,
89
                Observer {
90

    
91
        private DataStoreParameters parameters = null;
92
        private FeatureSelection selection;
93
        private FeatureLocks locks;
94

    
95
        private DefaultObservable observable = new DefaultObservable();
96

    
97
        private AbstractCommandsRecord commands;
98
        private FeatureTypeManager featureTypeManager;
99
        private FeatureManager featureManager;
100
        private SpatialManager spatialManager;
101

    
102
        private ArrayList resources = new ArrayList();
103

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

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

    
111
        private DefaultDataManager dataManager = null;
112

    
113
        private FeatureStoreProvider provider = null;
114

    
115
        private Logger logger = null;
116

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

    
126
        public DefaultFeatureStore() {
127

    
128
        }
129

    
130
        public DefaultFeatureStore(DefaultDataManager manager,
131
                        DataStoreParameters parameters, FeatureStoreProvider provider)
132
                        throws InitializeException {
133
                initialize(manager, parameters, provider);
134
        }
135

    
136
        public DefaultFeatureStore(DefaultDataManager manager, XMLEntity xmlEntity)
137
                        throws XMLException {
138
                this.dataManager = manager;
139
                this.setXMLEntity(xmlEntity);
140
        }
141

    
142
        private void initialize(DefaultDataManager manager,
143
                        DataStoreParameters parameters, FeatureStoreProvider provider)
144
                        throws InitializeException {
145
                this.dataManager = manager;
146
                this.provider = provider;
147
                this.parameters = parameters;
148
                this.provider.initialize(this);
149
        }
150

    
151
        public String getName() {
152
                return this.parameters.getDataStoreName();
153
        }
154

    
155
        public String getClassName() {
156
                return this.getClass().getName();
157
        }
158

    
159
        public DataStoreParameters getParameters() {
160
                return parameters;
161
        }
162

    
163
        public DefaultDataManager getManager() {
164
                return this.dataManager;
165
        }
166

    
167
        public Iterator getChilds() {
168
                return this.provider.getChilds();
169
        }
170

    
171
        public FeatureStoreProvider getProvider() {
172
                return this.provider;
173
        }
174

    
175
        public FeatureManager getFeatureManager() {
176
                return this.featureManager;
177
        }
178

    
179
        public void setFeatureTypes(List types, FeatureType defaultType) {
180
                this.featureTypes = types;
181
                this.defaultFeatureType = defaultType;
182
        }
183

    
184
        public void open() throws OpenException {
185
                // TODO: Se puede hacer un open estando en edicion ?
186
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
187
                this.provider.open();
188
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
189
        }
190

    
191
        public void refresh() throws OpenException, InitializeException {
192
                if (this.isEditing()) {
193
                        throw new IllegalStateException();
194
                }
195
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
196
                this.provider.refresh();
197
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
198
        }
199

    
200
        public void close() throws CloseException {
201
                // TODO: Se puede hacer un close estando en edicion ?
202
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
203
                this.provider.close();
204
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
205
        }
206

    
207
        public void dispose() throws CloseException {
208
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
209
                this.provider.dispose();
210
                if (this.selection != null) {
211
                        this.selection.dispose();
212
                        this.selection = null;
213
                }
214
                this.commands = null;
215

    
216
                if (this.locks != null) {
217
                        this.locks.dispose();
218
                        this.locks = null;
219
                }
220

    
221
                this.featureManager = null;
222
                this.spatialManager = null;
223
                this.removeAllResources();
224
                this.resources = null;
225

    
226
                this.parameters = null;
227
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
228
                this.observable.deleteObservers();
229
                this.observable = null;
230
        }
231

    
232
        public boolean allowWrite() {
233
                return this.provider.allowWrite();
234
        }
235

    
236
        public boolean canWriteGeometry(int geometryType) {
237
                return this.provider.canWriteGeometry(geometryType);
238
        }
239

    
240
        public DataExplorer getExplorer() throws ReadException {
241
                return this.provider.getExplorer();
242
        }
243

    
244
        public Metadata getMetadata() throws BaseException {
245
                // TODO:
246
                // Si el provider devuelbe null habria que ver de construir aqui
247
                // los metadatos basicos, como el Envelope y el SRS.
248
                return this.provider.getMetadata();
249
        }
250

    
251
        public Envelope getEnvelope() {
252
                return this.provider.getEnvelope();
253
        }
254

    
255
        public String getSRSDefaultGeometry() throws DataException {
256
                DefaultFeatureType type = (DefaultFeatureType) this
257
                                .getDefaultFeatureType();
258
                int index = type.getDefaultGeometryAttributeIndex();
259
                return type.getAttributeDescriptor(index).getSRS();
260
        }
261

    
262
        public FeatureLocks createDefaultFeatureLocks() throws DataException {
263
                return new DefaultFeatureLocks(this);
264
        }
265

    
266
        public FeatureSelection createDefaultFeatureSelection()
267
                        throws DataException {
268
                return new DefaultFeatureSelection(this);
269
        }
270

    
271
        public TemporaryContainer createDefaultTemporaryContainer()
272
                        throws DataException {
273
                return new MemoryTemporaryContainer();
274
        }
275

    
276
        public FeatureData createDefaultFeatureData(FeatureType type)
277
                        throws DataException {
278
                return new DefaultFeatureData(type);
279
        }
280

    
281
        //
282
        // ====================================================================
283
        // Persistencia
284
        // Interface IPersistence
285
        //
286

    
287
        public void setXMLEntity(XMLEntity xmlEntity) throws XMLException {
288
                if (this.provider != null) {
289
                        throw new XMLInitializeException("already initialized", this
290
                                        .getName());
291
                }
292
                if (this.getManager() == null) {
293
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
294
                }
295

    
296
                XMLEntity paramsXML = xmlEntity.firstChild("type", "parameters");
297
                if (paramsXML == null) {
298
                        throw new XMLInitializeException("parameters not found", this
299
                                        .getName());
300
                }
301
                FeatureStoreProvider provider ;
302
                DataStoreParameters params ;
303
                XMLEntity providerXML = xmlEntity.firstChild("type", "provider");
304
                try {
305
                        params = this.getManager().createDataStoreParameters(paramsXML);
306
                } catch (Exception e) {
307
                        throw new XMLInitializeException("can't create parameters", this
308
                                        .getName());
309
                }
310
                try {
311
                        Class providerClass = Class.forName(providerXML.getStringProperty("className"));
312
                        provider = (FeatureStoreProvider) providerClass.newInstance();
313
                } catch (Exception e) {
314
                        throw new XMLInitializeException(
315
                                        "can't create provider",
316
                                        this.getName()
317
                                );
318
                }
319
                provider.setXMLEntity(providerXML);
320

    
321
                try {
322
                        initialize(this.getManager(), params, provider);
323
                } catch (InitializeException e1) {
324
                        throw new XMLInitializeException("Initialize Exception", e1);
325
                }
326

    
327
                XMLEntity selectionXML = xmlEntity.firstChild("type", "selection");
328
                if (selectionXML != null) {
329
                        try {
330
                                selection = (DefaultFeatureSelection) createFeatureSelection();
331
                        } catch (Exception e) {
332
                                throw new XMLInitializeException("can't reload selection", this
333
                                                .getName());
334
                        }
335
                        selection.setXMLEntity(selectionXML);
336
                }
337

    
338
        }
339

    
340
        public XMLEntity getXMLEntity() throws XMLException {
341
                XMLEntity xml = new XMLEntity();
342
                xml.putProperty("dataStoreName", this.getName());
343
                xml.putProperty("className", this.getClassName());
344

    
345
                XMLEntity paramsXML = this.parameters.getXMLEntity();
346
                paramsXML.putProperty("type", "parameters");
347
                xml.addChild(paramsXML);
348

    
349
                XMLEntity providerXML = this.provider.getXMLEntity();
350
                providerXML.putProperty("className", this.provider.getClassName());
351
                providerXML.putProperty("type", "provider");
352
                xml.addChild(providerXML);
353

    
354
                XMLEntity selectionXML = this.selection.getXMLEntity();
355
                selectionXML.putProperty("type", "selection");
356
                xml.addChild(selectionXML);
357

    
358
                return xml;
359
        }
360

    
361
        //
362
        // ====================================================================
363
        // Gestion de la seleccion
364
        //
365

    
366
        private void setSelectionObserver() {
367
                if (this.selection instanceof Observable) {
368
                        Observable obSelection = this.selection;
369
                        obSelection.addObserver(this);
370
                }
371
        }
372

    
373
        private void unsetSelectionObserver() {
374
                if (this.selection instanceof Observable) {
375
                        Observable obSelection = this.selection;
376
                        obSelection.deleteObserver(this);
377
                }
378
        }
379

    
380
        public void setSelection(DataSet selection)
381
                        throws DataException {
382
                this.setSelection(selection);
383
        }
384

    
385
        public DataSet createSelection() throws DataException {
386
                return createFeatureSelection();
387
        }
388

    
389
        public DataSet getSelection() throws DataException {
390
                return this.getFeatureSelection();
391
        }
392

    
393
        public void setSelection(FeatureSet selection)
394
                        throws DataException {
395
                if (selection.equals(this.selection)) {
396
                        return;
397
                }
398
                if (!selection.isFromStore(this)) {
399
                        throw new SelectionNotAllowedException(getName());
400
                }
401
                this.unsetSelectionObserver();
402
                if (this.getSelection().getClass().isInstance(selection)) {
403
                        this.selection = (DefaultFeatureSelection) selection;
404
                } else {
405
                        this.selection = null;
406
                        this.getFeatureSelection().addAll(selection);
407
                }
408
                this.setSelectionObserver();
409
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
410
        }
411

    
412
        public FeatureSet createFeatureSelection() throws DataException {
413
                return this.provider.createFeatureSelection();
414
        }
415

    
416
        public FeatureSet getFeatureSelection() throws DataException {
417
                if (selection == null) {
418
                        this.selection = (DefaultFeatureSelection) createFeatureSelection();
419
                        this.setSelectionObserver();
420
                }
421
                return selection;
422
        }
423

    
424
        //
425
        // ====================================================================
426
        // Gestion de notificaciones
427
        //
428

    
429
        public void notifyChange(String notification) {
430
                this.observable.notifyObservers(this,
431
                                new DefaultFeatureStoreNotification(this, notification));
432

    
433
        }
434

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

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

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

    
452

    
453
        //
454
        // ====================================================================
455
        // Gestion de bloqueos
456
        //
457

    
458

    
459
        public FeatureSet getLocks() throws DataException {
460
                if (locks == null) {
461
                        this.locks = this.provider.createFeatureLocks();
462
                }
463
                return locks;
464
        }
465

    
466
        //
467
        // ====================================================================
468
        // Gestion de observers
469
        //
470

    
471
        public void disableNotifications() {
472
                this.observable.diableNotifications();
473

    
474
        }
475

    
476
        public void enableNotifications() {
477
                this.observable.enableNotifications();
478
        }
479

    
480
        public void beginComplexNotification() {
481
                this.observable.beginComplexNotification(new ComplexNotification());
482

    
483
        }
484

    
485
        public void endComplexNotification() {
486
                this.observable.endComplexNotification(this);
487

    
488
        }
489

    
490
        public void addObserver(Observer o) {
491
                this.observable.addObserver(o);
492

    
493
        }
494

    
495
        public void addObserver(Reference ref) {
496
                this.observable.addObserver(ref);
497
        }
498

    
499
        public void deleteObserver(Observer o) {
500
                this.observable.deleteObserver(o);
501
        }
502

    
503
        public void deleteObserver(Reference ref) {
504
                this.observable.deleteObserver(ref);
505
        }
506

    
507
        public void deleteObservers() {
508
                this.observable.deleteObservers();
509

    
510
        }
511

    
512
        //
513
        // ====================================================================
514
        // Interface Observer
515
        //
516
        // Usado para observar:
517
        // - su seleccion
518
        // - sus bloqueos
519
        // - sus recursos
520
        //
521

    
522
        public void update(Observable observable, Object notification) {
523
                if (notification instanceof ResourceNotification) {
524
                        if (((ResourceNotification) notification).getStore() == this) {
525
                                return;
526
                        }
527

    
528
                        if (((ResourceNotification) notification).getType().equals(
529
                                        ResourceNotification.CHANGED)) {
530
                                this.notifyChange(FeatureStoreNotification.RESOURCE_CHANGED);
531
                        }
532
                } else if (observable instanceof FeatureSet) {
533
                        if (observable == this.selection) {
534
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
535
                        } else if (observable == this.locks) {
536
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
537
                        }
538

    
539
                }
540
        }
541

    
542

    
543
        //
544
        // ====================================================================
545
        // Gestion de operaciones
546
        // Interface ExtendedOperations
547
        //
548
        public Object invokeOperation(int code, OperationContext context)
549
                        throws OperationException, OperationNotSupportedException {
550

    
551
                return this.getManager().invokeDataStoreOperation(this, code, context);
552
        }
553

    
554
        public Object invokeOperation(String name, OperationContext context)
555
                        throws OperationException, OperationNotSupportedException {
556
                return this.getManager().invokeDataStoreOperation(this, name, context);
557
        }
558

    
559
        public boolean implementsOperation(int code) {
560
                return this.getManager().implementsDataStoreOperation(this.getName(),
561
                                code);
562
        }
563

    
564
        public boolean implementsOperation(String name) {
565
                return this.getManager().implementsDataStoreOperation(this.getName(),
566
                                name);
567
        }
568

    
569
        // TODO: Y la implementacion de esto ?
570

    
571
        public Object getOperation(int code) throws OperationException {
572
                return null;
573
        }
574

    
575
        public Object getOperation(String name) throws OperationException {
576
                return null;
577
        }
578

    
579
        //
580
        // ====================================================================
581
        // Edicion
582
        //
583

    
584
        private void newVersionOfUpdate() {
585
                this.versionOfUpdate++;
586
        }
587

    
588
        private long currentVersionOfUpdate() {
589
                return this.versionOfUpdate;
590
        }
591

    
592
        private void checkInEditingMode()
593
                        throws NeedEditingModeException {
594
                if (!editingMode) {
595
                        throw new NeedEditingModeException(this.getName());
596
                }
597
        }
598

    
599
        private void checkIsOwnFeature(Feature feature)
600
                        throws FeatureNotAllowedForThisStoreException {
601
                if (((DefaultFeature) feature).getStore() != this) {
602
                        throw new FeatureNotAllowedForThisStoreException(this.getName());
603
                }
604
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
605
                // fixFeatureType((DefaultFeatureType) feature.getType());
606
        }
607

    
608
        private void exitEditingMode() {
609
                commands.clear();
610
                featureManager = null;
611
                spatialManager = null;
612
                featureTypeManager = null;
613
                commands = null;
614

    
615
                editingMode = false;
616
                hasStrongChanges = true; // Lo deja a true por si las moscas
617
        }
618

    
619
        synchronized public void edit() throws DataException {
620
                try {
621
                        if (isEditing()) {
622
                                throw new AlreadyEditingException(this.getName());
623
                        }
624
                        notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
625

    
626
                        featureManager = new FeatureManager(this.provider
627
                                        .createTemporaryContainer());
628
                        featureTypeManager = new FeatureTypeManager(this.provider
629
                                        .createTemporaryContainer());
630
                        spatialManager = new SpatialManager();
631

    
632
                        commands = new FeatureCommandsRecord(featureManager,
633
                                        spatialManager, featureTypeManager);
634
                        editingMode = true;
635
                        hasStrongChanges = false;
636
                        notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
637
                } catch (Exception e) {
638
                        throw new StoreEditException(e, this.getName());
639
                }
640
        }
641

    
642
        public boolean isEditing() {
643
                return editingMode;
644
        }
645

    
646
        synchronized public void update(EditableFeatureType type)
647
                        throws DataException {
648
                try {
649
                        checkInEditingMode();
650
                        if (type == null) {
651
                                throw new NullFeatureTypeException(getName());
652
                        }
653
                        // FIXME: Comprobar que es un featureType aceptable.
654
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
655
                        newVersionOfUpdate();
656

    
657
                        FeatureType oldt = type.getSource().getCopy();
658
                        FeatureType newt = type.getNotEditableCopy();
659
                        commands.update(newt, oldt);
660

    
661
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
662
                                hasStrongChanges = true;
663
                        }
664
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
665
                } catch (Exception e) {
666
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
667
                }
668
        }
669

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

    
687
        private static EditableFeature lastChangedFeature = null;
688

    
689
        synchronized public void insert(EditableFeature feature)
690
                        throws DataException {
691
                try {
692
                        checkInEditingMode();
693
                        checkIsOwnFeature(feature);
694
                        if (feature.getSource() != null) {
695
                                throw new NoNewFeatureInsertException(this.getName());
696
                        }
697
                        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
698
                        newVersionOfUpdate();
699
                        if (lastChangedFeature.getSource() != feature.getSource()) {
700
                                lastChangedFeature = feature;
701
                                feature.validate(Feature.UPDATE);
702
                                lastChangedFeature = null;
703
                        }
704
                        commands.insert(feature.getNotEditableCopy());
705
                        hasStrongChanges = true;
706
                        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
707
                } catch (Exception e) {
708
                        throw new StoreInsertFeatureException(e, this.getName());
709
                }
710
        }
711

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

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

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

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

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

    
768
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
769
                checkInEditingMode();
770
                return commands;
771
        }
772

    
773
        synchronized public void cancelEditing() throws DataException {
774
                try {
775
                        checkInEditingMode();
776
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
777
                        exitEditingMode();
778
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
779
                } catch (Exception e) {
780
                        throw new StoreCancelEditingException(e, this.getName());
781
                }
782
        }
783

    
784
        synchronized public void finishEditing() throws DataException {
785
                try {
786
                        checkInEditingMode();
787
                        if (!hasStrongChanges) {
788
                                performLightEditing();
789
                                return;
790
                        }
791
                        if (!this.allowWrite()) {
792
                                throw new WriteNotAllowedException(getName());
793
                        }
794

    
795
                        notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
796
                        validateFeatures(Feature.FINISH_EDITING);
797
                        provider.performEditing();
798
                        exitEditingMode();
799
                        notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
800
                } catch (Exception e) {
801
                        throw new FinishEditingException(e);
802
                }
803
        }
804

    
805
        private void performLightEditing() throws DataException {
806
                throw new UnsupportedOperationException(
807
                                "lightFinishEdition not yet implemented");
808

    
809
                // TODO: implementar
810
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
811
                // exitEditingMode();
812
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
813
        }
814

    
815
        public void export(FeatureExplorer explorer, DataStoreParameters params)
816
                        throws DataException {
817

    
818
                if (this.getFeatureTypes().size() != 1) {
819
                        throw new UnsupportedOperationException(
820
                                        "export whith more than one type not yet implemented");
821
                }
822
                try {
823
                        FeatureType type = this.getDefaultFeatureType();
824
                        explorer.add(params, type);
825

    
826
                        DataManager manager = DALLocator.getDataManager();
827
                        FeatureStore target = (FeatureStore) manager
828
                                        .createDataStore(params);
829
                        target.edit();
830

    
831
                        FeatureSet features = this.getFeatureSet();
832
                        Iterator it1 = features.iterator();
833
                        while (it1.hasNext()) {
834
                                Feature feature = (Feature) it1.next();
835
                                target.insert(target.createFeature(type, feature));
836
                        }
837
                        features.dispose();
838
                        target.finishEditing();
839
                        target.dispose();
840
                } catch (Exception e) {
841
                        throw new DataExportException(e, params.toString());
842
                }
843
        }
844

    
845
        //
846
        // ====================================================================
847
        // Obtencion de datos
848
        // getDataCollection, getFeatureCollection
849
        //
850

    
851
        public DataSet getDataSet() throws DataException {
852
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
853
                return new DefaultFeatureSet(this, query);
854
        }
855

    
856
        public DataSet getDataSet(DataQuery dataQuery)
857
                        throws DataException {
858
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
859
        }
860

    
861
        public void getDataSet(Observer observer) throws DataException {
862
                this.getFeatureSet(null, observer);
863
        }
864

    
865
        public void getDataSet(DataQuery dataQuery, Observer observer)
866
                        throws DataException {
867
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
868
        }
869

    
870
        public FeatureSet getFeatureSet() throws DataException {
871
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
872
                return new DefaultFeatureSet(this, query);
873
        }
874

    
875
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
876
                        throws DataException {
877
                fixFeatureQuery(featureQuery);
878
                return new DefaultFeatureSet(this, featureQuery);
879
        }
880

    
881
        private void fixFeatureQuery(FeatureQuery featureQuery)
882
                        throws DataException {
883
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
884
                if (featureQuery.getAttributeNames() != null){
885
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
886
                                        .getFeatureType();
887
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
888
                                        .getAttributeNames()));
889
                }
890
        }
891

    
892
        public void getFeatureSet(Observer observer)
893
                        throws DataException {
894
                this.getFeatureSet(null, observer);
895
        }
896

    
897
        public void getFeatureSet(FeatureQuery query, Observer observer)
898
                        throws DataException {
899
                class LoadInBackGround implements Runnable {
900
                        private FeatureStore store;
901
                        private FeatureQuery query;
902
                        private Observer observer;
903

    
904
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
905
                                        Observer observer) {
906
                                this.store = store;
907
                                this.query = query;
908
                                this.observer = observer;
909
                        }
910

    
911
                        public void run() {
912
                                try {
913
                                        FeatureSet collection = store.getFeatureSet(query);
914
                                        observer.update(
915
                                                        store,
916
                                                        new DefaultFeatureStoreNotification(
917
                                                                        store,
918
                                                                        FeatureStoreNotification.LOAD_FINISHED,
919
                                                                        collection
920
                                                                )
921
                                                );
922
                                } catch (Exception e) {
923
                                        observer.update(
924
                                                        store,
925
                                                        new DefaultFeatureStoreNotification(
926
                                                                        store,
927
                                                                        FeatureStoreNotification.LOAD_FINISHED,
928
                                                                        e
929
                                                                )
930
                                                );
931
                                }
932
                        }
933
                }
934

    
935
                if (query == null) {
936
                        query = new FeatureQuery(this.getDefaultFeatureType());
937
                }
938
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
939
                Thread thread = new Thread(task);
940
                thread.run();
941
        }
942

    
943
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
944
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
945
        }
946

    
947
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
948
                        throws DataException {
949
                featureType = fixFeatureType((DefaultFeatureType) featureType);
950
                // TODO comprobar que el id es de este store
951

    
952
                if (this.editingMode) {
953
                        if (featureManager.contains(reference)) {
954
                                return featureManager.getFeature(reference, this, featureType);
955
                        }
956
                }
957
                return this.createFeature(featureType, this.provider
958
                                .getFeatureDataByReference(reference, featureType));
959
        }
960

    
961
        //
962
        // ====================================================================
963
        // Gestion de features
964
        //
965

    
966
        private FeatureType fixFeatureType(DefaultFeatureType type)
967
                        throws DataException {
968
                FeatureType defaultType = this.getDefaultFeatureType();
969
                if (type == null || type.equals(defaultType)) {
970
                        return defaultType;
971
                }
972
                if (type.isSubtypeOf(defaultType)) {
973
                        return type;
974
                }
975
                Iterator iter = this.getFeatureTypes().iterator();
976
                FeatureType tmpType;
977
                while (iter.hasNext()) {
978
                        tmpType = (FeatureType) iter.next();
979
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
980
                                return type;
981
                        }
982

    
983
                }
984
                throw new FeatureTypeNotAllowedForThisStoreException(getName());
985
        }
986

    
987
        public void validateFeatures(int mode) throws DataException {
988
                try {
989
                        FeatureSet collection = this.getFeatureSet();
990
                        Iterator iter = collection.iterator();
991
                        long previousVersionOfUpdate = currentVersionOfUpdate();
992
                        while (iter.hasNext()) {
993
                                ((DefaultFeature) iter.next()).validate(mode);
994
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
995
                                        throw new ConcurrentDataModificationException(getName());
996
                                }
997
                        }
998
                } catch (Exception e) {
999
                        throw new ValidateFeaturesException(e, getName());
1000
                }
1001
        }
1002

    
1003
        public FeatureType getDefaultFeatureType() throws DataException {
1004
                try {
1005
                        if (isEditing()) {
1006
                                return featureTypeManager.getFeatureType();
1007
                        }
1008
                        return defaultFeatureType;
1009
                } catch (Exception e) {
1010
                        throw new GetFeatureTypeException(e, getName());
1011
                }
1012
        }
1013

    
1014
        public List getFeatureTypes() throws DataException {
1015
                try {
1016
                        List types;
1017
                        if (isEditing()) {
1018
                                types = featureTypeManager.getFeatureTypes();
1019
                        } else {
1020
                                types = featureTypes;
1021
                        }
1022
                        return Collections.unmodifiableList(types);
1023
                } catch (Exception e) {
1024
                        throw new GetFeatureTypeException(e, getName());
1025
                }
1026
        }
1027

    
1028
        public Feature createFeature(FeatureData data)
1029
                        throws DataException {
1030
                DefaultFeature feature = new DefaultFeature(this, data);
1031
                return feature;
1032
        }
1033

    
1034
        /**
1035
         * @deprecated
1036
         */
1037
        public Feature createFeature(FeatureType type, FeatureData data)
1038
                        throws DataException {
1039
                // FIXME: falta por implementar
1040
                // Comprobar si es un subtipo del feature de data
1041
                // y construir un feature usando el subtipo.
1042
                // Probablemente requiera generar una copia del data.
1043
                return null;
1044
        }
1045

    
1046
        public EditableFeature createFeature(FeatureType type,
1047
                        Feature defaultValues)
1048
                        throws DataException {
1049
                try {
1050
                        type = this.fixFeatureType((DefaultFeatureType) type);
1051
                        FeatureData data = this.provider.createFeatureData(type);
1052
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1053
                                        data);
1054
                        feature.initializeValues(defaultValues);
1055
                        return feature;
1056
                } catch (Exception e) {
1057
                        throw new CreateFeatureException(e, getName());
1058
                }
1059
        }
1060

    
1061
        public EditableFeature createFeature(FeatureType type,
1062
                        boolean defaultValues)
1063
                        throws DataException {
1064
                try {
1065
                        type = this.fixFeatureType((DefaultFeatureType) type);
1066
                        FeatureData data = this.provider.createFeatureData(type);
1067
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1068
                                        data);
1069
                        if (defaultValues) {
1070
                                feature.initializeValues();
1071
                        }
1072
                        return feature;
1073
                } catch (Exception e) {
1074
                        throw new CreateFeatureException(e, getName());
1075
                }
1076
        }
1077

    
1078
        public EditableFeature createFeature(boolean defaultValues)
1079
                        throws DataException {
1080
                return this.createFeature(this.getDefaultFeatureType(), defaultValues);
1081
        }
1082

    
1083
        public EditableFeature createFeature() throws DataException {
1084
                return this.createFeature(this.getDefaultFeatureType(), true);
1085
        }
1086

    
1087
        public Index createIndex(FeatureType type,
1088
                        String colName) throws IndexException {
1089
                // TODO Auto-generated method stub
1090
                return null;
1091
        }
1092

    
1093
        public boolean hasIndex(FeatureType type, String attributeName) {
1094
                // TODO Auto-generated method stub
1095
                return false;
1096
        }
1097

    
1098
        public EditableFeatureType createFeatureType() {
1099
                return new DefaultEditableFeatureType();
1100
        }
1101

    
1102
        public boolean isLocksSupported() {
1103
                return this.provider.isLocksSupported();
1104
        }
1105

    
1106
        public Logger getLogger() {
1107
                if (this.logger == null) {
1108
                        this.logger = LoggerFactory.getLogger(this.getClass());
1109
                }
1110
                return this.logger;
1111
        }
1112
}