Statistics
| Revision:

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

History | View | Annotate | Download (52.4 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.Map.Entry;
39
import java.util.Set;
40

    
41
import org.cresques.cts.IProjection;
42
import org.slf4j.Logger;
43
import org.slf4j.LoggerFactory;
44

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

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

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

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

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

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

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

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

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

    
176
        private DefaultDataManager dataManager = null;
177

    
178
        private FeatureStoreProvider provider = null;
179

    
180
        private DefaultFeatureIndexes indexes;
181

    
182
        private DefaultFeatureStoreTransforms transforms;
183

    
184
        private DelegatedDynObject metadata;
185
        private Set metadataChildren;
186

    
187
        private Long featureCount = null;
188

    
189
        private long temporalOid = 0;
190

    
191
        private FeatureCacheProvider cache;
192

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

    
202
    public DefaultFeatureStore() {
203

    
204
        }
205

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

    
209
                DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
210

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

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

    
228
        }
229

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

    
237
        public DataStoreParameters getParameters() {
238
                return parameters;
239
        }
240

    
241
        public int getMode() {
242
                return this.mode;
243
        }
244

    
245
        public DataManager getManager() {
246
                return this.dataManager;
247
        }
248

    
249
        public Iterator getChildren() {
250
                return this.provider.getChilds();
251
        }
252

    
253
        public FeatureStoreProvider getProvider() {
254
                return this.provider;
255
        }
256

    
257
        public FeatureManager getFeatureManager() {
258
                return this.featureManager;
259
        }
260

    
261
        public void setFeatureTypes(List types, FeatureType defaultType) {
262
                this.featureTypes = types;
263
                this.defaultFeatureType = defaultType;
264
        }
265

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

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

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

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

    
305
                if (this.featureTypeManager != null) {
306
                        this.featureTypeManager.dispose();
307
                        this.featureTypeManager = null;
308
                }
309

    
310
                this.featureManager = null;
311
                this.spatialManager = null;
312

    
313
                this.parameters = null;
314
                this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
315
                if (delegateObservable != null) {
316
                        this.delegateObservable.deleteObservers();
317
                        this.delegateObservable = null;
318
                }
319
        }
320

    
321
        public boolean allowWrite() {
322
                return this.provider.allowWrite();
323
        }
324

    
325
        public boolean canWriteGeometry(int geometryType) throws DataException {
326
                return this.provider.canWriteGeometry(geometryType, 0);
327
        }
328

    
329
        public DataServerExplorer getExplorer() throws ReadException,
330
                        ValidateDataParametersException {
331
                return this.provider.getExplorer();
332
        }
333

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

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

    
346
        public Envelope getEnvelope() throws DataException {
347
                if (this.mode == MODE_FULLEDIT) {
348
                        return this.spatialManager.getEnvelope();
349
                }
350
                return this.provider.getEnvelope();
351
        }
352

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

    
360
        public FeatureSelection createDefaultFeatureSelection()
361
        throws DataException {
362
                return new DefaultFeatureSelection(this);
363
        }
364

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

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

    
408

    
409
                }
410

    
411
                if (evaluatedAttr.isEmpty()) {
412
                        evaluatedAttr = null;
413
                }
414

    
415
                state.set("evaluatedAttributes", evaluatedAttr);
416
                state.set("defaultFeatureTypeId", defaultFeatureType.getId());
417

    
418
        }
419

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

    
428
                DataStoreParameters params = (DataStoreParameters) state.get("parameters");
429

    
430
                try {
431

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

    
468
                                }
469

    
470

    
471
                        }
472

    
473
                        String defFTypeid = state.getString("defaultFeatureTypeId");
474
                        FeatureType ftype = null;
475
                        if (!this.defaultFeatureType.getId().equals(
476
                                        state.getString("defaultFeatureTypeId"))) {
477

    
478
                                ftype = getFeatureType(defFTypeid);
479
                                if (ftype == null) {
480
                                        throw new PersistenceCantFindDefaultFeatureTypeException(this.getName(), defFTypeid);
481
                                }
482
                                this.defaultFeatureType = ftype;
483
                        }
484

    
485

    
486
                } catch (InitializeException e) {
487
                        throw new PersistenceException(e);
488
                } catch (DataException e) {
489
                        throw new PersistenceException(e);
490
                }
491

    
492
        }
493

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

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

    
554
        public void setSelection(DataSet selection)
555
        throws DataException {
556
                this.setSelection((FeatureSet) selection);
557
        }
558

    
559
        public DataSet createSelection() throws DataException {
560
                return createFeatureSelection();
561
        }
562

    
563
        public DataSet getSelection() throws DataException {
564
                return this.getFeatureSelection();
565
        }
