Statistics
| Revision:

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

History | View | Annotate | Download (52.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27

    
28

    
29
package org.gvsig.fmap.dal.feature.impl;
30

    
31
import java.util.ArrayList;
32
import java.util.Collections;
33
import java.util.HashMap;
34
import java.util.HashSet;
35
import java.util.Iterator;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Set;
39
import java.util.Map.Entry;
40

    
41
import org.cresques.cts.IProjection;
42
import org.gvsig.fmap.dal.DALLocator;
43
import org.gvsig.fmap.dal.DataManager;
44
import org.gvsig.fmap.dal.DataQuery;
45
import org.gvsig.fmap.dal.DataServerExplorer;
46
import org.gvsig.fmap.dal.DataSet;
47
import org.gvsig.fmap.dal.DataStore;
48
import org.gvsig.fmap.dal.DataStoreNotification;
49
import org.gvsig.fmap.dal.DataStoreParameters;
50
import org.gvsig.fmap.dal.exception.CloseException;
51
import org.gvsig.fmap.dal.exception.CreateException;
52
import org.gvsig.fmap.dal.exception.DataException;
53
import org.gvsig.fmap.dal.exception.InitializeException;
54
import org.gvsig.fmap.dal.exception.OpenException;
55
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
56
import org.gvsig.fmap.dal.exception.ReadException;
57
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
58
import org.gvsig.fmap.dal.feature.EditableFeature;
59
import org.gvsig.fmap.dal.feature.EditableFeatureType;
60
import org.gvsig.fmap.dal.feature.Feature;
61
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
62
import org.gvsig.fmap.dal.feature.FeatureCache;
63
import org.gvsig.fmap.dal.feature.FeatureIndex;
64
import org.gvsig.fmap.dal.feature.FeatureIndexes;
65
import org.gvsig.fmap.dal.feature.FeatureLocks;
66
import org.gvsig.fmap.dal.feature.FeatureQuery;
67
import org.gvsig.fmap.dal.feature.FeatureReference;
68
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
69
import org.gvsig.fmap.dal.feature.FeatureSelection;
70
import org.gvsig.fmap.dal.feature.FeatureSet;
71
import org.gvsig.fmap.dal.feature.FeatureStore;
72
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
73
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
74
import org.gvsig.fmap.dal.feature.FeatureType;
75
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
76
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
77
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
78
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
79
import org.gvsig.fmap.dal.feature.exception.DataExportException;
80
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
81
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
82
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
83
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
84
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
85
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
86
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
87
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
88
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindDefaultFeatureTypeException;
89
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindFeatureTypeException;
90
import org.gvsig.fmap.dal.feature.exception.PersistenceStoreAlreadyLoadedException;
91
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
92
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
93
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
94
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
95
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
96
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
97
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
98
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
99
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
100
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
101
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
102
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
103
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
104
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
105
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
106
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
107
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
108
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
109
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
110
import org.gvsig.fmap.dal.feature.spi.cache.FeatureCacheProvider;
111
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
112
import org.gvsig.fmap.dal.impl.DataStoreImplementation;
113
import org.gvsig.fmap.dal.impl.DefaultDataManager;
114
import org.gvsig.fmap.dal.resource.Resource;
115
import org.gvsig.fmap.dal.spi.DataStoreProvider;
116
import org.gvsig.fmap.geom.primitive.Envelope;
117
import org.gvsig.metadata.MetadataLocator;
118
import org.gvsig.metadata.MetadataManager;
119
import org.gvsig.metadata.exceptions.MetadataException;
120
import org.gvsig.tools.ToolsLocator;
121
import org.gvsig.tools.dispose.DisposableIterator;
122
import org.gvsig.tools.dispose.impl.AbstractDisposable;
123
import org.gvsig.tools.dynobject.DelegatedDynObject;
124
import org.gvsig.tools.dynobject.DynClass;
125
import org.gvsig.tools.dynobject.DynObject;
126
import org.gvsig.tools.dynobject.DynObjectManager;
127
import org.gvsig.tools.dynobject.DynStruct;
128
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
129
import org.gvsig.tools.dynobject.exception.DynMethodException;
130
import org.gvsig.tools.exception.BaseException;
131
import org.gvsig.tools.exception.NotYetImplemented;
132
import org.gvsig.tools.observer.Observable;
133
import org.gvsig.tools.observer.Observer;
134
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
135
import org.gvsig.tools.persistence.PersistenceManager;
136
import org.gvsig.tools.persistence.Persistent;
137
import org.gvsig.tools.persistence.PersistentState;
138
import org.gvsig.tools.persistence.exception.PersistenceException;
139
import org.gvsig.tools.task.Executor;
140
import org.gvsig.tools.undo.RedoException;
141
import org.gvsig.tools.undo.UndoException;
142
import org.gvsig.tools.undo.command.Command;
143
import org.gvsig.tools.visitor.Visitor;
144
import org.slf4j.Logger;
145
import org.slf4j.LoggerFactory;
146

    
147
public final class DefaultFeatureStore extends AbstractDisposable implements
148
                DataStoreImplementation, FeatureStoreProviderServices, FeatureStore,
149
                Observer {
150

    
151
        final static private Logger logger = LoggerFactory
152
                        .getLogger(DefaultFeatureStore.class);
153

    
154
        private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
155

    
156
        private DataStoreParameters parameters = null;
157
        private FeatureSelection selection;
158
        private FeatureLocks locks;
159

    
160
        private DelegateWeakReferencingObservable delegateObservable = new DelegateWeakReferencingObservable(this);
161

    
162
        private FeatureCommandsStack commands;
163
        private FeatureTypeManager featureTypeManager;
164
        private FeatureManager featureManager;
165
        private SpatialManager spatialManager;
166

    
167
        private FeatureType defaultFeatureType = null;
168
        private List featureTypes = new ArrayList();
169

    
170
        private int mode = MODE_QUERY;
171
        private long versionOfUpdate = 0;
172
        private boolean hasStrongChanges = true;
173
        private boolean hasInserts = true;
174

    
175
        private DefaultDataManager dataManager = null;
176

    
177
        private FeatureStoreProvider provider = null;
178

    
179
        private DefaultFeatureIndexes indexes;
180

    
181
        private DefaultFeatureStoreTransforms transforms;
182

    
183
        private DelegatedDynObject metadata;
184
        private Set metadataChildren;
185

    
186
        private Long featureCount = null;
187

    
188
        private long temporalOid = 0;
189

    
190
        private FeatureCacheProvider cache;
191

    
192
        /*
193
         * TODO:
194
         *
195
         * - Comprobar que solo se pueden a�adir reglas de validacion sobre un
196
         * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
197
         * featureType al que se le han cambiado las reglas de validacion cuando
198
         * hasStrongChanges=false.
199
         */
200

    
201
        public DefaultFeatureStore() {
202

    
203
        }
204

    
205
        public void intializePhase1(DefaultDataManager dataManager,
206
                        DataStoreParameters parameters) throws InitializeException {
207

    
208
                DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
209

    
210
                this.metadata = (DelegatedDynObject) dynManager
211
                                .createDynObject(
212
                                                METADATA_DEFINITION_NAME,
213
                                                MetadataManager.METADATA_NAMESPACE
214
                                );
215
                                                
216
                                                
217
                this.dataManager = dataManager;
218

    
219
                this.parameters = parameters;
220
                this.transforms = new DefaultFeatureStoreTransforms(this);
221
                try {
222
                        indexes = new DefaultFeatureIndexes(this);
223
                } catch (DataException e) {
224
                        throw new InitializeException(e);
225
                }
226

    
227
        }
228

    
229
        public void intializePhase2(DataStoreProvider provider) {
230
                this.provider = (FeatureStoreProvider) provider;
231
                this.delegate(provider);
232
                this.metadataChildren = new HashSet();
233
                this.metadataChildren.add(provider);
234
        }
235

    
236
        public String getName() {
237
                return this.parameters.getDataStoreName();
238
        }
239

    
240
        public DataStoreParameters getParameters() {
241
                return parameters;
242
        }
243

    
244
        public int getMode() {
245
                return this.mode;
246
        }
247

    
248
        public DataManager getManager() {
249
                return this.dataManager;
250
        }
251

    
252
        public Iterator getChildren() {
253
                return this.provider.getChilds();
254
        }
255

    
256
        public FeatureStoreProvider getProvider() {
257
                return this.provider;
258
        }
259

    
260
        public FeatureManager getFeatureManager() {
261
                return this.featureManager;
262
        }
263

    
264
        public void setFeatureTypes(List types, FeatureType defaultType) {
265
                this.featureTypes = types;
266
                this.defaultFeatureType = defaultType;
267
        }
268

    
269
        public void open() throws OpenException {
270
                // TODO: Se puede hacer un open estando en edicion ?
271
                this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
272
                this.provider.open();
273
                this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
274
        }
275

    
276
        public void refresh() throws OpenException, InitializeException {
277
                if (this.mode != MODE_QUERY) {
278
                        throw new IllegalStateException();
279
                }
280
                this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
281
                this.featureCount = null;
282
                this.provider.refresh();
283
                this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
284
        }
285

    
286
        public void close() throws CloseException {
287
                // TODO: Se puede hacer un close estando en edicion ?
288
                this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
289
                this.featureCount = null;
290
                this.provider.close();
291
                this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
292
        }
293

    
294
        protected void doDispose() throws BaseException {
295
                this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
296
                this.provider.dispose();
297
                if (this.selection != null) {
298
                        this.selection.dispose();
299
                        this.selection = null;
300
                }
301
                this.commands = null;
302
                this.featureCount = null;
303
                if (this.locks != null) {
304
                        //this.locks.dispose();
305
                        this.locks = null;
306
                }
307

    
308
                if (this.featureTypeManager != null) {
309
                        this.featureTypeManager.dispose();
310
                        this.featureTypeManager = null;
311
                }
312

    
313
                this.featureManager = null;
314
                this.spatialManager = null;
315

    
316
                this.parameters = null;
317
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
318
                if (delegateObservable != null) {
319
                        this.delegateObservable.deleteObservers();
320
                        this.delegateObservable = null;
321
                }
322
        }
323

    
324
        public boolean allowWrite() {
325
                return this.provider.allowWrite();
326
        }
327

    
328
        public boolean canWriteGeometry(int geometryType) throws DataException {
329
                return this.provider.canWriteGeometry(geometryType, 0);
330
        }
331

    
332
        public DataServerExplorer getExplorer() throws ReadException,
333
                        ValidateDataParametersException {
334
                return this.provider.getExplorer();
335
        }
336

    
337
        /*
338
        public Metadata getMetadata() throws MetadataNotFoundException {
339
                // TODO:
340
                // Si el provider devuelbe null habria que ver de construir aqui
341
                // los metadatos basicos, como el Envelope y el SRS.
342

343
                // TODO: Estando en edicion el Envelope deberia de
344
                // actualizarse usando el spatialManager
345
                return this.provider.getMetadata();
346
        }
347
         */
348

    
349
        public Envelope getEnvelope() throws DataException {
350
                if (this.mode == MODE_FULLEDIT) {
351
                        return this.spatialManager.getEnvelope();
352
                }
353
                return this.provider.getEnvelope();
354
        }
355

    
356
        /**
357
         * @deprecated use getDefaultFeatureType().getDefaultSRS()
358
         */
359
        public IProjection getSRSDefaultGeometry() throws DataException {
360
                return this.getDefaultFeatureType().getDefaultSRS();
361
        }
362

    
363
        public FeatureSelection createDefaultFeatureSelection()
364
        throws DataException {
365
                return new DefaultFeatureSelection(this);
366
        }
367

    
368
        public FeatureProvider createDefaultFeatureProvider(FeatureType type)
369
        throws DataException {
370
                if( type.hasOID() ) {
371
                        return new DefaultFeatureProvider(type, this.provider.createNewOID());
372
                }
373
                return new DefaultFeatureProvider(type);
374
        }
375

    
376
        public void saveToState(PersistentState state) throws PersistenceException {
377
                if (this.mode != FeatureStore.MODE_QUERY){
378
                        throw new PersistenceException(
379
                                        new IllegalStateException(this
380
                                        .getName()));
381
                }
382
                state.set("dataStoreName", this.getName());
383
                state.set("parameters", this.parameters);
384
                state.set("selection", this.selection);
385
                state.set("transforms", this.transforms);
386
                // TODO locks persistence
387
                // state.set("locks", this.locks);
388
                // TODO indexes persistence
389
                // state.set("indexes", this.indexes);
390
                Map evaluatedAttr = new HashMap(1);
391
                Iterator iterType = featureTypes.iterator();
392
                Iterator iterAttr;
393
                FeatureType type;
394
                DefaultFeatureAttributeDescriptor attr;
395
                List attrs;
396
                while (iterType.hasNext()) {
397
                        type = (FeatureType) iterType.next();
398
                        attrs = new ArrayList();
399
                        iterAttr = type.iterator();
400
                        while (iterAttr.hasNext()) {
401
                                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
402
                                if (attr.getEvaluator() != null
403
                                                && attr.getEvaluator() instanceof Persistent) {
404
                                        attrs.add(attr);
405
                                }
406
                        }
407
                        if (!attrs.isEmpty()) {
408
                                evaluatedAttr.put(type.getId(), attrs);
409
                        }
410

    
411

    
412
                }
413

    
414
                if (evaluatedAttr.isEmpty()) {
415
                        evaluatedAttr = null;
416
                }
417

    
418
                state.set("evaluatedAttributes", evaluatedAttr);
419
                state.set("defaultFeatureTypeId", defaultFeatureType.getId());
420

    
421
        }
422

    
423
        public void loadFromState(PersistentState state) throws PersistenceException {
424
                if (this.provider != null) {
425
                        throw new PersistenceStoreAlreadyLoadedException(this.getName());
426
                }
427
                if (this.getManager() == null) {
428
                        this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
429
                }
430

    
431
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
432

    
433
                try {
434

    
435
                        this.dataManager.intializeDataStore(this, params);
436
                        this.selection = (FeatureSelection) state.get("selection");
437
                        this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
438
                        Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
439
                        if (evaluatedAttributes != null && !evaluatedAttributes.isEmpty()) {
440
                                List attrs;
441
                                Iterator iterEntries = evaluatedAttributes.entrySet().iterator();
442
                                Entry entry;
443
                                while (iterEntries.hasNext()){
444
                                        entry = (Entry) iterEntries.next();
445
                                        attrs = (List) entry.getValue();
446
                                        if (attrs.isEmpty()){
447
                                                continue;
448
                                        }
449
                                        int fTypePos = -1;
450
                                        DefaultFeatureType type = null;
451
                                        for (int i=0;i<featureTypes.size();i++){
452
                                                type = (DefaultFeatureType) featureTypes.get(i);
453
                                                if (type.getId().equals(entry.getKey())){
454
                                                        fTypePos = i;
455
                                                        break;
456
                                                }
457
                                        }
458
                                        if (fTypePos < 0){
459
                                                throw new PersistenceCantFindFeatureTypeException(this.getName(), (String)entry.getKey());
460
                                        }
461
                                        DefaultEditableFeatureType eType = (DefaultEditableFeatureType) type
462
                                                        .getEditable();
463
                                        Iterator iterAttr = attrs.iterator();
464
                                        FeatureAttributeDescriptor attr;
465
                                        while (iterAttr.hasNext()) {
466
                                                attr = (FeatureAttributeDescriptor) iterAttr.next();
467
                                                eType.addLike(attr);
468
                                        }
469
                                        featureTypes.set(fTypePos, eType.getNotEditableCopy());
470

    
471
                                }
472

    
473

    
474
                        }
475

    
476
                        String defFTypeid = state.getString("defaultFeatureTypeId");
477
                        FeatureType ftype = null;
478
                        if (!this.defaultFeatureType.getId().equals(
479
                                        state.getString("defaultFeatureTypeId"))) {
480

    
481
                                ftype = getFeatureType(defFTypeid);
482
                                if (ftype == null) {
483
                                        throw new PersistenceCantFindDefaultFeatureTypeException(this.getName(), defFTypeid);
484
                                }
485
                                this.defaultFeatureType = ftype;
486
                        }
487

    
488

    
489
                } catch (InitializeException e) {
490
                        throw new PersistenceException(e);
491
                } catch (DataException e) {
492
                        throw new PersistenceException(e);
493
                }
494

    
495
        }
496

    
497
        public static void registerPersistenceDefinition() {
498
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
499
                if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
500
                        DynStruct definition = manager.addDefinition(
501
                                        DefaultFeatureStore.class, 
502
                                        PERSISTENCE_DEFINITION_NAME, 
503
                                        PERSISTENCE_DEFINITION_NAME+" Persistent definition",
504
                                        null, 
505
                                        null
506
                                );
507
                        definition.addDynFieldString("dataStoreName")
508
                                .setMandatory(true)
509
                                .setPersistent(true);
510
                        
511
                        definition.addDynFieldObject("parameters")
512
                                .setClassOfValue(DynObject.class)
513
                                .setMandatory(true)
514
                                .setPersistent(true);
515
        
516
                        definition.addDynFieldObject("selection")
517
                                        .setClassOfValue(FeatureSelection.class)
518
                                        .setMandatory(true)
519
                                        .setPersistent(true);
520
        
521
                        definition.addDynFieldObject("transforms")
522
                                        .setClassOfValue(DefaultFeatureStoreTransforms.class)
523
                                        .setMandatory(true)
524
                                        .setPersistent(true);
525
        
526
                        definition.addDynFieldMap("evaluatedAttributes")
527
                                        .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
528
                                        .setMandatory(true)
529
                                        .setPersistent(true);
530
        
531
                        definition.addDynFieldString("defaultFeatureTypeId")
532
                                        .setMandatory(true)
533
                                        .setPersistent(true);
534
                }
535
        }
536

    
537
        public static void registerMetadataDefinition() throws MetadataException {
538
                MetadataManager manager = MetadataLocator.getMetadataManager();
539
                if( manager.getDefinition(METADATA_DEFINITION_NAME)==null ) {
540
                        DynStruct metadataDefinition = manager.addDefinition(
541
                                        METADATA_DEFINITION_NAME,
542
                                        null
543
                        );
544
                        metadataDefinition.extend(
545
                                        manager.getDefinition(
546
                                                DataStore.METADATA_DEFINITION_NAME
547
                                        )
548
                        );
549
                }
550
        }
551
        
552
        //
553
        // ====================================================================
554
        // Gestion de la seleccion
555
        //
556

    
557
        public void setSelection(DataSet selection)
558
        throws DataException {
559
                this.setSelection((FeatureSet) selection);
560
        }
561

    
562
        public DataSet createSelection() throws DataException {
563
                return createFeatureSelection();
564
        }
565

    
566
        public DataSet getSelection() throws DataException {
567
                return this.getFeatureSelection();
568
        }
569

    
570
    public void setSelection(FeatureSet selection) throws DataException {
571
        setSelection(selection, true);
572
    }
573

    
574
    /**
575
     * @see #setSelection(FeatureSet)
576
     * @param undoable
577
     *            if the action must be undoable
578
     */
579
    public void setSelection(FeatureSet selection, boolean undoable)
580
        throws DataException {
581
            if (selection == null) {
582
                        if (undoable) {
583
                                throw new SelectionNotAllowedException(getName());
584
                        }
585

    
586
                } else {
587
                        if (selection.equals(this.selection)) {
588
                                return;
589
                        }
590
                        if (!selection.isFromStore(this)) {
591
                                throw new SelectionNotAllowedException(getName());
592
                        }
593
                }
594

    
595
            if (this.selection != null) {
596
                        this.selection.deleteObserver(this);
597
                }
598
                if (selection == null) {
599
                        if (this.selection != null) {
600
                                this.selection.dispose();
601
                        }
602
                        this.selection = null;
603
                        return;
604
                }
605
                if (selection instanceof FeatureSelection) {
606
                        if (undoable && isEditing()) {
607
                                commands.selectionSet(this, this.selection,
608
                                                (FeatureSelection) selection);
609
                        }
610
                        if (this.selection != null) {
611
                                this.selection.dispose();
612
                        }
613
                        this.selection = (FeatureSelection) selection;
614
                } else {
615
                        if (undoable && isEditing()) {
616
                                commands.startComplex("_selectionSet");
617
                        }
618
                        if (selection instanceof DefaultFeatureSelection) {
619
                DefaultFeatureSelection defSelection = (DefaultFeatureSelection) selection;
620
                defSelection.deselectAll(undoable);
621
                defSelection.select(selection, undoable);
622
            } else {
623
                this.selection.deselectAll();
624
                this.selection.select(selection);
625
            }
626
                        if (undoable && isEditing()) {
627
                                commands.endComplex();
628
                        }
629
                }
630
                this.selection.addObserver(this);
631

    
632
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
633
        }
634

    
635
        public FeatureSelection createFeatureSelection() throws DataException {
636
                return this.provider.createFeatureSelection();
637
        }
638

    
639
        public FeatureSelection getFeatureSelection() throws DataException {
640
                if (selection == null) {
641
                        this.selection = createFeatureSelection();
642
                        this.selection.addObserver(this);
643
                }
644
                return selection;
645
        }
646

    
647
        //
648
        // ====================================================================
649
        // Gestion de notificaciones
650
        //
651

    
652
        public void notifyChange(String notification) {
653
                if (delegateObservable != null) {
654
                        delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
655
                                        this, notification));
656
                }
