Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_data / src / org / gvsig / fmap / data / feature / impl / DefaultFeatureStore.java @ 24019

History | View | Annotate | Download (32.7 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.ProviderNotRegisteredException;
21
import org.gvsig.fmap.data.exceptions.ReadException;
22
import org.gvsig.fmap.data.feature.Command;
23
import org.gvsig.fmap.data.feature.CommandsRecord;
24
import org.gvsig.fmap.data.feature.EditableFeature;
25
import org.gvsig.fmap.data.feature.EditableFeatureType;
26
import org.gvsig.fmap.data.feature.Feature;
27
import org.gvsig.fmap.data.feature.FeatureExplorer;
28
import org.gvsig.fmap.data.feature.FeatureIndex;
29
import org.gvsig.fmap.data.feature.FeatureIndexes;
30
import org.gvsig.fmap.data.feature.FeatureQuery;
31
import org.gvsig.fmap.data.feature.FeatureReference;
32
import org.gvsig.fmap.data.feature.FeatureSelection;
33
import org.gvsig.fmap.data.feature.FeatureSet;
34
import org.gvsig.fmap.data.feature.FeatureStore;
35
import org.gvsig.fmap.data.feature.FeatureStoreNotification;
36
import org.gvsig.fmap.data.feature.FeatureStoreParameters;
37
import org.gvsig.fmap.data.feature.FeatureType;
38
import org.gvsig.fmap.data.feature.exceptions.AlreadyEditingException;
39
import org.gvsig.fmap.data.feature.exceptions.ConcurrentDataModificationException;
40
import org.gvsig.fmap.data.feature.exceptions.CreateFeatureException;
41
import org.gvsig.fmap.data.feature.exceptions.DataExportException;
42
import org.gvsig.fmap.data.feature.exceptions.DataIndexException;
43
import org.gvsig.fmap.data.feature.exceptions.FinishEditingException;
44
import org.gvsig.fmap.data.feature.exceptions.GetFeatureTypeException;
45
import org.gvsig.fmap.data.feature.exceptions.IllegalFeatureException;
46
import org.gvsig.fmap.data.feature.exceptions.IllegalFeatureTypeException;
47
import org.gvsig.fmap.data.feature.exceptions.NeedEditingModeException;
48
import org.gvsig.fmap.data.feature.exceptions.NoNewFeatureInsertException;
49
import org.gvsig.fmap.data.feature.exceptions.NullFeatureTypeException;
50
import org.gvsig.fmap.data.feature.exceptions.SelectionNotAllowedException;
51
import org.gvsig.fmap.data.feature.exceptions.StoreCancelEditingException;
52
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteEditableFeatureException;
53
import org.gvsig.fmap.data.feature.exceptions.StoreDeleteFeatureException;
54
import org.gvsig.fmap.data.feature.exceptions.StoreEditException;
55
import org.gvsig.fmap.data.feature.exceptions.StoreInsertFeatureException;
56
import org.gvsig.fmap.data.feature.exceptions.StoreRedoException;
57
import org.gvsig.fmap.data.feature.exceptions.StoreUndoException;
58
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureException;
59
import org.gvsig.fmap.data.feature.exceptions.StoreUpdateFeatureTypeException;
60
import org.gvsig.fmap.data.feature.exceptions.ValidateFeaturesException;
61
import org.gvsig.fmap.data.feature.exceptions.WriteNotAllowedException;
62
import org.gvsig.fmap.data.feature.exceptions.XMLInitializeException;
63
import org.gvsig.fmap.data.feature.impl.commands.AbstractCommandsRecord;
64
import org.gvsig.fmap.data.feature.impl.commands.implementation.FeatureCommandsRecord;
65
import org.gvsig.fmap.data.feature.impl.featureSet.DefaultFeatureSet;
66
import org.gvsig.fmap.data.feature.spi.DefaultFeatureData;
67
import org.gvsig.fmap.data.feature.spi.FeatureData;
68
import org.gvsig.fmap.data.feature.spi.FeatureLocks;
69
import org.gvsig.fmap.data.feature.spi.FeatureStoreProvider;
70
import org.gvsig.fmap.data.feature.spi.FeatureStoreProviderServices;
71
import org.gvsig.fmap.data.feature.spi.index.FeatureIndexProviderServices;
72
import org.gvsig.fmap.data.impl.DefaultDataManager;
73
import org.gvsig.fmap.geom.primitive.Envelope;
74
import org.gvsig.metadata.Metadata;
75
import org.gvsig.tools.exception.BaseException;
76
import org.gvsig.tools.observer.ComplexNotification;
77
import org.gvsig.tools.observer.DefaultObservable;
78
import org.gvsig.tools.observer.Observable;
79
import org.gvsig.tools.observer.Observer;
80
import org.gvsig.tools.operations.OperationContext;
81
import org.gvsig.tools.operations.OperationException;
82
import org.gvsig.tools.operations.OperationNotSupportedException;
83
import org.slf4j.Logger;
84
import org.slf4j.LoggerFactory;
85

    
86
import com.iver.utiles.XMLEntity;
87
import com.iver.utiles.XMLException;
88

    
89
final public class DefaultFeatureStore implements
90
                FeatureStoreProviderServices,
91
                Observer /* , Persistent */{
92

    
93
        private DataStoreParameters parameters = null;
94
        private FeatureSelection selection;
95
        private FeatureLocks locks;
96

    
97
        private DefaultObservable observable = new DefaultObservable();
98

    
99
        private AbstractCommandsRecord commands;
100
        private FeatureTypeManager featureTypeManager;
101
        private FeatureManager featureManager;
102
        private SpatialManager spatialManager;
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 DefaultFeatureIndexes indexes;
116

    
117
        private Logger logger = null;
118

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

    
128
        public DefaultFeatureStore() {
129

    
130
        }
131

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

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

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

    
153
        public String getName() {
154
                return this.parameters.getDataStoreName();
155
        }
156

    
157
        public String getClassName() {
158
                return this.getClass().getName();
159
        }
160

    
161
        public DataStoreParameters getParameters() {
162
                return parameters;
163
        }
164

    
165
        public DefaultDataManager getManager() {
166
                return this.dataManager;
167
        }
168

    
169
        public Iterator getChilds() {
170
                return this.provider.getChilds();
171
        }
172

    
173
        public FeatureStoreProvider getProvider() {
174
                return this.provider;
175
        }
176

    
177
        public FeatureManager getFeatureManager() {
178
                return this.featureManager;
179
        }
180

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

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

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

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

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

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

    
223
                this.featureManager = null;
224
                this.spatialManager = 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 FeatureIndexes getIndexes() {
256
                return this.indexes;
257
        }
258

    
259
        public String getSRSDefaultGeometry() throws DataException {
260
                DefaultFeatureType type = (DefaultFeatureType) this
261
                                .getDefaultFeatureType();
262
                int index = type.getDefaultGeometryAttributeIndex();
263
                return type.getAttributeDescriptor(index).getSRS();
264
        }
265

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

    
271
        public FeatureData createDefaultFeatureData(FeatureType type)
272
                        throws DataException {
273
                return new DefaultFeatureData(type);
274
        }
275

    
276
        //
277
        // ====================================================================
278
        // Persistencia
279
        // Interface IPersistence
280
        //
281

    
282
        public void setXMLEntity(XMLEntity xmlEntity) throws XMLException {
283
                if (this.provider != null) {
284
                        throw new XMLInitializeException("already initialized", this
285
                                        .getName());
286
                }
287
                if (this.getManager() == null) {
288
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
289
                }
290

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

    
316
                try {
317
                        initialize(this.getManager(), params, provider);
318
                } catch (InitializeException e1) {
319
                        throw new XMLInitializeException("Initialize Exception", e1);
320
                }
321

    
322
                XMLEntity selectionXML = xmlEntity.firstChild("type", "selection");
323
                if (selectionXML != null) {
324
                        try {
325
                                selection = createFeatureSelection();
326
                        } catch (Exception e) {
327
                                throw new XMLInitializeException("can't reload selection", this
328
                                                .getName());
329
                        }
330
                        selection.setXMLEntity(selectionXML);
331
                }
332

    
333
        }
334

    
335
        public XMLEntity getXMLEntity() throws XMLException {
336
                XMLEntity xml = new XMLEntity();
337
                xml.putProperty("dataStoreName", this.getName());
338
                xml.putProperty("className", this.getClassName());
339

    
340
                XMLEntity paramsXML = this.parameters.getXMLEntity();
341
                paramsXML.putProperty("type", "parameters");
342
                xml.addChild(paramsXML);
343

    
344
                XMLEntity providerXML = this.provider.getXMLEntity();
345
                providerXML.putProperty("className", this.provider.getClassName());
346
                providerXML.putProperty("type", "provider");
347
                xml.addChild(providerXML);
348

    
349
                XMLEntity selectionXML = this.selection.getXMLEntity();
350
                selectionXML.putProperty("type", "selection");
351
                xml.addChild(selectionXML);
352

    
353
                return xml;
354
        }
355

    
356
        /*
357

358
        public void getState(PersistentState state) throws PersistenceException {
359
                state.setTheClass(this);
360
                state.set("dataStoreName", this.getName());
361
                state.set("parameters", this.parameters);
362
                state.set("provider", this.provider);
363
                state.set("selection", this.selection);
364
        }
365

366
        public void setState(PersistentState state) throws PersistenceException {
367
                if (this.provider != null) {
368
                        throw new PersistenceException(null);
369
                }
370
                if (this.getManager() == null) {
371
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
372
                }
373

374
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
375
                FeatureStoreProvider provider = (FeatureStoreProvider) state.get("provider");
376

377
                initialize(this.getManager(), params, provider);
378

379
                setSelection((FeatureSelection) state.get("selection"));
380
        }
381
        */
382

    
383
        //
384
        // ====================================================================
385
        // Gestion de la seleccion
386
        //
387

    
388
        public void setSelection(DataSet selection)
389
                        throws DataException {
390
                this.setSelection((FeatureSet) selection);
391
        }
392

    
393
        public DataSet createSelection() throws DataException {
394
                return createFeatureSelection();
395
        }
396

    
397
        public DataSet getSelection() throws DataException {
398
                return this.getFeatureSelection();
399
        }
400

    
401
        public void setSelection(FeatureSet selection)
402
                        throws DataException {
403
                if (selection.equals(this.selection)) {
404
                        return;
405
                }
406
                if (!selection.isFromStore(this)) {
407
                        throw new SelectionNotAllowedException(getName());
408
                }
409

    
410
                this.selection.deleteObserver(this);
411
                if (selection instanceof FeatureSelection) {
412
                        this.selection = (FeatureSelection) selection;
413
                } else {
414
                        this.selection.deselectAll();
415
                        this.selection.select(selection);
416
                }
417
                this.selection.addObserver(this);
418

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

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

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

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

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

    
443
        }
444

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

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

    
457
        public void notifyChange(String notification, EditableFeatureType type) {
458
                this.observable.notifyObservers(this,
459
                                new DefaultFeatureStoreNotification(this, notification, type));
460
        }
461

    
462

    
463
        //
464
        // ====================================================================
465
        // Gestion de bloqueos
466
        //
467

    
468

    
469
        public FeatureSet getLocks() throws DataException {
470
                if (!this.provider.isLocksSupported()) {
471
                        getLogger().warn("Locks not supporteds");
472
                        return null;
473
                }
474
                if (locks == null) {
475
                        this.locks = this.provider.createFeatureLocks();
476
                }
477
                return locks;
478
        }
479

    
480
        //
481
        // ====================================================================
482
        // Gestion de observers
483
        //
484

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

    
488
        }
489

    
490
        public void enableNotifications() {
491
                this.observable.enableNotifications();
492
        }
493

    
494
        public void beginComplexNotification() {
495
                this.observable.beginComplexNotification(new ComplexNotification());
496

    
497
        }
498

    
499
        public void endComplexNotification() {
500
                this.observable.endComplexNotification(this);
501

    
502
        }
503

    
504
        public void addObserver(Observer o) {
505
                this.observable.addObserver(o);
506

    
507
        }
508

    
509
        public void addObserver(Reference ref) {
510
                this.observable.addObserver(ref);
511
        }
512

    
513
        public void deleteObserver(Observer o) {
514
                this.observable.deleteObserver(o);
515
        }
516

    
517
        public void deleteObserver(Reference ref) {
518
                this.observable.deleteObserver(ref);
519
        }
520

    
521
        public void deleteObservers() {
522
                this.observable.deleteObservers();
523

    
524
        }
525

    
526
        //
527
        // ====================================================================
528
        // Interface Observer
529
        //
530
        // Usado para observar:
531
        // - su seleccion
532
        // - sus bloqueos
533
        // - sus recursos
534
        //
535

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

    
544
                }
