Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2023 / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 34360

History | View | Annotate | Download (62.7 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
                        notifyChange(new DefaultFeatureStoreNotification(
652
                this, notification));
653
        }
654

    
655
    }
656

    
657
        public void notifyChange(String notification, FeatureProvider data) {
658
                try {
659
                        notifyChange(notification, createFeature(data));
660
                } catch (DataException ex) {
661
                        logger.error("Error notifying about the notification: "
662
                                        + notification + ", with the data: " + data, ex);
663
                }
664
        }
665

    
666
    public void notifyChange(String notification, Feature feature) {
667
                notifyChange(new DefaultFeatureStoreNotification(
668
            this, notification, feature));
669
    }
670

    
671
    public void notifyChange(String notification, Command command) {
672
                notifyChange(new DefaultFeatureStoreNotification(
673
            this, notification, command));
674
    }
675

    
676
    public void notifyChange(String notification, EditableFeatureType type) {
677
                notifyChange(new DefaultFeatureStoreNotification(this,
678
            notification, type));
679
    }
680

    
681
        public void notifyChange(FeatureStoreNotification storeNotification) {
682
                delegateObservable.notifyObservers(storeNotification);
683
        }
684

    
685
    public void notifyChange(String notification, Resource resource) {
686
                notifyChange(new DefaultFeatureStoreNotification(this,
687
            FeatureStoreNotification.RESOURCE_CHANGED));
688
    }
689

    
690

    
691
    //
692
    // ====================================================================
693
    // Gestion de bloqueos
694
    //
695

    
696
    public boolean isLocksSupported() {
697
        return this.provider.isLocksSupported();
698
    }
699

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

    
711
    //
712
    // ====================================================================
713
    // Interface Observable
714
    //
715

    
716
    public void disableNotifications() {
717
        this.delegateObservable.disableNotifications();
718

    
719
    }
720

    
721
    public void enableNotifications() {
722
        this.delegateObservable.enableNotifications();
723
    }
724

    
725
    public void beginComplexNotification() {
726
        this.delegateObservable.beginComplexNotification();
727

    
728
    }
729

    
730
    public void endComplexNotification() {
731
        this.delegateObservable.endComplexNotification();
732

    
733
    }
734

    
735
    public void addObserver(Observer observer) {
736
        this.delegateObservable.addObserver(observer);
737

    
738
    }
739

    
740
    public void deleteObserver(Observer observer) {
741
        if (delegateObservable != null) {
742
            this.delegateObservable.deleteObserver(observer);
743
        }
744
    }
745

    
746
    public void deleteObservers() {
747
        this.delegateObservable.deleteObservers();
748

    
749
    }
750

    
751
    //
752
    // ====================================================================
753
    // Interface Observer
754
    //
755
    // Usado para observar:
756
    // - su seleccion
757
    // - sus bloqueos
758
    // - sus recursos
759
    //
760

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

    
769
        } else if (observable instanceof FeatureStoreProvider) {
770
            if (observable == this.provider) {
771

    
772
            }
773

    
774
        }
775
    }
776

    
777
    //
778
    // ====================================================================
779
    // Edicion
780
    //
781

    
782
    private void newVersionOfUpdate() {
783
        this.versionOfUpdate++;
784
    }
785

    
786
    private long currentVersionOfUpdate() {
787
        return this.versionOfUpdate;
788
    }
789

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

    
797
    private void checkNotInAppendMode() throws IllegalStateException {
798
        if (mode == MODE_APPEND) {
799
            throw new IllegalStateException(this.getName());
800
        }
801
    }
802

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

    
812
    private void exitEditingMode() {
813
        if (commands != null) {
814
            commands.clear();
815
            commands = null;
816
        }
817

    
818
        if (featureTypeManager != null) {
819
            featureTypeManager.dispose();
820
            featureTypeManager = null;
821

    
822
        }
823

    
824
        // TODO implementar un dispose para estos dos
825
        featureManager = null;
826
        spatialManager = null;
827

    
828
        featureCount = null;
829

    
830
        mode = MODE_QUERY;
831
        hasStrongChanges = true; // Lo deja a true por si las moscas
832
        hasInserts = true;
833
    }
834

    
835
    synchronized public void edit() throws DataException {
836
        edit(MODE_FULLEDIT);
837
    }
838

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

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

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

    
885
    public boolean isEditing() {
886
        return mode == MODE_FULLEDIT;
887
    }
888

    
889
    public boolean isAppending() {
890
        return mode == MODE_APPEND;
891
    }
892

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

    
904
            FeatureType oldt = type.getSource().getCopy();
905
            FeatureType newt = type.getNotEditableCopy();
906
            commands.update(newt, oldt);
907

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

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

    
934
    private static EditableFeature lastChangedFeature = null;
935

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

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

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

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

    
997
            Feature oldf = feature.getSource();