657

    
658
        }
659

    
660
        public void notifyChange(String notification, Feature feature) {
661
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
662
                                this, notification, feature));
663
        }
664

    
665
        public void notifyChange(String notification, Command command) {
666
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
667
                                this, notification, command));
668
        }
669

    
670
        public void notifyChange(String notification, EditableFeatureType type) {
671
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
672
                                notification, type));
673
        }
674

    
675
        /*
676
         * (non-Javadoc)
677
         *
678
         * @see
679
         * org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices#notifyChange
680
         * (java.lang.String, org.gvsig.fmap.dal.resource.Resource)
681
         */
682
        public void notifyChange(String notification, Resource resource) {
683
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
684
                                FeatureStoreNotification.RESOURCE_CHANGED));
685
        }
686

    
687

    
688
        //
689
        // ====================================================================
690
        // Gestion de bloqueos
691
        //
692

    
693
        public boolean isLocksSupported() {
694
                return this.provider.isLocksSupported();
695
        }
696

    
697
        public FeatureLocks getLocks() throws DataException {
698
                if (!this.provider.isLocksSupported()) {
699
                        logger.warn("Locks not supporteds");
700
                        return null;
701
                }
702
                if (locks == null) {
703
                        this.locks = this.provider.createFeatureLocks();
704
                }
705
                return locks;
706
        }