545
        }
546

    
547

    
548
        //
549
        // ====================================================================
550
        // Gestion de operaciones
551
        // Interface ExtendedOperations
552
        //
553
        public Object invokeOperation(int code, OperationContext context)
554
                        throws OperationException, OperationNotSupportedException {
555

    
556
                return this.getManager().invokeDataStoreOperation(this, code, context);
557
        }
558

    
559
        public Object invokeOperation(String name, OperationContext context)
560
                        throws OperationException, OperationNotSupportedException {
561
                return this.getManager().invokeDataStoreOperation(this, name, context);
562
        }
563

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

    
569
        public boolean implementsOperation(String name) {
570
                return this.getManager().implementsDataStoreOperation(this.getName(),
571
                                name);
572
        }
573

    
574
        // TODO: Y la implementacion de esto ?
575

    
576
        public Object getOperation(int code) throws OperationException {
577
                return null;
578
        }
579

    
580
        public Object getOperation(String name) throws OperationException {
581
                return null;
582
        }
583

    
584
        //
585
        // ====================================================================
586
        // Edicion
587
        //
588

    
589
        private void newVersionOfUpdate() {
590
                this.versionOfUpdate++;
591
        }
592

    
593
        private long currentVersionOfUpdate() {
594
                return this.versionOfUpdate;
595
        }