566

    
567
    public void setSelection(FeatureSet selection) throws DataException {
568
        setSelection(selection, true);
569
    }
570

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

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

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

    
629
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
630
        }
631

    
632
        public FeatureSelection createFeatureSelection() throws DataException {
633
                return this.provider.createFeatureSelection();
634
        }
635

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

    
644
        //
645
        // ====================================================================
646
        // Gestion de notificaciones
647
        //
648

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

    
655
        }
656

    
657
        public void notifyChange(String notification, Feature feature) {
658
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
659
                                this, notification, feature));
660
        }
661

    
662
        public void notifyChange(String notification, Command command) {
663
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(
664
                                this, notification, command));
665
        }
666

    
667
        public void notifyChange(String notification, EditableFeatureType type) {
668
                delegateObservable.notifyObservers(new DefaultFeatureStoreNotification(this,
669
                                notification, type));
670
        }
671

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

    
684

    
685
        //
686
        // ====================================================================
687
        // Gestion de bloqueos
688
        //
689

    
690
        public boolean isLocksSupported() {
691
                return this.provider.isLocksSupported();
692
        }
693

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

    
705
        //
706
        // ====================================================================
707
        // Interface Observable
708
        //
709

    
710
        public void disableNotifications() {
711
                this.delegateObservable.disableNotifications();
712

    
713
        }
714

    
715
        public void enableNotifications() {
716
                this.delegateObservable.enableNotifications();
717
        }
718

    
719
        public void beginComplexNotification() {
720
                this.delegateObservable.beginComplexNotification();
721

    
722
        }
723

    
724
        public void endComplexNotification() {
725
                this.delegateObservable.endComplexNotification();
726

    
727
        }
728

    
729
        public void addObserver(Observer observer) {
730
                this.delegateObservable.addObserver(observer);
731

    
732
        }
733

    
734
        public void deleteObserver(Observer observer) {
735
                if (delegateObservable != null) {
736
                        this.delegateObservable.deleteObserver(observer);
737
                }
738
        }
739

    
740
        public void deleteObservers() {
741
                this.delegateObservable.deleteObservers();
742

    
743
        }
744

    
745
        //
746
        // ====================================================================
747
        // Interface Observer
748
        //
749
        // Usado para observar:
750
        // - su seleccion
751
        // - sus bloqueos
752
        // - sus recursos
753
        //
754

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

    
763
                } else if (observable instanceof FeatureStoreProvider) {
764
                        if (observable == this.provider) {
765

    
766
                        }
767

    
768
                }
769
        }
770

    
771
        //
772
        // ====================================================================
773
        // Edicion
774
        //
775

    
776
        private void newVersionOfUpdate() {
777
                this.versionOfUpdate++;
778
        }
779

    
780
        private long currentVersionOfUpdate() {
781
                return this.versionOfUpdate;
782
        }
783

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

    
791
        private void checkNotInAppendMode() throws IllegalStateException {
792
                if (mode == MODE_APPEND) {
793
                        throw new IllegalStateException(this.getName());
794
                }
795
        }
796

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

    
806
        private void exitEditingMode() {
807
                if (commands != null) {
808
                        commands.clear();
809
                        commands = null;
810
                }
811

    
812
                if (featureTypeManager != null) {
813
                        featureTypeManager.dispose();
814
                        featureTypeManager = null;
815

    
816
                }
817

    
818
                // TODO implementar un dispose para estos dos
819
                featureManager = null;
820
                spatialManager = null;
821

    
822
                featureCount = null;
823

    
824
                mode = MODE_QUERY;
825
                hasStrongChanges = true; // Lo deja a true por si las moscas
826
                hasInserts = true;
827
        }
828

    
829
        synchronized public void edit() throws DataException {
830
                edit(MODE_FULLEDIT);
831
        }
832

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

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

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

    
879
        public boolean isEditing() {
880
                return mode == MODE_FULLEDIT;
881
        }
882

    
883
        public boolean isAppending() {
884
                return mode == MODE_APPEND;
885
        }
886

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

    
898
                        FeatureType oldt = type.getSource().getCopy();
899
                        FeatureType newt = type.getNotEditableCopy();
900
                        commands.update(newt, oldt);
901

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

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

    
928
        private static EditableFeature lastChangedFeature = null;
929

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

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

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

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

    
991
                        Feature oldf = feature.getSource();
992
                        Feature newf = feature.getNotEditableCopy();
993
                        commands.update(newf, oldf);
994

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

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

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

    
1030
        public List getRedoInfos() {
1031
                if (isEditing() && commands != null) {
1032
                        return commands.getRedoInfos();
1033
                } else {
1034
                        return null;
1035
                }
1036
        }