707

    
708
        //
709
        // ====================================================================
710
        // Interface Observable
711
        //
712

    
713
        public void disableNotifications() {
714
                this.delegateObservable.disableNotifications();
715

    
716
        }
717

    
718
        public void enableNotifications() {
719
                this.delegateObservable.enableNotifications();
720
        }
721

    
722
        public void beginComplexNotification() {
723
                this.delegateObservable.beginComplexNotification();
724

    
725
        }
726

    
727
        public void endComplexNotification() {
728
                this.delegateObservable.endComplexNotification();
729

    
730
        }
731

    
732
        public void addObserver(Observer observer) {
733
                this.delegateObservable.addObserver(observer);
734

    
735
        }
736

    
737
        public void deleteObserver(Observer observer) {
738
                if (delegateObservable != null) {
739
                        this.delegateObservable.deleteObserver(observer);
740
                }
741
        }
742

    
743
        public void deleteObservers() {
744
                this.delegateObservable.deleteObservers();
745

    
746
        }
747

    
748
        //
749
        // ====================================================================
750
        // Interface Observer
751
        //
752
        // Usado para observar:
753
        // - su seleccion
754
        // - sus bloqueos
755
        // - sus recursos
756
        //
757

    
758
        public void update(Observable observable, Object notification) {
759
                if (observable instanceof FeatureSet) {
760
                        if (observable == this.selection) {
761
                                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
762
                        } else if (observable == this.locks) {
763
                                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
764
                        }
765

    
766
                } else if (observable instanceof FeatureStoreProvider) {
767
                        if (observable == this.provider) {
768

    
769
                        }
770

    
771
                }
772
        }