596

    
597
        private void checkInEditingMode()
598
                        throws NeedEditingModeException {
599
                if (!editingMode) {
600
                        throw new NeedEditingModeException(this.getName());
601
                }
602
        }
603

    
604
        private void checkIsOwnFeature(Feature feature)
605
                        throws IllegalFeatureException {
606
                if (((DefaultFeature) feature).getStore() != this) {
607
                        throw new IllegalFeatureException(this.getName());
608
                }
609
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
610
                // fixFeatureType((DefaultFeatureType) feature.getType());
611
        }
612

    
613
        private void exitEditingMode() {
614
                commands.clear();
615
                featureManager = null;
616
                spatialManager = null;
617
                featureTypeManager = null;
618
                commands = null;
619

    
620
                editingMode = false;
621
                hasStrongChanges = true; // Lo deja a true por si las moscas
622
        }
623

    
624
        synchronized public void edit() throws DataException {
625
                try {
626
                        if (isEditing()) {
627
                                throw new AlreadyEditingException(this.getName());
628
                        }
629
                        notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
630

    
631
                        featureManager = new FeatureManager(this.provider
632
                                        .createTemporaryContainer());
633
                        featureTypeManager = new FeatureTypeManager(this.provider
634
                                        .createTemporaryContainer());
635
                        spatialManager = new SpatialManager();
636

    
637
                        commands = new FeatureCommandsRecord(featureManager,
638
                                        spatialManager, featureTypeManager);
639
                        editingMode = true;
640
                        hasStrongChanges = false;
641
                        notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
642
                } catch (Exception e) {
643
                        throw new StoreEditException(e, this.getName());
644
                }
645
        }