1037

    
1038
        public List getUndoInfos() {
1039
                if (isEditing() && commands != null) {
1040
                        return commands.getUndoInfos();
1041
                } else {
1042
                        return null;
1043
                }
1044
        }
1045

    
1046
        public synchronized FeatureCommandsStack getCommandsStack()
1047
        throws DataException {
1048
                checkInEditingMode();
1049
                return commands;
1050
        }
1051

    
1052
        synchronized public void cancelEditing() throws DataException {
1053
                spatialManager.cancelModifies();
1054
                try {
1055
                        checkInEditingMode();
1056

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

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

    
1078
                        case MODE_APPEND:
1079
                                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1080
                                provider.endAppend();
1081
                                exitEditingMode();
1082
                                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1083
                                break;
1084

    
1085
                        case MODE_FULLEDIT:
1086
                                if (hasStrongChanges && !this.allowWrite()) {
1087
                                        throw new WriteNotAllowedException(getName());
1088
                                }
1089

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

    
1107
        public void beginEditingGroup(String description)
1108
        throws NeedEditingModeException {
1109
                checkInEditingMode();
1110
                commands.startComplex(description);
1111
        }
1112

    
1113
        public void endEditingGroup() throws NeedEditingModeException {
1114
                checkInEditingMode();
1115
                commands.endComplex();
1116
        }
1117

    
1118
        public boolean isAppendModeSupported() {
1119
                return this.provider.supportsAppendMode();
1120
        }
1121

    
1122

    
1123
        public void export(DataServerExplorer explorer, String provider, NewFeatureStoreParameters params)
1124
        throws DataException {
1125

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

    
1140
                        }
1141
                        explorer.add(provider, params, true);
1142

    
1143
                        DataManager manager = DALLocator.getDataManager();
1144
                        target = (FeatureStore) manager.openStore(provider, params);
1145
                        FeatureType targetType = target.getDefaultFeatureType();
1146

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

    
1178
        //
1179
        // ====================================================================
1180
        // Obtencion de datos
1181
        // getDataCollection, getFeatureCollection
1182
        //
1183

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

    
1191
        public DataSet getDataSet(DataQuery dataQuery)
1192
        throws DataException {
1193
                checkNotInAppendMode();
1194
                return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1195
        }
1196

    
1197
        public void getDataSet(Observer observer) throws DataException {
1198
                checkNotInAppendMode();
1199
                this.getFeatureSet(null, observer);
1200
        }
1201

    
1202
        public void getDataSet(DataQuery dataQuery, Observer observer)
1203
        throws DataException {
1204
                checkNotInAppendMode();
1205
                this.getFeatureSet((FeatureQuery) dataQuery, observer);
1206
        }
1207

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

    
1215
        public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1216
        throws DataException {
1217
                checkNotInAppendMode();
1218
                return new DefaultFeatureSet(this, featureQuery);
1219
        }
1220

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

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

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

    
1250
        public void getFeatureSet(Observer observer)
1251
        throws DataException {
1252
                checkNotInAppendMode();
1253
                this.getFeatureSet(null, observer);
1254
        }
1255

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

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

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

    
1285
                        }
1286

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

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

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

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

    
1331
                        featureType = this.transforms
1332
                        .getSourceFeatureTypeFrom(featureType);
1333

    
1334
                }
1335
                // TODO comprobar que el id es de este store
1336

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

    
1350
                if (!this.transforms.isEmpty()) {
1351
                        return this.transforms.applyTransform(feature, featureType);
1352
                }
1353
                return feature;
1354
        }
1355

    
1356
        //
1357
        // ====================================================================
1358
        // Gestion de features
1359
        //
1360

    
1361
        private FeatureType fixFeatureType(DefaultFeatureType type)
1362
        throws DataException {
1363
                FeatureType original = this.getDefaultFeatureType();
1364

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

    
1377
                                        }else if (type.isSubtypeOf(tmpType)) {
1378
                                                found = true;
1379
                                                original = tmpType;
1380
                                                break;
1381
                                        }
1382

    
1383
                                }
1384
                                if (!found) {
1385
                                        throw new IllegalFeatureTypeException(getName());
1386
                                }
1387
                        }
1388
                }
1389

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

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

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

    
1434
                }
1435

    
1436

    
1437
                return type;
1438
        }
1439

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

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

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

    
1510

    
1511
        public FeatureType getProviderDefaultFeatureType() {
1512
                return defaultFeatureType;
1513
        }
1514

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

    
1547
        public List getProviderFeatureTypes() throws DataException {
1548
                return Collections.unmodifiableList(this.featureTypes);
1549
        }
1550

    
1551
        public Feature createFeature(FeatureProvider data)