773

    
774
        //
775
        // ====================================================================
776
        // Edicion
777
        //
778

    
779
        private void newVersionOfUpdate() {
780
                this.versionOfUpdate++;
781
        }
782

    
783
        private long currentVersionOfUpdate() {
784
                return this.versionOfUpdate;
785
        }
786

    
787
        private void checkInEditingMode()
788
        throws NeedEditingModeException {
789
                if (mode != MODE_FULLEDIT) {
790
                        throw new NeedEditingModeException(this.getName());
791
                }
792
        }
793

    
794
        private void checkNotInAppendMode() throws IllegalStateException {
795
                if (mode == MODE_APPEND) {
796
                        throw new IllegalStateException(this.getName());
797
                }
798
        }
799

    
800
        private void checkIsOwnFeature(Feature feature)
801
        throws IllegalFeatureException {
802
                if (((DefaultFeature) feature).getStore() != this) {
803
                        throw new IllegalFeatureException(this.getName());
804
                }
805
                // FIXME: fixFeatureType no vale para el checkIsOwnFeature
806
                // fixFeatureType((DefaultFeatureType) feature.getType());
807
        }
808

    
809
        private void exitEditingMode() {
810
                if (commands != null) {
811
                        commands.clear();
812
                        commands = null;
813
                }
814

    
815
                if (featureTypeManager != null) {
816
                        featureTypeManager.dispose();
817
                        featureTypeManager = null;
818

    
819
                }
820

    
821
                // TODO implementar un dispose para estos dos
822
                featureManager = null;
823
                spatialManager = null;
824

    
825
                featureCount = null;
826

    
827
                mode = MODE_QUERY;
828
                hasStrongChanges = true; // Lo deja a true por si las moscas
829
                hasInserts = true;
830
        }
831

    
832
        synchronized public void edit() throws DataException {
833
                edit(MODE_FULLEDIT);
834
        }
835

    
836
        synchronized public void edit(int mode) throws DataException {
837
                try {
838
                        if ( this.mode != MODE_QUERY ) {
839
                                throw new AlreadyEditingException(this.getName());
840
                        }
841
                        if (!this.provider.supportsAppendMode()) {
842
                                mode = MODE_FULLEDIT;
843
                        }
844
                        switch (mode) {
845
                        case MODE_QUERY:
846
                                throw new IllegalStateException(this.getName());
847

    
848
                        case MODE_FULLEDIT:
849
                                if (!this.transforms.isEmpty()) {
850
                                        throw new IllegalStateException(this.getName());
851
                                }
852
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
853
                                featureManager = new FeatureManager(new MemoryExpansionAdapter());
854
                                featureTypeManager = new FeatureTypeManager(this,
855
                                                new MemoryExpansionAdapter());
856
                                spatialManager = new SpatialManager(this, provider
857
                                                .getEnvelope());
858

    
859
                                commands = new DefaultFeatureCommandsStack(featureManager,
860
                                                spatialManager, featureTypeManager);
861
                                this.mode = MODE_FULLEDIT;
862
                                hasStrongChanges = false;
863
                                hasInserts = false;
864
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
865
                                break;
866
                        case MODE_APPEND:
867
                                if (!this.transforms.isEmpty()) {
868
                                        throw new IllegalStateException(this.getName());
869
                                }
870
                                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
871
                                this.provider.beginAppend();
872
                                this.mode = MODE_APPEND;
873
                                hasInserts = false;
874
                                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
875
                                break;
876
                        }
877
                } catch (Exception e) {
878
                        throw new StoreEditException(e, this.getName());
879
                }
880
        }
881

    
882
        public boolean isEditing() {
883
                return mode == MODE_FULLEDIT;
884
        }
885

    
886
        public boolean isAppending() {
887
                return mode == MODE_APPEND;
888
        }
889

    
890
        synchronized public void update(EditableFeatureType type)
891
        throws DataException {
892
                try {
893
                        checkInEditingMode();
894
                        if (type == null) {
895
                                throw new NullFeatureTypeException(getName());
896
                        }
897
                        // FIXME: Comprobar que es un featureType aceptable.
898
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
899
                        newVersionOfUpdate();
900

    
901
                        FeatureType oldt = type.getSource().getCopy();
902
                        FeatureType newt = type.getNotEditableCopy();
903
                        commands.update(newt, oldt);
904

    
905
                        if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
906
                                hasStrongChanges = true;
907
                        }
908
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
909
                } catch (Exception e) {
910
                        throw new StoreUpdateFeatureTypeException(e, this.getName());
911
                }
912
        }
913

    
914
        synchronized public void delete(Feature feature) throws DataException {
915
                try {
916
                        checkInEditingMode();
917
                        checkIsOwnFeature(feature);
918
                        if (feature instanceof EditableFeature) {
919
                                throw new StoreDeleteEditableFeatureException(getName());
920
                        }
921
                        notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
922
                        this.commands.delete(feature);
923
                        newVersionOfUpdate();
924
                        hasStrongChanges = true;
925
                        notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
926
                } catch (Exception e) {
927
                        throw new StoreDeleteFeatureException(e, this.getName());
928
                }
929
        }
930

    
931
        private static EditableFeature lastChangedFeature = null;
932

    
933
        synchronized public void insert(EditableFeature feature)
934
        throws DataException {
935
                try {
936
                        switch (mode) {
937
                        case MODE_QUERY:
938
                                throw new NeedEditingModeException(this.getName());
939

    
940
                        case MODE_APPEND:
941
                                checkIsOwnFeature(feature);
942
                                if (feature.getSource() != null) {
943
                                        throw new NoNewFeatureInsertException(this.getName());
944
                                }
945
                                this.featureCount = null;
946
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
947
                                feature.validate(Feature.UPDATE);
948
                                provider.append(((DefaultEditableFeature) feature).getData());
949
                                hasStrongChanges = true;
950
                                hasInserts = true;
951
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
952
                                break;
953

    
954
                        case MODE_FULLEDIT:
955
                                checkIsOwnFeature(feature);
956
                                if (feature.getSource() != null) {
957
                                        throw new NoNewFeatureInsertException(this.getName());
958
                                }
959
                                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
960
                                newVersionOfUpdate();
961
                                if (lastChangedFeature ==null || lastChangedFeature.getSource() != feature.getSource()) {
962
                                        lastChangedFeature = feature;
963
                                        feature.validate(Feature.UPDATE);
964
                                        lastChangedFeature = null;
965
                                }
966
                                commands.insert(feature.getNotEditableCopy());
967
                                hasStrongChanges = true;
968
                                hasInserts = true;
969
                                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
970
                                break;
971
                        }
972
                } catch (Exception e) {
973
                        throw new StoreInsertFeatureException(e, this.getName());
974
                }
975
        }