998
            Feature newf = feature.getNotEditableCopy();
999
            commands.update(newf, oldf);
1000

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

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

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

    
1036
    public List getRedoInfos() {
1037
        if (isEditing() && commands != null) {
1038
            return commands.getRedoInfos();
1039
        } else {
1040
            return null;
1041
        }
1042
    }
1043

    
1044
    public List getUndoInfos() {
1045
        if (isEditing() && commands != null) {
1046
            return commands.getUndoInfos();
1047
        } else {
1048
            return null;
1049
        }
1050
    }
1051

    
1052
    public synchronized FeatureCommandsStack getCommandsStack()
1053
    throws DataException {
1054
        checkInEditingMode();
1055
        return commands;
1056
    }
1057

    
1058
    synchronized public void cancelEditing() throws DataException {
1059
        spatialManager.cancelModifies();
1060
        try {
1061
            checkInEditingMode();
1062

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

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

    
1084
            case MODE_APPEND:
1085
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1086
                provider.endAppend();
1087
                exitEditingMode();
1088
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1089
                break;
1090

    
1091
            case MODE_FULLEDIT:
1092
                if (hasStrongChanges && !this.allowWrite()) {
1093
                    throw new WriteNotAllowedException(getName());
1094
                }
1095

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

    
1113
    public void beginEditingGroup(String description)
1114
    throws NeedEditingModeException {
1115
        checkInEditingMode();
1116
        commands.startComplex(description);
1117
    }
1118

    
1119
    public void endEditingGroup() throws NeedEditingModeException {
1120
        checkInEditingMode();
1121
        commands.endComplex();
1122
    }
1123

    
1124
    public boolean isAppendModeSupported() {
1125
        return this.provider.supportsAppendMode();
1126
    }
1127

    
1128

    
1129
    public void export(DataServerExplorer explorer, String provider, NewFeatureStoreParameters params)
1130
    throws DataException {
1131

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

    
1146
            }
1147
            explorer.add(provider, params, true);
1148

    
1149
            DataManager manager = DALLocator.getDataManager();
1150
            target = (FeatureStore) manager.openStore(provider, params);
1151
            FeatureType targetType = target.getDefaultFeatureType();
1152

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

    
1184
    //
1185
    // ====================================================================
1186
    // Obtencion de datos
1187
    // getDataCollection, getFeatureCollection
1188
    //
1189

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

    
1197
    public DataSet getDataSet(DataQuery dataQuery)
1198
    throws DataException {
1199
        checkNotInAppendMode();
1200
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1201
    }
1202

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

    
1208
    public void getDataSet(DataQuery dataQuery, Observer observer)
1209
    throws DataException {
1210
        checkNotInAppendMode();
1211
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1212
    }
1213

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

    
1221
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1222
    throws DataException {
1223
        checkNotInAppendMode();
1224
        return new DefaultFeatureSet(this, featureQuery);
1225
    }
1226

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

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

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

    
1256
    public void getFeatureSet(Observer observer)
1257
    throws DataException {
1258
        checkNotInAppendMode();
1259
        this.getFeatureSet(null, observer);
1260
    }
1261

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

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

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

    
1291
            }
1292

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

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

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

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

    
1337
            featureType = this.transforms
1338
            .getSourceFeatureTypeFrom(featureType);
1339

    
1340
        }
1341
        // TODO comprobar que el id es de este store
1342

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

    
1356
        if (!this.transforms.isEmpty()) {
1357
            return this.transforms.applyTransform(feature, featureType);
1358
        }
1359
        return feature;
1360
    }
1361

    
1362
    //
1363
    // ====================================================================
1364
    // Gestion de features
1365
    //
1366

    
1367
    private FeatureType fixFeatureType(DefaultFeatureType type)
1368
    throws DataException {
1369
        FeatureType original = this.getDefaultFeatureType();
1370

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

    
1383
                    }else if (type.isSubtypeOf(tmpType)) {
1384
                        found = true;
1385
                        original = tmpType;
1386
                        break;
1387
                    }
1388

    
1389
                }
1390
                if (!found) {
1391
                    throw new IllegalFeatureTypeException(getName());
1392
                }
1393
            }
1394
        }
1395

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

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

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

    
1440
        }
1441

    
1442

    
1443
        return type;
1444
    }
1445

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

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

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

    
1516

    
1517
    public FeatureType getProviderDefaultFeatureType() {
1518
        return defaultFeatureType;
1519
    }
1520

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

    
1553
    public List getProviderFeatureTypes() throws DataException {
1554
        return Collections.unmodifiableList(this.featureTypes);
1555
    }
1556

    
1557
    public Feature createFeature(FeatureProvider data)
1558
    throws DataException {
1559
        DefaultFeature feature = new DefaultFeature(this, data);
1560
        return feature;
1561
    }