1552
        throws DataException {
1553
                DefaultFeature feature = new DefaultFeature(this, data);
1554
                return feature;
1555
        }
1556

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

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

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

    
1591
        }
1592

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

    
1608
        public EditableFeature createNewFeature(boolean defaultValues)
1609
        throws DataException {
1610
                return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1611
        }
1612

    
1613
        public EditableFeature createNewFeature() throws DataException {
1614
                return this.createNewFeature(this.getDefaultFeatureType(), true);
1615
        }
1616

    
1617
        public EditableFeatureType createFeatureType() {
1618
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1619
                return ftype;
1620
        }
1621

    
1622
        public EditableFeatureType createFeatureType(String id) {
1623
                DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1624
                return ftype;
1625
        }
1626

    
1627

    
1628
        //
1629
        // ====================================================================
1630
        // Index related methods
1631
        //
1632

    
1633
        public FeatureIndexes getIndexes() {
1634
                return this.indexes;
1635
        }
1636

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

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

    
1658
        //
1659
        // ====================================================================
1660
        // Transforms related methods
1661
        //
1662

    
1663
        public FeatureStoreTransforms getTransforms() {
1664
                return this.transforms;
1665
        }
1666

    
1667
        public FeatureQuery createFeatureQuery() {
1668
                return new DefaultFeatureQuery();
1669
        }
1670

    
1671
        public DataQuery createQuery() {
1672
                return createFeatureQuery();
1673
        }
1674

    
1675
        //
1676
        // ====================================================================
1677
        // UndoRedo related methods
1678
        //
1679

    
1680
        public boolean canRedo() {
1681
                return commands.canRedo();
1682
        }
1683

    
1684
        public boolean canUndo() {
1685
                return commands.canUndo();
1686
        }
1687

    
1688
        public void redo(int num) throws RedoException {
1689
                commands.redo(num);
1690
        }
1691

    
1692
        public void undo(int num) throws UndoException {
1693
                commands.undo(num);
1694
        }
1695

    
1696
        //
1697
        // ====================================================================
1698
        // Metadata related methods
1699
        //
1700

    
1701
        public Object getMetadataID() {
1702
                return this.provider.getSourceId();
1703
        }
1704

    
1705
        public void delegate(DynObject dynObject) {
1706
                this.metadata.delegate(dynObject);
1707
        }
1708

    
1709
        public DynClass getDynClass() {
1710
                return this.metadata.getDynClass();
1711
        }
1712

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

    
1731
        public boolean hasDynValue(String name) {
1732
                return this.metadata.hasDynValue(name);
1733
        }
1734

    
1735
        public void implement(DynClass dynClass) {
1736
                this.metadata.implement(dynClass);
1737
        }
1738

    
1739
        public Object invokeDynMethod(String name, DynObject context)
1740
        throws DynMethodException {
1741
                return this.metadata.invokeDynMethod(this, name, context);
1742
        }
1743

    
1744
        public Object invokeDynMethod(int code, DynObject context)
1745
        throws DynMethodException {
1746
                return this.metadata.invokeDynMethod(this, code, context);
1747
        }
1748

    
1749
        public void setDynValue(String name, Object value)
1750
        throws DynFieldNotFoundException {
1751
                this.metadata.setDynValue(name, value);
1752

    
1753
        }
1754

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

    
1764
        /*
1765
         * (non-Javadoc)
1766
         *
1767
         * @see org.gvsig.metadata.Metadata#getMetadataName()
1768
         */
1769
        public String getMetadataName() {
1770
                return this.provider.getProviderName();
1771
        }
1772

    
1773
        public FeatureTypeManager getFeatureTypeManager() {
1774
                return this.featureTypeManager;
1775
        }
1776

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

    
1788
        private Long getTemporalOID() {
1789
                return new Long(this.temporalOid++);
1790
        }
1791

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

    
1807
        public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1808
                return ((DefaultFeature) feature).getData();
1809
        }
1810

    
1811
        public DataStore getStore() {
1812
                return this;
1813
        }
1814

    
1815
        public FeatureStore getFeatureStore() {
1816
                return this;
1817
        }
1818

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

    
1828
                featureCount = null;
1829
        }
1830

    
1831
        public FeatureCache getCache() {
1832
                return cache;
1833
        }
1834

    
1835
        public void clear() {
1836
                if (metadata != null) {
1837
                        metadata.clear();
1838
                }
1839
        }
1840

    
1841
        public String getName() {
1842
                return this.provider.getName();
1843
        }
1844

    
1845
        public String getFullName() {
1846
                return this.provider.getFullName();
1847
        }
1848

    
1849
        public String getProviderName() {
1850
                return this.provider.getProviderName();
1851
        }
1852
}