976

    
977
        synchronized public void update(EditableFeature feature)
978
        throws DataException {
979
                try {
980
                        if ((feature).getSource() == null) {
981
                                insert(feature);
982
                                return;
983
                        }
984
                        checkInEditingMode();
985
                        checkIsOwnFeature(feature);
986
                        notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
987
                        newVersionOfUpdate();
988
                        if (lastChangedFeature==null || lastChangedFeature.getSource() != feature.getSource()) {
989
                                lastChangedFeature = feature;
990
                                feature.validate(Feature.UPDATE);
991
                                lastChangedFeature = null;
992
                        }
993

    
994
                        Feature oldf = feature.getSource();
995
                        Feature newf = feature.getNotEditableCopy();
996
                        commands.update(newf, oldf);
997

    
998
                        hasStrongChanges = true;
999
                        notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1000
                } catch (Exception e) {
1001
                        throw new StoreUpdateFeatureException(e, this.getName());
1002
                }
1003
        }
1004

    
1005
        synchronized public void redo() throws RedoException {
1006
                Command redo = commands.getNextRedoCommand();
1007
                try {
1008
                        checkInEditingMode();
1009
                } catch (NeedEditingModeException ex) {
1010
                        throw new RedoException(redo, ex);
1011
                }
1012
                notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1013
                newVersionOfUpdate();
1014
                commands.redo();
1015
                hasStrongChanges = true;
1016
                notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1017
        }
1018

    
1019
        synchronized public void undo() throws UndoException {
1020
                Command undo = commands.getNextUndoCommand();
1021
                try {
1022
                        checkInEditingMode();
1023
                } catch (NeedEditingModeException ex) {
1024
                        throw new UndoException(undo, ex);
1025
                }
1026
                notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1027
                newVersionOfUpdate();
1028
                commands.undo();
1029
                hasStrongChanges = true;
1030
                notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1031
        }
1032

    
1033
        public List getRedoInfos() {
1034
                if (isEditing() && commands != null) {
1035
                        return commands.getRedoInfos();
1036
                } else {
1037
                        return null;
1038
                }
1039
        }
1040

    
1041
        public List getUndoInfos() {
1042
                if (isEditing() && commands != null) {
1043
                        return commands.getUndoInfos();
1044
                } else {
1045
                        return null;
1046
                }
1047
        }
1048

    
1049
        public synchronized FeatureCommandsStack getCommandsStack()
1050
        throws DataException {
1051
                checkInEditingMode();
1052
                return commands;
1053
        }
1054

    
1055
        synchronized public void cancelEditing() throws DataException {
1056
                spatialManager.cancelModifies();
1057
                try {
1058
                        checkInEditingMode();
1059

    
1060
                        boolean clearSelection = this.hasStrongChanges;
1061
                        if (this.selection instanceof FeatureReferenceSelection) {
1062
                                clearSelection = this.hasInserts;
1063
                        }
1064
                        notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1065
                        exitEditingMode();
1066
                        if (clearSelection) {
1067
                                ((FeatureSelection) this.getSelection()).deselectAll();
1068
                        }
1069
                        notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1070
                } catch (Exception e) {
1071
                        throw new StoreCancelEditingException(e, this.getName());
1072
                }
1073
        }
1074

    
1075
        synchronized public void finishEditing() throws DataException {
1076
                try {
1077
                        switch (mode) {
1078
                        case MODE_QUERY:
1079
                                throw new NeedEditingModeException(this.getName());
1080

    
1081
                        case MODE_APPEND:
1082
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1083
                                provider.endAppend();
1084
                                exitEditingMode();
1085
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1086
                                break;
1087

    
1088
                        case MODE_FULLEDIT:
1089
                                if (hasStrongChanges && !this.allowWrite()) {
1090
                                        throw new WriteNotAllowedException(getName());
1091
                                }
1092

    
1093
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1094
                                if (hasStrongChanges) {
1095
                                        validateFeatures(Feature.FINISH_EDITING);
1096
                                        provider.performChanges(featureManager.getDeleted(),
1097
                                                        featureManager.getInserted(), featureManager
1098
                                                                        .getUpdated(), featureTypeManager
1099
                                                                        .getFeatureTypesChanged());
1100
                                }
1101
                                exitEditingMode();
1102
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1103
                                break;
1104
                        }
1105
                } catch (Exception e) {
1106
                        throw new FinishEditingException(e);
1107
                }
1108
        }
1109

    
1110
        public void beginEditingGroup(String description)
1111
        throws NeedEditingModeException {
1112
                checkInEditingMode();
1113
                commands.startComplex(description);
1114
        }
1115

    
1116
        public void endEditingGroup() throws NeedEditingModeException {
1117
                checkInEditingMode();
1118
                commands.endComplex();
1119
        }
1120

    
1121
        public boolean isAppendModeSupported() {
1122
                return this.provider.supportsAppendMode();
1123
        }
1124

    
1125

    
1126
        public void export(DataServerExplorer explorer, String provider, NewFeatureStoreParameters params)
1127
        throws DataException {
1128

    
1129
                if (this.getFeatureTypes().size() != 1) {
1130
                        throw new NotYetImplemented(
1131
                        "export whith more than one type not yet implemented");
1132
                }
1133
                FeatureSelection featureSelection=(FeatureSelection)getSelection();
1134
                FeatureStore target = null;
1135
                FeatureSet features = null;
1136
                DisposableIterator iterator = null;
1137
                try {
1138
                        FeatureType type = this.getDefaultFeatureType();
1139
                        if (params.getDefaultFeatureType() == null
1140
                                        || params.getDefaultFeatureType().size() == 0) {
1141
                                params.setDefaultFeatureType(type.getEditable());
1142

    
1143
                        }
1144
                        explorer.add(provider, params, true);
1145

    
1146
                        DataManager manager = DALLocator.getDataManager();
1147
                        target = (FeatureStore) manager.openStore(provider, params);
1148
                        FeatureType targetType = target.getDefaultFeatureType();
1149

    
1150
                        target.edit(MODE_APPEND);
1151
                        FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1152
                        if (featureSelection.getSize()>0){
1153
                                features = this.getFeatureSelection();
1154
                        }else{
1155
                                if (pk != null && pk.length > 0){
1156
                                        FeatureQuery query = createFeatureQuery();
1157
                                        for (int i = 0; i < pk.length; i++) {
1158
                                                query.getOrder().add(pk[i].getName(), true);
1159
                                        }
1160
                                        features = this.getFeatureSet(query);
1161
                                } else {
1162
                                        features = this.getFeatureSet();
1163
                                }
1164
                        }
1165
                        iterator = features.iterator();
1166
                        while (iterator.hasNext()) {
1167
                                DefaultFeature feature = (DefaultFeature) iterator.next();
1168
                                target.insert(target.createNewFeature(targetType, feature));
1169
                        }
1170
                        target.finishEditing();
1171
                        target.dispose();
1172
                } catch (Exception e) {
1173
                        throw new DataExportException(e, params.toString());
1174
                } finally {
1175
                        dispose(iterator);
1176
                        dispose(features);
1177
                        dispose(target);
1178
                }
1179
        }