646

    
647
        public boolean isEditing() {
648
                return editingMode;
649
        }
650

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

    
662
                        FeatureType oldt = type.getSource().getCopy();
663
                        FeatureType newt = type.getNotEditableCopy();
664
                        commands.update(newt, oldt);
665

    
666
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
667
                                hasStrongChanges = true;
668
                        }
669
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
670
                } catch (Exception e) {
671
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
672
                }
673
        }
674

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

    
692
        private static EditableFeature lastChangedFeature = null;
693

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

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

    
734
                        Feature oldf = feature.getSource();
735
                        Feature newf = feature.getNotEditableCopy();
736
                        commands.update(newf, oldf);
737

    
738
                        hasStrongChanges = true;
739
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
740
                } catch (Exception e) {
741
                        throw new StoreUpdateFeatureException(e, this.getName());
742
                }
743
        }
744

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

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

    
773
        synchronized public CommandsRecord getCommandsRecord() throws DataException {
774
                checkInEditingMode();
775
                return commands;
776
        }
777

    
778
        synchronized public void cancelEditing() throws DataException {
779
                try {
780
                        checkInEditingMode();
781
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
782
                        exitEditingMode();
783
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
784
                } catch (Exception e) {
785
                        throw new StoreCancelEditingException(e, this.getName());
786
                }
787
        }