1562

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

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

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

    
1597
    }
1598

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

    
1614
    public EditableFeature createNewFeature(boolean defaultValues)
1615
    throws DataException {
1616
        return this.createNewFeature(this.getDefaultFeatureType(), defaultValues);
1617
    }
1618

    
1619
    public EditableFeature createNewFeature() throws DataException {
1620
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1621
    }
1622

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

    
1628
    public EditableFeatureType createFeatureType(String id) {
1629
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1630
        return ftype;
1631
    }
1632

    
1633

    
1634
    //
1635
    // ====================================================================
1636
    // Index related methods
1637
    //
1638

    
1639
    public FeatureIndexes getIndexes() {
1640
        return this.indexes;
1641
    }
1642

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

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

    
1664
    //
1665
    // ====================================================================
1666
    // Transforms related methods
1667
    //
1668

    
1669
    public FeatureStoreTransforms getTransforms() {
1670
        return this.transforms;
1671
    }
1672

    
1673
    public FeatureQuery createFeatureQuery() {
1674
        return new DefaultFeatureQuery();
1675
    }
1676

    
1677
    public DataQuery createQuery() {
1678
        return createFeatureQuery();
1679
    }
1680

    
1681
    //
1682
    // ====================================================================
1683
    // UndoRedo related methods
1684
    //
1685

    
1686
    public boolean canRedo() {
1687
        return commands.canRedo();
1688
    }
1689

    
1690
    public boolean canUndo() {
1691
        return commands.canUndo();
1692
    }
1693

    
1694
    public void redo(int num) throws RedoException {
1695
        commands.redo(num);
1696
    }
1697

    
1698
    public void undo(int num) throws UndoException {
1699
        commands.undo(num);
1700
    }
1701

    
1702
    //
1703
    // ====================================================================
1704
    // Metadata related methods
1705
    //
1706

    
1707
    public Object getMetadataID() {
1708
        return this.provider.getSourceId();
1709
    }
1710

    
1711
    public void delegate(DynObject dynObject) {
1712
        this.metadata.delegate(dynObject);
1713
    }
1714

    
1715
    public DynClass getDynClass() {
1716
        return this.metadata.getDynClass();
1717
    }
1718

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

    
1737
    public boolean hasDynValue(String name) {
1738
        return this.metadata.hasDynValue(name);
1739
    }
1740

    
1741
    public void implement(DynClass dynClass) {
1742
        this.metadata.implement(dynClass);
1743
    }
1744

    
1745
    public Object invokeDynMethod(String name, DynObject context)
1746
    throws DynMethodException {
1747
        return this.metadata.invokeDynMethod(this, name, context);
1748
    }
1749

    
1750
    public Object invokeDynMethod(int code, DynObject context)
1751
    throws DynMethodException {
1752
        return this.metadata.invokeDynMethod(this, code, context);
1753
    }
1754

    
1755
    public void setDynValue(String name, Object value)
1756
    throws DynFieldNotFoundException {
1757
        this.metadata.setDynValue(name, value);
1758

    
1759
    }
1760

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

    
1770
    /*
1771
     * (non-Javadoc)
1772
     *
1773
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1774
     */
1775
    public String getMetadataName() {
1776
        return this.provider.getProviderName();
1777
    }
1778

    
1779
    public FeatureTypeManager getFeatureTypeManager() {
1780
        return this.featureTypeManager;
1781
    }
1782

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

    
1794
    private Long getTemporalOID() {
1795
        return new Long(this.temporalOid++);
1796
    }
1797

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

    
1813
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1814
        return ((DefaultFeature) feature).getData();
1815
    }
1816

    
1817
    public DataStore getStore() {
1818
        return this;
1819
    }
1820

    
1821
    public FeatureStore getFeatureStore() {
1822
        return this;
1823
    }
1824

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

    
1834
        featureCount = null;
1835
    }
1836

    
1837
    public FeatureCache getCache() {
1838
        return cache;
1839
    }
1840

    
1841
    public void clear() {
1842
        if (metadata != null) {
1843
            metadata.clear();
1844
        }
1845
    }
1846

    
1847
    public String getName() {
1848
        return this.provider.getName();
1849
    }
1850

    
1851
    public String getFullName() {
1852
        return this.provider.getFullName();
1853
    }
1854

    
1855
    public String getProviderName() {
1856
        return this.provider.getProviderName();
1857
    }
1858

    
1859
    public boolean isKnownEnvelope() {
1860
        return this.provider.isKnownEnvelope();
1861
    }
1862

    
1863
    public boolean hasRetrievedFeaturesLimit() {
1864
        return this.provider.hasRetrievedFeaturesLimit();
1865
    }
1866

    
1867
    public int getRetrievedFeaturesLimit() {
1868
        return this.provider.getRetrievedFeaturesLimit();
1869
    }
1870
}