1180

    
1181
        //
1182
        // ====================================================================
1183
        // Obtencion de datos
1184
        // getDataCollection, getFeatureCollection
1185
        //
1186

    
1187
        public DataSet getDataSet() throws DataException {
1188
                checkNotInAppendMode();
1189
                FeatureQuery query = new DefaultFeatureQuery(this
1190
                                .getDefaultFeatureType());
1191
                return new DefaultFeatureSet(this, query);
1192
        }
1193

    
1194
        public DataSet getDataSet(DataQuery dataQuery)
1195
        throws DataException {
1196
                checkNotInAppendMode();
1197
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1198
        }
1199

    
1200
        public void getDataSet(Observer observer) throws DataException {
1201
                checkNotInAppendMode();
1202
                this.getFeatureSet(null, observer);
1203
        }
1204

    
1205
        public void getDataSet(DataQuery dataQuery, Observer observer)
1206
        throws DataException {
1207
                checkNotInAppendMode();
1208
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
1209
        }
1210

    
1211
        public FeatureSet getFeatureSet() throws DataException {
1212
                checkNotInAppendMode();
1213
                FeatureQuery query = new DefaultFeatureQuery(this
1214
                                .getDefaultFeatureType());
1215
                return new DefaultFeatureSet(this, query);
1216
        }
1217

    
1218
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1219
        throws DataException {
1220
                checkNotInAppendMode();
1221
                return new DefaultFeatureSet(this, featureQuery);
1222
        }
1223

    
1224
        public void accept(Visitor visitor) throws BaseException {
1225
                FeatureSet set = getFeatureSet();
1226
                try {
1227
                        set.accept(visitor);
1228
                } finally {
1229
                        set.dispose();
1230
                }
1231
        }
1232

    
1233
        public void accept(Visitor visitor, DataQuery dataQuery)
1234
                        throws BaseException {
1235
                FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1236
                try {
1237
                        set.accept(visitor);
1238
                } finally {
1239
                        set.dispose();
1240
                }
1241
        }
1242

    
1243
        public FeatureType getFeatureType(FeatureQuery featureQuery)
1244
                        throws DataException {
1245
                DefaultFeatureType fType = (DefaultFeatureType) this
1246
                                .getFeatureType(featureQuery.getFeatureTypeId());
1247
                if (featureQuery.getAttributeNames() != null){
1248
                        return fType.getSubtype(featureQuery.getAttributeNames());
1249
                }
1250
                return fType;
1251
        }
1252

    
1253
        public void getFeatureSet(Observer observer)
1254
        throws DataException {
1255
                checkNotInAppendMode();
1256
                this.getFeatureSet(null, observer);
1257
        }
1258

    
1259
        public void getFeatureSet(FeatureQuery query, Observer observer)
1260
        throws DataException {
1261
                class LoadInBackGround implements Runnable {
1262
                        private FeatureStore store;
1263
                        private FeatureQuery query;
1264
                        private Observer observer;
1265
                        private Executor executor;
1266
                        private FeatureStoreNotification notification;
1267

    
1268
                        public LoadInBackGround(FeatureStore store, FeatureQuery query,
1269
                                        Observer observer, Executor executor) {
1270
                                this.store = store;
1271
                                this.query = query;
1272
                                this.observer = observer;
1273
                                this.executor = executor;
1274
                        }
1275

    
1276
                        void notify(FeatureStoreNotification theNotification) {
1277
                                if (executor == null) {
1278
                                        observer.update(store, theNotification);
1279
                                        return;
1280
                                }
1281
                                this.notification = theNotification;
1282
                                executor.execute(new Runnable() {
1283
                                        public void run() {
1284
                                                observer.update(store, notification);
1285
                                        }
1286
                                });
1287

    
1288
                        }
1289

    
1290
                        public void run() {
1291
                                FeatureSet set = null;
1292
                                try {
1293
                                        set = store.getFeatureSet(query);
1294
                                        notify(new DefaultFeatureStoreNotification(store,
1295
                                                        FeatureStoreNotification.LOAD_FINISHED, set));
1296
                                } catch (Exception e) {
1297
                                        notify(new DefaultFeatureStoreNotification(store,
1298
                                                        FeatureStoreNotification.LOAD_FINISHED, e));
1299
                                } finally {
1300
                                        dispose(set);
1301
                                }
1302
                        }
1303
                }
1304

    
1305
                checkNotInAppendMode();
1306
                if (query == null) {
1307
                        query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1308
                }
1309
                Executor executor = ToolsLocator.getTaskManager().getExecutor();
1310
                LoadInBackGround task = new LoadInBackGround(this, query, observer,
1311
                                executor);
1312
                Thread thread = new Thread(task);
1313
                thread.run();
1314
        }
1315

    
1316
        public Feature getFeatureByReference(FeatureReference reference) throws DataException {
1317
                checkNotInAppendMode();
1318
                DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1319
                FeatureType featureType;
1320
                if (ref.getFeatureTypeId() == null) {
1321
                        featureType = this.getDefaultFeatureType();
1322
                } else {
1323
                        featureType = this.getFeatureType(ref.getFeatureTypeId());
1324
                }
1325
                return this.getFeatureByReference(reference, featureType);
1326
        }
1327

    
1328
        public Feature getFeatureByReference(FeatureReference reference, FeatureType featureType)
1329
        throws DataException {
1330
                checkNotInAppendMode();
1331
                featureType = fixFeatureType((DefaultFeatureType) featureType);
1332
                if (!this.transforms.isEmpty()) {
1333

    
1334
                        featureType = this.transforms
1335
                        .getSourceFeatureTypeFrom(featureType);
1336

    
1337
                }
1338
                // TODO comprobar que el id es de este store
1339

    
1340
                if (this.mode == MODE_FULLEDIT) {
1341
                        Feature f = featureManager.get(reference, this, featureType);
1342
                        if (f!=null) {
1343
                                return f;
1344
                        }
1345
                }
1346
                DefaultFeature feature = new DefaultFeature(
1347
                                this,
1348
                                this.provider
1349
                                .getFeatureProviderByReference(
1350
                                                (FeatureReferenceProviderServices) reference,
1351
                                                featureType));
1352

    
1353
                if (!this.transforms.isEmpty()) {
1354
                        return this.transforms.applyTransform(feature, featureType);
1355
                }
1356
                return feature;
1357
        }
1358

    
1359
        //
1360
        // ====================================================================
1361
        // Gestion de features
1362
        //
1363

    
1364
        private FeatureType fixFeatureType(DefaultFeatureType type)