788

    
789
        synchronized public void finishEditing() throws DataException {
790
                try {
791
                        checkInEditingMode();
792
                        if (!hasStrongChanges) {
793
                                performLightEditing();
794
                                return;
795
                        }
796
                        if (!this.allowWrite()) {
797
                                throw new WriteNotAllowedException(getName());
798
                        }
799

    
800
                        notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
801
                        validateFeatures(Feature.FINISH_EDITING);
802
                        provider.performEditing();
803
                        exitEditingMode();
804
                        notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
805
                } catch (Exception e) {
806
                        throw new FinishEditingException(e);
807
                }
808
        }
809

    
810
        private void performLightEditing() throws DataException {
811
                throw new UnsupportedOperationException(
812
                                "lightFinishEdition not yet implemented");
813

    
814
                // TODO: implementar
815
                // notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
816
                // exitEditingMode();
817
                // notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
818
        }
819

    
820
        public void export(FeatureExplorer explorer, FeatureStoreParameters params)
821
                        throws DataException {
822

    
823
                if (this.getFeatureTypes().size() != 1) {
824
                        throw new UnsupportedOperationException(
825
                                        "export whith more than one type not yet implemented");
826
                }
827
                try {
828
                        FeatureType type = this.getDefaultFeatureType();
829
                        params.setDefaultFeatureType(type);
830
                        explorer.add(params);
831

    
832
                        DataManager manager = DALLocator.getDataManager();
833
                        FeatureStore target = (FeatureStore) manager
834
                                        .createDataStore(params);
835
                        target.edit();
836

    
837
                        FeatureSet features = this.getFeatureSet();
838
                        Iterator it1 = features.iterator();
839
                        while (it1.hasNext()) {
840
                                Feature feature = (Feature) it1.next();
841
                                target.insert(target.createFeature(type, feature));
842
                        }
843
                        features.dispose();
844
                        target.finishEditing();
845
                        target.dispose();
846
                } catch (Exception e) {
847
                        throw new DataExportException(e, params.toString());
848
                }
849
        }
