Statistics
| Revision:

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

History | View | Annotate | Download (62.6 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

    
1853
    public boolean isKnownEnvelope() {
1854
        return this.provider.isKnownEnvelope();
1855
    }
1856

    
1857
    public boolean hasRetrievedFeaturesLimit() {
1858
        return this.provider.hasRetrievedFeaturesLimit();
1859
    }
1860

    
1861
    public int getRetrievedFeaturesLimit() {
1862
        return this.provider.getRetrievedFeaturesLimit();
1863
    }
1864
}