1365
        throws DataException {
1366
                FeatureType original = this.getDefaultFeatureType();
1367

    
1368
                if (type == null || type.equals(original)) {
1369
                        return original;
1370
                } else {
1371
                        if (!type.isSubtypeOf(original)) {
1372
                                Iterator iter = this.getFeatureTypes().iterator();
1373
                                FeatureType tmpType;
1374
                                boolean found = false;
1375
                                while (iter.hasNext()) {
1376
                                        tmpType = (FeatureType) iter.next();
1377
                                        if (type.equals(tmpType)) {
1378
                                                return type;
1379

    
1380
                                        }else if (type.isSubtypeOf(tmpType)) {
1381
                                                found = true;
1382
                                                original = tmpType;
1383
                                                break;
1384
                                        }
1385

    
1386
                                }
1387
                                if (!found) {
1388
                                        throw new IllegalFeatureTypeException(getName());
1389
                                }
1390
                        }
1391
                }
1392

    
1393
                // Checks that type has all fields of pk
1394
                // else add the missing attributes at the end.
1395
                if (!original.hasOID()) {
1396
                        // Gets original pk attributes
1397
                        DefaultEditableFeatureType edOriginal = (DefaultEditableFeatureType) original
1398
                                        .getEditable();
1399
                        FeatureAttributeDescriptor orgAttr;
1400
                        Iterator edOriginalIter = edOriginal.iterator();
1401
                        while (edOriginalIter.hasNext()) {
1402
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1403
                                if (!orgAttr.isPrimaryKey()) {
1404
                                        edOriginalIter.remove();
1405
                                }
1406
                        }
1407

    
1408
                        // Checks if all pk attributes are in type
1409
                        Iterator typeIterator;
1410
                        edOriginalIter = edOriginal.iterator();
1411
                        FeatureAttributeDescriptor attr;
1412
                        while (edOriginalIter.hasNext()) {
1413
                                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1414
                                typeIterator = type.iterator();
1415
                                while (typeIterator.hasNext()) {
1416
                                        attr = (FeatureAttributeDescriptor) typeIterator.next();
1417
                                        if (attr.getName().equals(orgAttr.getName())) {
1418
                                                edOriginalIter.remove();
1419
                                                break;
1420
                                        }
1421
                                }
1422
                        }
1423

    
1424
                        // add missing pk attributes if any
1425
                        if (edOriginal.size() > 0) {
1426
                                boolean isEditable = type instanceof DefaultEditableFeatureType;
1427
                                DefaultEditableFeatureType edType = (DefaultEditableFeatureType) original
1428
                                                .getEditable();
1429
                                edType.clear();
1430
                                edType.addAll(type);
1431
                                edType.addAll(edOriginal);
1432
                                if (!isEditable) {
1433
                                        type = (DefaultFeatureType) edType.getNotEditableCopy();
1434
                                }
1435
                        }
1436

    
1437
                }
1438

    
1439

    
1440
                return type;
1441
        }
1442

    
1443
        public void validateFeatures(int mode) throws DataException {
1444
                FeatureSet collection = null;
1445
                DisposableIterator iter = null;
1446
                try {
1447
                        checkNotInAppendMode();
1448
                        collection = this.getFeatureSet();
1449
                        iter = collection.iterator();
1450
                        long previousVersionOfUpdate = currentVersionOfUpdate();
1451
                        while (iter.hasNext()) {
1452
                                ((DefaultFeature) iter.next()).validate(mode);
1453
                                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1454
                                        throw new ConcurrentDataModificationException(getName());
1455
                                }
1456
                        }
1457
                } catch (Exception e) {
1458
                        throw new ValidateFeaturesException(e, getName());
1459
                } finally {
1460
                        dispose(iter);
1461
                        dispose(collection);
1462
                }
1463
        }
1464

    
1465
        public FeatureType getDefaultFeatureType() throws DataException {
1466
                try {
1467
                        if (isEditing()) {
1468
                                FeatureType auxFeatureType=featureTypeManager.getType(defaultFeatureType.getId());
1469
                                if (auxFeatureType!=null) {
1470
                                        return auxFeatureType;
1471
                                }
1472
                        }
1473
                        FeatureType type = this.transforms.getDefaultFeatureType();
1474
                        if (type != null) {
1475
                                return type;
1476
                        }
1477
                        return defaultFeatureType;
1478
                } catch (Exception e) {
1479
                        throw new GetFeatureTypeException(e, getName());
1480
                }
1481
        }
1482

    
1483
        public FeatureType getFeatureType(String featureTypeId)
1484
                        throws DataException {
1485
                if (featureTypeId == null) {
1486
                        return this.getDefaultFeatureType();
1487
                }
1488
                try {
1489
                        if (isEditing()) {
1490
                                FeatureType auxFeatureType = featureTypeManager
1491
                                                .getType(featureTypeId);
1492
                                if (auxFeatureType != null) {
1493
                                        return auxFeatureType;
1494
                                }
1495
                        }
1496
                        FeatureType type = this.transforms.getFeatureType(featureTypeId);
1497
                        if (type != null) {
1498
                                return type;
1499
                        }
1500
                        Iterator iter = this.featureTypes.iterator();
1501
                        while (iter.hasNext()){
1502
                                type = (FeatureType) iter.next();
1503
                                if (type.getId().equals(featureTypeId)) {
1504
                                        return type;
1505
                                }
1506
                        }
1507
                        return null;
1508
                } catch (Exception e) {
1509
                        throw new GetFeatureTypeException(e, getName());
1510
                }
1511
        }
1512

    
1513

    
1514
        public FeatureType getProviderDefaultFeatureType() {
1515
                return defaultFeatureType;
1516
        }
1517

    
1518
        public List getFeatureTypes() throws DataException {
1519
                try {
1520
                        List types;
1521
                        if (isEditing()) {
1522
                                types=new ArrayList();
1523
                                Iterator it=featureTypes.iterator();
1524
                                while (it.hasNext()) {
1525
                                        FeatureType type = (FeatureType) it.next();
1526
                                        FeatureType typeaux = featureTypeManager.getType(type.getId());
1527
                                        if (typeaux!=null) {
1528
                                                types.add(typeaux);
1529
                                        }else{
1530
                                                types.add(type);
1531
                                        }
1532
                                }
1533
                                it = featureTypeManager.newsIterator();
1534
                                while (it.hasNext()) {
1535
                                        FeatureType type = (FeatureType) it.next();
1536
                                        types.add(type);
1537
                                }
1538
                        } else {
1539
                                types = this.transforms.getFeatureTypes();
1540
                                if (types == null) {
1541
                                        types = featureTypes;
1542
                                }
1543
                        }
1544
                        return Collections.unmodifiableList(types);
1545
                } catch (Exception e) {
1546
                        throw new GetFeatureTypeException(e, getName());
1547
                }
1548
        }
1549

    
1550
        public List getProviderFeatureTypes() throws DataException {
1551
                return Collections.unmodifiableList(this.featureTypes);
1552
        }
1553

    
1554
        public Feature createFeature(FeatureProvider data)
1555
        throws DataException {
1556
                DefaultFeature feature = new DefaultFeature(this, data);
1557
                return feature;
1558
        }
1559

    
1560
        public Feature createFeature(FeatureProvider data, FeatureType type)
1561
        throws DataException {
1562
                // FIXME: falta por implementar
1563
                // Comprobar si es un subtipo del feature de data
1564
                // y construir un feature usando el subtipo.
1565
                // Probablemente requiera generar una copia del data.
1566
                throw new NotYetImplemented();
1567
        }
1568

    
1569
        public EditableFeature createNewFeature(FeatureType type,
1570
                        Feature defaultValues)
1571
        throws DataException {
1572
                try {
1573
                        FeatureProvider data = createNewFeatureProvider(type);
1574
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1575
                        feature.initializeValues(defaultValues);
1576
                        return feature;
1577
                } catch (Exception e) {
1578
                        throw new CreateFeatureException(e, getName());
1579
                }
1580
        }
1581

    
1582
        private FeatureProvider createNewFeatureProvider(FeatureType type)
1583
                        throws DataException {
1584
                type = this.fixFeatureType((DefaultFeatureType) type);
1585
                FeatureProvider data = this.provider.createFeatureProvider(type);
1586
                data.setNew(true);
1587
                if (type.hasOID() && data.getOID() == null) {
1588
                        data.setOID(this.provider.createNewOID());
1589
                } else {
1590
                        data.setOID(this.getTemporalOID());
1591
                }
1592
                return data;
1593

    
1594
        }
1595

    
1596
        public EditableFeature createNewFeature(FeatureType type,
1597
                        boolean defaultValues)