850

    
851
        //
852
        // ====================================================================
853
        // Obtencion de datos
854
        // getDataCollection, getFeatureCollection
855
        //
856

    
857
        public DataSet getDataSet() throws DataException {
858
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
859
                return new DefaultFeatureSet(this, query);
860
        }
861

    
862
        public DataSet getDataSet(DataQuery dataQuery)
863
                        throws DataException {
864
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
865
        }
866

    
867
        public void getDataSet(Observer observer) throws DataException {
868
                this.getFeatureSet(null, observer);
869
        }
870

    
871
        public void getDataSet(DataQuery dataQuery, Observer observer)
872
                        throws DataException {
873
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
874
        }
875

    
876
        public FeatureSet getFeatureSet() throws DataException {
877
                FeatureQuery query = new FeatureQuery(this.getDefaultFeatureType());
878
                return new DefaultFeatureSet(this, query);
879
        }
880

    
881
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
882
                        throws DataException {
883
                fixFeatureQuery(featureQuery);
884
                return new DefaultFeatureSet(this, featureQuery);
885
        }
886

    
887
        private void fixFeatureQuery(FeatureQuery featureQuery)
888
                        throws DataException {
889
                featureQuery.setFeatureType(this.fixFeatureType((DefaultFeatureType) featureQuery.getFeatureType()));
890
                if (featureQuery.getAttributeNames() != null){
891
                        DefaultFeatureType originalType = (DefaultFeatureType) featureQuery
892
                                        .getFeatureType();
893
                        featureQuery.setFeatureType(originalType.getSubtype(featureQuery
894
                                        .getAttributeNames()));
895
                }
896
        }
897

    
898
        public void getFeatureSet(Observer observer)
899
                        throws DataException {
900
                this.getFeatureSet(null, observer);
901
        }
902

    
903
        public void getFeatureSet(FeatureQuery query, Observer observer)
904
                        throws DataException {
905
                class LoadInBackGround implements Runnable {
906
                        private FeatureStore store;
907
                        private FeatureQuery query;
908
                        private Observer observer;
909

    
910
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
911
                                        Observer observer) {
912
                                this.store = store;
913
                                this.query = query;
914
                                this.observer = observer;
915
                        }
916

    
917
                        public void run() {
918
                                try {
919
                                        FeatureSet collection = store.getFeatureSet(query);
920
                                        observer.update(
921
                                                        store,
922
                                                        new DefaultFeatureStoreNotification(
923
                                                                        store,
924
                                                                        FeatureStoreNotification.LOAD_FINISHED,
925
                                                                        collection
926
                                                                )
927
                                                );
928
                                } catch (Exception e) {
929
                                        observer.update(
930
                                                        store,
931
                                                        new DefaultFeatureStoreNotification(
932
                                                                        store,
933
                                                                        FeatureStoreNotification.LOAD_FINISHED,
934
                                                                        e
935
                                                                )
936
                                                );
937
                                }
938
                        }
939
                }
940

    
941
                if (query == null) {
942
                        query = new FeatureQuery(this.getDefaultFeatureType());
943
                }
944
                LoadInBackGround task = new LoadInBackGround(this, query, observer);
945
                Thread thread = new Thread(task);
946
                thread.run();
947
        }
948

    
949
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
950
                return this.getFeatureByReference(reference, this.getDefaultFeatureType());
951
        }
952

    
953
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
954
                        throws DataException {
955
                featureType = fixFeatureType((DefaultFeatureType) featureType);
956
                // TODO comprobar que el id es de este store
957

    
958
                if (this.editingMode) {
959
                        if (featureManager.contains(reference)) {
960
                                return featureManager.getFeature(reference, this, featureType);
961
                        }
962
                }
963
                return this.createFeature(featureType, this.provider
964
                                .getFeatureDataByReference(reference, featureType));
965
        }
966

    
967
        //