1598
        throws DataException {
1599
                try {
1600
                        FeatureProvider data = createNewFeatureProvider(type);
1601
                        DefaultEditableFeature feature = new DefaultEditableFeature(this, data);
1602
                        if (defaultValues) {
1603
                                feature.initializeValues();
1604
                        }
1605
                        return feature;
1606
                } catch (Exception e) {
1607
                        throw new CreateFeatureException(e, getName());
1608
                }
1609
        }
1610

    
1611
        public EditableFeature createNewFeature(boolean defaultValues)
1612
        throws DataException {
1613
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1614
        }
1615

    
1616
        public EditableFeature createNewFeature() throws DataException {
1617
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1618
        }
1619

    
1620
        public EditableFeatureType createFeatureType() {
1621
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1622
                return ftype;
1623
        }
1624

    
1625
        public EditableFeatureType createFeatureType(String id) {
1626
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1627
                return ftype;
1628
        }
1629

    
1630

    
1631
        //
1632
        // ====================================================================
1633
        // Index related methods
1634
        //
1635

    
1636
        public FeatureIndexes getIndexes() {
1637
                return this.indexes;
1638
        }
1639

    
1640
        public FeatureIndex createIndex(FeatureType featureType,
1641
                        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1642
                checkNotInAppendMode();
1643
                FeatureIndexProviderServices index = null;
1644
                index = dataManager.createFeatureIndexProvider(null, this, featureType,
1645
                indexName, featureType.getAttributeDescriptor(attributeName));
1646
                try {
1647
                        index.fill();
1648
                } catch (FeatureIndexException e) {
1649
                        throw new InitializeException(index.getName(), e);
1650
                }
1651
                ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1652
                return index;
1653
        }
1654

    
1655
        public FeatureIndex createIndex(FeatureType featureType,
1656
                        String attributeName, String indexName, Observer observer) {
1657
                // TODO Implement observer interaction
1658
                throw new UnsupportedOperationException();
1659
        }
1660

    
1661
        //
1662
        // ====================================================================
1663
        // Transforms related methods
1664
        //
1665

    
1666
        public FeatureStoreTransforms getTransforms() {
1667
                return this.transforms;
1668
        }
1669

    
1670
        public FeatureQuery createFeatureQuery() {
1671
                return new DefaultFeatureQuery();
1672
        }
1673

    
1674
        public DataQuery createQuery() {
1675
                return createFeatureQuery();
1676
        }
1677

    
1678
        //
1679
        // ====================================================================
1680
        // UndoRedo related methods
1681
        //
1682

    
1683
        public boolean canRedo() {
1684
                return commands.canRedo();
1685
        }
1686

    
1687
        public boolean canUndo() {
1688
                return commands.canUndo();
1689
        }
1690

    
1691
        public void redo(int num) throws RedoException {
1692
                commands.redo(num);
1693
        }
1694

    
1695
        public void undo(int num) throws UndoException {
1696
                commands.undo(num);
1697
        }
1698

    
1699
        //
1700
        // ====================================================================
1701
        // Metadata related methods
1702
        //
1703

    
1704
        public Object getMetadataID() {
1705
                return this.provider.getSourceId();
1706
        }
1707

    
1708
        public void delegate(DynObject dynObject) {
1709
                this.metadata.delegate(dynObject);
1710
        }
1711

    
1712
        public DynClass getDynClass() {
1713
                return this.metadata.getDynClass();
1714
        }
1715

    
1716
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1717
                if( this.metadata.hasDynValue(name) ) {
1718
                        return this.metadata.getDynValue(name); 
1719
                }
1720
                if( METADATA_PROVIDER.equalsIgnoreCase(name) ) {
1721
                        return this.provider.getName();
1722
                } else if( METADATA_CONTAINERNAME.equalsIgnoreCase(name) ) {
1723
                        return this.provider.getSourceId();
1724
                } else if( METADATA_FEATURETYPE.equalsIgnoreCase(name) ) {
1725
                        try {
1726
                                return this.getDefaultFeatureType();
1727
                        } catch (DataException e) {
1728
                                return null;
1729
                        }
1730
                }
1731
                return this.metadata.getDynValue(name);
1732
        }
1733

    
1734
        public boolean hasDynValue(String name) {
1735
                return this.metadata.hasDynValue(name);
1736
        }
1737

    
1738
        public void implement(DynClass dynClass) {
1739
                this.metadata.implement(dynClass);
1740
        }
1741

    
1742
        public Object invokeDynMethod(String name, DynObject context)
1743
        throws DynMethodException {
1744
                return this.metadata.invokeDynMethod(this, name, context);
1745
        }
1746

    
1747
        public Object invokeDynMethod(int code, DynObject context)
1748
        throws DynMethodException {
1749
                return this.metadata.invokeDynMethod(this, code, context);
1750
        }
1751

    
1752
        public void setDynValue(String name, Object value)
1753
        throws DynFieldNotFoundException {
1754
                this.metadata.setDynValue(name, value);
1755

    
1756
        }
1757

    
1758
        /*
1759
         * (non-Javadoc)
1760
         *
1761
         * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1762
         */
1763
        public Set getMetadataChildren() {
1764
                return this.metadataChildren;
1765
        }
1766

    
1767
        /*
1768
         * (non-Javadoc)
1769
         *
1770
         * @see org.gvsig.metadata.Metadata#getMetadataName()
1771
         */
1772
        public String getMetadataName() {
1773
                return this.provider.getName();
1774
        }
1775

    
1776
        public FeatureTypeManager getFeatureTypeManager() {
1777
                return this.featureTypeManager;
1778
        }
1779

    
1780
        public long getFeatureCount() throws DataException {
1781
                if (featureCount == null) {
1782
                        featureCount = new Long(this.provider.getFeatureCount());
1783
                }
1784
                if (this.isEditing() && !this.isAppending()) {
1785
                        return featureCount.longValue()
1786
                                        - this.featureManager.getDeltaSize();
1787
                }
1788
                return featureCount.longValue();
1789
        }
1790

    
1791
        private Long getTemporalOID() {
1792
                return new Long(this.temporalOid++);
1793
        }
1794

    
1795
        public FeatureType getProviderFeatureType(String featureTypeId) {
1796
                if (featureTypeId == null) {
1797
                        return this.defaultFeatureType;
1798
                }
1799
                FeatureType type;
1800
                Iterator iter = this.featureTypes.iterator();
1801
                while (iter.hasNext()) {
1802
                        type = (FeatureType) iter.next();
1803
                        if (type.getId().equals(featureTypeId)) {
1804
                                return type;
1805
                        }
1806
                }
1807
                return null;
1808
        }
1809

    
1810
        public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1811
                return ((DefaultFeature) feature).getData();
1812
        }
1813

    
1814
        public DataStore getStore() {
1815
                return this;
1816
        }
1817

    
1818
        public FeatureStore getFeatureStore() {
1819
                return this;
1820
        }
1821

    
1822
        public void createCache(String name, DynObject parameters)
1823
        throws DataException {
1824
                cache = dataManager.createFeatureCacheProvider(name, parameters);
1825
                if (cache == null){
1826
                        throw new CreateException("FeaureCacheProvider", null);
1827
                }
1828
                cache.apply(this, provider);
1829
                provider = cache;
1830

    
1831
                featureCount = null;
1832
        }
1833

    
1834
        public FeatureCache getCache() {
1835
                return cache;
1836
        }
1837

    
1838
        public void clear() {
1839
                if (metadata != null) {
1840
                        metadata.clear();
1841
                }
1842
        }
1843

    
1844
        public String getProviderName() {
1845
                return this.provider.getName();
1846
        }
1847
}