968
        // ====================================================================
969
        // Gestion de features
970
        //
971

    
972
        private FeatureType fixFeatureType(DefaultFeatureType type)
973
                        throws DataException {
974
                FeatureType defaultType = this.getDefaultFeatureType();
975
                if (type == null || type.equals(defaultType)) {
976
                        return defaultType;
977
                }
978
                if (type.isSubtypeOf(defaultType)) {
979
                        return type;
980
                }
981
                Iterator iter = this.getFeatureTypes().iterator();
982
                FeatureType tmpType;
983
                while (iter.hasNext()) {
984
                        tmpType = (FeatureType) iter.next();
985
                        if (type.equals(tmpType) || type.isSubtypeOf(tmpType)) {
986
                                return type;
987
                        }
988

    
989
                }
990
                throw new IllegalFeatureTypeException(getName());
991
        }
992

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

    
1009
        public FeatureType getDefaultFeatureType() throws DataException {
1010
                try {
1011
                        if (isEditing()) {
1012
                                return featureTypeManager.getFeatureType();
1013
                        }
1014
                        return defaultFeatureType;
1015
                } catch (Exception e) {
1016
                        throw new GetFeatureTypeException(e, getName());
1017
                }
1018
        }
1019

    
1020
        public List getFeatureTypes() throws DataException {
1021
                try {
1022
                        List types;
1023
                        if (isEditing()) {
1024
                                types = featureTypeManager.getFeatureTypes();
1025
                        } else {
1026
                                types = featureTypes;
1027
                        }
1028
                        return Collections.unmodifiableList(types);
1029
                } catch (Exception e) {
1030
                        throw new GetFeatureTypeException(e, getName());
1031
                }
1032
        }
1033

    
1034
        public Feature createFeature(FeatureData data)
1035
                        throws DataException {
1036
                DefaultFeature feature = new DefaultFeature(this, data);
1037
                return feature;
1038
        }
1039

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

    
1052
        public EditableFeature createFeature(FeatureType type,
1053
                        Feature defaultValues)
1054
                        throws DataException {
1055
                try {
1056
                        type = this.fixFeatureType((DefaultFeatureType) type);
1057
                        FeatureData data = this.provider.createFeatureData(type);
1058
                        DefaultEditableFeature feature = new DefaultEditableFeature(this,
1059
                                        data);
1060
                        feature.initializeValues(defaultValues);
1061
                        return feature;
1062
                } catch (Exception e) {
1063
                        throw new CreateFeatureException(e, getName());
1064
                }
1065
        }
1066

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

    
1084
        public EditableFeature createFeature(boolean defaultValues)
1085
                        throws DataException {
1086
                return this.createFeature(this.getDefaultFeatureType(), defaultValues);
1087
        }
1088

    
1089
        public EditableFeature createFeature() throws DataException {
1090
                return this.createFeature(this.getDefaultFeatureType(), true);
1091
        }
1092

    
1093
        public EditableFeatureType createFeatureType() {
1094
                return new DefaultEditableFeatureType();
1095
        }
1096

    
1097
        public boolean isLocksSupported() {
1098
                return this.provider.isLocksSupported();
1099
        }
1100

    
1101
        public Logger getLogger() {
1102
                if (this.logger == null) {
1103
                        this.logger = LoggerFactory.getLogger(this.getClass());
1104
                }
1105
                return this.logger;
1106
        }
1107

    
1108
        public FeatureIndex createIndex(FeatureType featureType,
1109
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1110
                FeatureIndexProviderServices index = null;
1111
                index = getManager().createDataIndexProvider(this, featureType, featureType.getAttributeDescriptor(attributeName));
1112
                try {
1113
                        index.fill();
1114
                } catch (DataIndexException e) {
1115
                        throw new InitializeException(index.getName(), e);
1116
                }
1117
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1118
                return index;
1119
        }
1120

    
1121
}