Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 43841

History | View | Annotate | Download (89.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.fmap.dal.feature.impl;
26

    
27
import org.gvsig.fmap.dal.feature.impl.editing.memory.SpatialManager;
28
import org.gvsig.fmap.dal.feature.impl.editing.memory.FeatureTypeManager;
29
import org.gvsig.fmap.dal.feature.impl.editing.memory.FeatureManager;
30
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
31

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

    
43
import org.apache.commons.io.FilenameUtils;
44
import org.apache.commons.lang3.StringUtils;
45
import org.cresques.cts.IProjection;
46

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

    
166
import org.slf4j.Logger;
167
import org.slf4j.LoggerFactory;
168

    
169
public class DefaultFeatureStore extends AbstractDisposable implements
170
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
171

    
172
    private static final Logger LOG = LoggerFactory
173
        .getLogger(DefaultFeatureStore.class);
174

    
175
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
176

    
177
    private DataStoreParameters parameters = null;
178
    private FeatureSelection selection;
179
    private FeatureLocks locks;
180

    
181
    private DelegateWeakReferencingObservable delegateObservable =
182
        new DelegateWeakReferencingObservable(this);
183

    
184
    private FeatureCommandsStack commands;
185
    
186
    /*
187
    TODO: Sustituir estos tres manager por un EditingManager
188
    */
189
    private FeatureTypeManager featureTypeManager;
190
    private FeatureManager featureManager;
191
    private SpatialManager spatialManager;
192

    
193
    private FeatureType defaultFeatureType = null;
194
    private List featureTypes = new ArrayList();
195

    
196
    private int mode = MODE_QUERY;
197
    private long versionOfUpdate = 0;
198
    private boolean hasStrongChanges = true;
199
    private boolean hasInserts = true;
200

    
201
    private DefaultDataManager dataManager = null;
202

    
203
    private FeatureStoreProvider provider = null;
204

    
205
    private DefaultFeatureIndexes indexes;
206

    
207
    private DefaultFeatureStoreTransforms transforms;
208

    
209
    DelegatedDynObject metadata;
210

    
211
    private Set metadataChildren;
212

    
213
    private Long featureCount = null;
214

    
215
    private long temporalOid = 0;
216

    
217
    private FeatureCacheProvider cache;
218

    
219
    StateInformation state;
220

    
221
    FeatureStoreTimeSupport timeSupport;
222

    
223

    
224
    private class StateInformation extends HashMap<Object, Object> {
225

    
226
        private static final long serialVersionUID = 4109026189635185666L;
227

    
228
        private boolean broken;
229
        private Throwable breakingsCause;
230

    
231
        @SuppressWarnings("OverridableMethodCallInConstructor")
232
        public StateInformation() {
233
            this.clear();
234
        }
235

    
236
        @Override
237
        public void clear() {
238
            this.broken = false;
239
            this.breakingsCause = null;
240
            super.clear();
241
        }
242

    
243
        public boolean isBroken() {
244
            return this.broken;
245
        }
246

    
247
        public void broken() {
248
            this.broken = true;
249
        }
250

    
251
        public Throwable getBreakingsCause() {
252
            return this.breakingsCause;
253
        }
254

    
255
        public void setBreakingsCause(Throwable cause) {
256
            if( this.breakingsCause==null ) {
257
                this.breakingsCause = cause;
258
            }
259
            this.broken = true;
260
        }
261
    }
262

    
263

    
264

    
265
    /*
266
     * TODO:
267
     *
268
     * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
269
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
270
     * featureType al que se le han cambiado las reglas de validacion cuando
271
     * hasStrongChanges=false.
272
     */
273

    
274
    public DefaultFeatureStore() {
275
        this.state = new StateInformation();
276
    }
277

    
278
    @Override
279
    public void intialize(DataManager dataManager,
280
        DataStoreParameters parameters) throws InitializeException {
281

    
282
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
283

    
284
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
285
            FeatureStore.METADATA_DEFINITION_NAME,
286
            MetadataManager.METADATA_NAMESPACE
287
        );
288

    
289
        this.dataManager = (DefaultDataManager) dataManager;
290

    
291
        this.parameters = parameters;
292
        this.transforms = new DefaultFeatureStoreTransforms(this);
293
        try {
294
            indexes = new DefaultFeatureIndexes(this);
295
        } catch (DataException e) {
296
            throw new InitializeException(e);
297
        }
298

    
299
    }
300

    
301
    @Override
302
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
303
        this.provider = (FeatureStoreProvider) provider;
304
        this.delegate((DynObject) provider);
305
        this.metadataChildren = new HashSet();
306
        this.metadataChildren.add(provider);
307
    }
308

    
309
    @Override
310
    public DataStoreParameters getParameters() {
311
        return parameters;
312
    }
313

    
314
    public int getMode() {
315
        return this.mode;
316
    }
317

    
318
    @Override
319
    public DataManager getManager() {
320
        return this.dataManager;
321
    }
322

    
323
    @Override
324
    public Iterator getChildren() {
325
        return this.provider.getChilds();
326
    }
327

    
328
    @Override
329
    public FeatureStoreProvider getProvider() {
330
        return this.provider;
331
    }
332

    
333
    public FeatureManager getFeatureManager() {
334
        return this.featureManager;
335
    }
336

    
337
    @Override
338
    public void setFeatureTypes(List types, FeatureType defaultType) {
339
        this.featureTypes = types;
340
        this.defaultFeatureType = defaultType;
341
    }
342

    
343
    public void open() throws OpenException {
344
        if (this.mode != MODE_QUERY) {
345
            // TODO: Se puede hacer un open estando en edicion ?
346
            try {
347
                throw new IllegalStateException();
348
            } catch(Exception ex) {
349
                LOG.warn("Opening a store in editing/append mode ("+this.getFullName()+").",ex);
350
            }
351
        }
352
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
353
        this.provider.open();
354
        this.notifyChange(DataStoreNotification.AFTER_OPEN);
355
    }
356

    
357
    @Override
358
    public void refresh() throws OpenException, InitializeException {
359
        if (this.mode != MODE_QUERY) {
360
            throw new IllegalStateException();
361
        }
362
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
363
        if( state.isBroken() ) {
364
            this.load(state);
365
        } else {
366
            this.featureCount = null;
367
            this.provider.refresh();
368
        }
369
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
370
    }
371

    
372
    public void close() throws CloseException {
373
        if (this.mode != MODE_QUERY) {
374
            // TODO: Se puede hacer un close estando en edicion ?
375
            try {
376
                throw new IllegalStateException();
377
            } catch(Exception ex) {
378
                LOG.warn("Clossing a store in editing/append mode ("+this.getFullName()+").",ex);
379
            }
380
        }
381
        this.notifyChange(DataStoreNotification.BEFORE_CLOSE);
382
        this.featureCount = null;
383
        this.provider.close();
384
        this.notifyChange(DataStoreNotification.AFTER_CLOSE);
385
    }
386

    
387
    @Override
388
    protected void doDispose() throws BaseException {
389
        if (this.mode != MODE_QUERY) {
390
            // TODO: Se puede hacer un dispose estando en edicion ?
391
            try {
392
                throw new IllegalStateException();
393
            } catch(Exception ex) {
394
                LOG.warn("Dispossing a store in editing/append mode ("+this.getFullName()+").",ex);
395
            }
396
        }
397
        this.notifyChange(DataStoreNotification.BEFORE_DISPOSE);
398
        this.disposeIndexes();
399
        if( this.provider!=null ) {
400
            this.provider.dispose();
401
        }
402
        if (this.selection != null) {
403
            this.selection.dispose();
404
            this.selection = null;
405
        }
406
        this.commands = null;
407
        this.featureCount = null;
408
        if (this.locks != null) {
409
            // this.locks.dispose();
410
            this.locks = null;
411
        }
412

    
413
        if (this.featureTypeManager != null) {
414
            this.featureTypeManager.dispose();
415
            this.featureTypeManager = null;
416
        }
417

    
418
        this.featureManager = null;
419
        this.spatialManager = null;
420

    
421
        this.parameters = null;
422
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
423
        if (delegateObservable != null) {
424
            this.delegateObservable.deleteObservers();
425
            this.delegateObservable = null;
426
        }
427
    }
428

    
429
    @Override
430
    public boolean allowWrite() {
431
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
432
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
433
            return false;
434
        }
435
        return this.provider.allowWrite();
436
    }
437

    
438
    @Override
439
    public boolean canWriteGeometry(int geometryType) throws DataException {
440
        return this.provider.canWriteGeometry(geometryType, 0);
441
    }
442

    
443
    @Override
444
    public DataServerExplorer getExplorer() throws ReadException,
445
        ValidateDataParametersException {
446
        if( this.state.isBroken() ) {
447
            try {
448
                return this.provider.getExplorer();
449
            } catch(Throwable th) {
450
                return null;
451
            }
452
        } else {
453
            return this.provider.getExplorer();
454
        }
455
    }
456

    
457
    /*
458
     * public Metadata getMetadata() throws MetadataNotFoundException {
459
     * // TODO:
460
     * // Si el provider devuelbe null habria que ver de construir aqui
461
     * // los metadatos basicos, como el Envelope y el SRS.
462
     *
463
     * // TODO: Estando en edicion el Envelope deberia de
464
     * // actualizarse usando el spatialManager
465
     * return this.provider.getMetadata();
466
     * }
467
     */
468

    
469
    @Override
470
    public Envelope getEnvelope() throws DataException {
471
        if (this.mode == MODE_FULLEDIT) {
472
                // Just in case another thread tries to write in the store
473
                synchronized (this) {
474
                        return this.spatialManager.getEnvelope();
475
                        }
476
        }
477
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
478
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
479
        }
480
        return this.provider.getEnvelope();
481
    }
482

    
483
    /**
484
     * @throws org.gvsig.fmap.dal.exception.DataException
485
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
486
     */
487
    @Override
488
    public IProjection getSRSDefaultGeometry() throws DataException {
489
        return this.getDefaultFeatureType().getDefaultSRS();
490
    }
491

    
492
    @Override
493
    public FeatureSelection createDefaultFeatureSelection()
494
        throws DataException {
495
        return new DefaultFeatureSelection(this);
496
    }
497

    
498
    @Override
499
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
500
        throws DataException {
501
        if (type.hasOID()) {
502
            return new DefaultFeatureProvider(type,
503
                this.provider.createNewOID());
504
        }
505
        return new DefaultFeatureProvider(type);
506
    }
507

    
508
    @Override
509
    public void saveToState(PersistentState state) throws PersistenceException {
510
        /*if (this.mode != FeatureStore.MODE_QUERY) {
511
            throw new PersistenceException(new IllegalStateException(
512
                this.getName()));
513
        }*/
514
        state.set("dataStoreName", this.getName());
515
        state.set("parameters", this.parameters);
516
        state.set("selection", this.selection);
517
        state.set("transforms", this.transforms);
518
        // TODO locks persistence
519
        // state.set("locks", this.locks);
520
        // TODO indexes persistence
521
        // state.set("indexes", this.indexes);
522
        Map evaluatedAttr = new HashMap(1);
523
        Iterator iterType = featureTypes.iterator();
524
        Iterator iterAttr;
525
        FeatureType type;
526
        DefaultFeatureAttributeDescriptor attr;
527
        List attrs;
528
        while (iterType.hasNext()) {
529
            type = (FeatureType) iterType.next();
530
            attrs = new ArrayList();
531
            iterAttr = type.iterator();
532
            while (iterAttr.hasNext()) {
533
                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
534
                if ((attr.getEvaluator() != null)
535
                    && (attr.getEvaluator() instanceof Persistent)) {
536
                    attrs.add(attr);
537
                }
538
            }
539
            if (!attrs.isEmpty()) {
540
                evaluatedAttr.put(type.getId(), attrs);
541
            }
542

    
543
        }
544

    
545
        if (evaluatedAttr.isEmpty()) {
546
            evaluatedAttr = null;
547
        }
548

    
549
        state.set("evaluatedAttributes", evaluatedAttr);
550
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
551

    
552
    }
553

    
554
    @Override
555
    public void loadFromState(final PersistentState persistentState)
556
        throws PersistenceException {
557
        if (this.provider != null) {
558
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
559
        }
560
        if (this.getManager() == null) {
561
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
562
        }
563
        state.clear();
564
        try {
565
            state.put("parameters", persistentState.get("parameters"));
566
        } catch(Throwable th) {
567
            state.setBreakingsCause(th);
568
        }
569
        try {
570
            state.put("selection", persistentState.get("selection"));
571
        } catch(Throwable th) {
572
            state.setBreakingsCause(th);
573
        }
574
        try {
575
            state.put("transforms",  persistentState.get("transforms"));
576
        } catch(Throwable th) {
577
            state.setBreakingsCause(th);
578
        }
579
        try {
580
            state.put("evaluatedAttributes",  persistentState.get("evaluatedAttributes"));
581
        } catch(Throwable th) {
582
            state.setBreakingsCause(th);
583
        }
584
        try {
585
            state.put("defaultFeatureTypeId", persistentState.getString("defaultFeatureTypeId"));
586
        } catch(Throwable th) {
587
            state.setBreakingsCause(th);
588
        }
589
        load(state);
590
    }
591

    
592
    private void load(StateInformation state) {
593
        this.featureTypes = new ArrayList();
594
        this.defaultFeatureType = null;
595
        this.featureCount = null;
596

    
597
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
598
        try {
599
            intialize(dataManager, params);
600
        } catch(Throwable th) {
601
            state.setBreakingsCause(th);
602
        }
603

    
604
        try {
605
            DataStoreProvider prov = dataManager.createProvider(
606
                getStoreProviderServices(),
607
                params
608
            );
609
            setProvider(prov);
610
        } catch(Throwable th) {
611
            state.setBreakingsCause(th);
612
        }
613

    
614
        try {
615
            selection = (FeatureSelection) state.get("selection");
616
        } catch(Throwable th) {
617
            state.setBreakingsCause(th);
618
        }
619

    
620
        try {
621
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
622
            this.transforms.setFeatureStore(this);
623
            for( FeatureStoreTransform transform : this.transforms ) {
624
                try {
625
                    transform.setUp();
626
                } catch(Throwable th) {
627
                    state.setBreakingsCause(th);
628
                }
629
            }
630
        } catch(Throwable th) {
631
            state.setBreakingsCause(th);
632
        }
633

    
634
        try {
635
            Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
636
            if ((evaluatedAttributes != null) && !evaluatedAttributes.isEmpty()) {
637
                    Iterator iterEntries = evaluatedAttributes.entrySet().iterator();
638
                    while (iterEntries.hasNext()) {
639
                            Entry entry = (Entry) iterEntries.next();
640
                            List attrs = (List) entry.getValue();
641
                            if (attrs.isEmpty()) {
642
                                    continue;
643
                            }
644
                            int fTypePos = -1;
645
                            DefaultFeatureType type = null;
646
                            for (int i = 0; i < featureTypes.size(); i++) {
647
                                    type = (DefaultFeatureType) featureTypes.get(i);
648
                                    if (type.getId().equals(entry.getKey())) {
649
                                            fTypePos = i;
650
                                            break;
651
                                    }
652
                            }
653
                            if (type == null) {
654
                                    throw new PersistenceCantFindFeatureTypeException(
655
                                            getName(), (String) entry.getKey());
656
                            }
657
                            DefaultEditableFeatureType eType = (DefaultEditableFeatureType) type.getEditable();
658
                            Iterator<FeatureAttributeDescriptor> iterAttr = attrs.iterator();
659
                            while (iterAttr.hasNext()) {
660
                                    FeatureAttributeDescriptor attr = iterAttr.next();
661
                                    eType.addLike(attr);
662
                            }
663
                            featureTypes.set(fTypePos, eType.getNotEditableCopy());
664

    
665
                    }
666

    
667
            }
668
        } catch(Throwable th) {
669
            state.setBreakingsCause(th);
670
        }
671

    
672

    
673
        try {
674
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
675
            FeatureType ftype;
676

    
677
            if (defaultFeatureType == null ||
678
                    defaultFeatureType.getId() == null ||
679
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
680

    
681
                    ftype = getFeatureType(defaultFeatureTypeId);
682
                    if (ftype == null) {
683
                            /*
684
                             * Un error en el m?todo de PostgreSQL getName(), hace que
685
                             * el nombre del featureType sea valor retornado por el getProviderName()
686
                             * De momento se pone este parche para apa?arlo y poder mantener compatibilidad
687
                             * con proyectos antiguos (2.1 y 2.2)
688
                             */
689
                            ftype = getFeatureType(getName());
690
                            if(ftype == null ) {
691
                                    throw new RuntimeException("Can't locate feature type");
692
                            }
693
                    }
694
                    defaultFeatureType = ftype;
695
            }
696
        } catch(Throwable th) {
697
            state.setBreakingsCause(th);
698
        }
699

    
700
        LOG.info("load() broken:{}, {}, {}.",
701
                new Object[] { state.isBroken(), this.getProviderName(), params }
702
        );
703
    }
704

    
705
        public DataStoreProviderServices getStoreProviderServices() {
706
                return this;
707
        }
708

    
709
    public static void registerPersistenceDefinition() {
710
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
711
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
712
            DynStruct definition =
713
                manager.addDefinition(DefaultFeatureStore.class,
714
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
715
                        + " Persistent definition", null, null);
716
            definition.addDynFieldString("dataStoreName").setMandatory(true)
717
                .setPersistent(true);
718

    
719
            definition.addDynFieldObject("parameters")
720
                .setClassOfValue(DynObject.class).setMandatory(true)
721
                .setPersistent(true);
722

    
723
            definition.addDynFieldObject("selection")
724
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
725
                .setPersistent(true);
726

    
727
            definition.addDynFieldObject("transforms")
728
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
729
                .setMandatory(true).setPersistent(true);
730

    
731
            definition.addDynFieldMap("evaluatedAttributes")
732
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
733
                .setMandatory(false).setPersistent(true);
734

    
735
            definition.addDynFieldString("defaultFeatureTypeId")
736
                .setMandatory(true).setPersistent(true);
737
        }
738
    }
739

    
740
    public static void registerMetadataDefinition() throws MetadataException {
741
        MetadataManager manager = MetadataLocator.getMetadataManager();
742
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
743
            DynStruct metadataDefinition =
744
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
745
            metadataDefinition.extend(manager
746
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
747
        }
748
    }
749

    
750
    //
751
    // ====================================================================
752
    // Gestion de la seleccion
753
    //
754

    
755
    @Override
756
    public void setSelection(DataSet selection) throws DataException {
757
        this.setSelection((FeatureSet) selection);
758
    }
759

    
760
    @Override
761
    public DataSet createSelection() throws DataException {
762
        return createFeatureSelection();
763
    }
764

    
765
    @Override
766
    public DataSet getSelection() throws DataException {
767
        return this.getFeatureSelection();
768
    }
769

    
770
    @Override
771
    public void setSelection(FeatureSet selection) throws DataException {
772
        setSelection(selection, true);
773
    }
774

    
775
    public void setSelection(FeatureSet selection, boolean undoable)
776
        throws DataException {
777
        if (selection == null) {
778
            if (undoable) {
779
                throw new SelectionNotAllowedException(getName());
780
            }
781

    
782
        } else {
783
            if (selection.equals(this.selection)) {
784
                return;
785
            }
786
            if (!selection.isFromStore(this)) {
787
                throw new SelectionNotAllowedException(getName());
788
            }
789
        }
790

    
791
        if (this.selection != null) {
792
            this.selection.deleteObserver(this);
793
        }
794
        if (selection == null) {
795
            if (this.selection != null) {
796
                this.selection.dispose();
797
            }
798
            this.selection = null;
799
            return;
800
        }
801
        if (selection instanceof FeatureSelection) {
802
            if (undoable && isEditing()) {
803
                commands.selectionSet(this, this.selection,
804
                    (FeatureSelection) selection);
805
            }
806
            if (this.selection != null) {
807
                this.selection.dispose();
808
            }
809
            this.selection = (FeatureSelection) selection;
810
        } else {
811
            if (undoable && isEditing()) {
812
                commands.startComplex("_selectionSet");
813
            }
814
            if (selection instanceof DefaultFeatureSelection) {
815
                DefaultFeatureSelection defSelection =
816
                    (DefaultFeatureSelection) selection;
817
                defSelection.deselectAll(undoable);
818
                defSelection.select(selection, undoable);
819
            } else {
820
                this.selection.deselectAll();
821
                this.selection.select(selection);
822
            }
823
            if (undoable && isEditing()) {
824
                commands.endComplex();
825
            }
826
        }
827
        this.selection.addObserver(this);
828

    
829
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
830
    }
831

    
832
    @Override
833
    public FeatureSelection createFeatureSelection() throws DataException {
834
        return this.provider.createFeatureSelection();
835
    }
836

    
837
    @Override
838
    public FeatureSelection getFeatureSelection() throws DataException {
839
        if (selection == null) {
840
            this.selection = createFeatureSelection();
841
            this.selection.addObserver(this);
842
        }
843
        return selection;
844
    }
845

    
846
    //
847
    // ====================================================================
848
    // Gestion de notificaciones
849
    //
850

    
851
    @Override
852
    public void notifyChange(FeatureStoreNotification storeNotification) {
853
        try {
854
            delegateObservable.notifyObservers(storeNotification);
855
        } catch (Throwable ex) {
856
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
857
        }
858
    }
859

    
860
    @Override
861
    public void notifyChange(String notification) {
862
        if (delegateObservable != null) {
863
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
864
        }
865

    
866
    }
867

    
868
    @Override
869
    public void notifyChange(String notification, FeatureProvider data) {
870
        Feature f = null;
871
        try {
872
            f = createFeature(data);
873
        } catch (Throwable ex) {
874
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
875
        }
876
        notifyChange(notification, f);
877
    }
878

    
879
    public void notifyChange(String notification, Feature feature) {
880
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
881
            feature));
882
    }
883

    
884
    public void notifyChange(String notification, Command command) {
885
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
886
            command));
887
    }
888

    
889
    public void notifyChange(String notification, EditableFeatureType type) {
890
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
891
            type));
892
    }
893

    
894
    @Override
895
    public void notifyChange(String notification, Resource resource) {
896
        notifyChange(new DefaultFeatureStoreNotification(this,
897
            DataStoreNotification.RESOURCE_CHANGED));
898
    }
899

    
900
    //
901
    // ====================================================================
902
    // Gestion de bloqueos
903
    //
904

    
905
    @Override
906
    public boolean isLocksSupported() {
907
        return this.provider.isLocksSupported();
908
    }
909

    
910
    @Override
911
    public FeatureLocks getLocks() throws DataException {
912
        if (!this.provider.isLocksSupported()) {
913
            LOG.warn("Locks not supported");
914
            return null;
915
        }
916
        if (locks == null) {
917
            this.locks = this.provider.createFeatureLocks();
918
        }
919
        return locks;
920
    }
921

    
922
    //
923
    // ====================================================================
924
    // Interface Observable
925
    //
926

    
927
    @Override
928
    public void disableNotifications() {
929
        this.delegateObservable.disableNotifications();
930

    
931
    }
932

    
933
    @Override
934
    public void enableNotifications() {
935
        this.delegateObservable.enableNotifications();
936
    }
937

    
938
    @Override
939
    public void beginComplexNotification() {
940
        this.delegateObservable.beginComplexNotification();
941

    
942
    }
943

    
944
    @Override
945
    public void endComplexNotification() {
946
        this.delegateObservable.endComplexNotification();
947

    
948
    }
949

    
950
    @Override
951
    public void addObserver(Observer observer) {
952
        if (delegateObservable != null) {
953
            this.delegateObservable.addObserver(observer);
954
        }
955
    }
956

    
957
    @Override
958
    public void deleteObserver(Observer observer) {
959
        if (delegateObservable != null) {
960
            this.delegateObservable.deleteObserver(observer);
961
        }
962
    }
963

    
964
    @Override
965
    public void deleteObservers() {
966
        this.delegateObservable.deleteObservers();
967

    
968
    }
969

    
970
    //
971
    // ====================================================================
972
    // Interface Observer
973
    //
974
    // Usado para observar:
975
    // - su seleccion
976
    // - sus bloqueos
977
    // - sus recursos
978
    //
979

    
980
    @Override
981
    public void update(Observable observable, Object notification) {
982
        if (observable instanceof FeatureSet) {
983
            if (observable == this.selection) {
984
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
985
            } else if (observable == this.locks) {
986
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
987
            }
988

    
989
        } else if (observable instanceof FeatureStoreProvider) {
990
            if (observable == this.provider) {
991

    
992
            }
993
        } else if (observable instanceof FeatureReferenceSelection) {
994
            if(notification instanceof String){
995
                    this.notifyChange((String)notification);
996
            }
997
        }
998
    }
999

    
1000
    //
1001
    // ====================================================================
1002
    // Edicion
1003
    //
1004

    
1005
    private void newVersionOfUpdate() {
1006
        this.versionOfUpdate++;
1007
    }
1008

    
1009
    private long currentVersionOfUpdate() {
1010
        return this.versionOfUpdate;
1011
    }
1012

    
1013
    private void checkInEditingMode() throws NeedEditingModeException {
1014
        if (mode != MODE_FULLEDIT) {
1015
            throw new NeedEditingModeException(this.getName());
1016
        }
1017
    }
1018

    
1019
    private void checkNotInAppendMode() throws IllegalStateException {
1020
        if (mode == MODE_APPEND) {
1021
                        throw new IllegalStateException("Error: store "
1022
                                        + this.getFullName() + " is in append mode");
1023
        }
1024
    }
1025

    
1026
    private void checkIsOwnFeature(Feature feature)
1027
        throws IllegalFeatureException {
1028
        if (((DefaultFeature) feature).getStore() != this) {
1029
            throw new IllegalFeatureException(this.getName());
1030
        }
1031
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1032
        // fixFeatureType((DefaultFeatureType) feature.getType());
1033
    }
1034

    
1035
    private void exitEditingMode() {
1036
        if (commands != null) {
1037
            commands.clear();
1038
            commands = null;
1039
        }
1040

    
1041
        if (featureTypeManager != null) {
1042
            featureTypeManager.dispose();
1043
            featureTypeManager = null;
1044

    
1045
        }
1046

    
1047
        // TODO implementar un dispose para estos dos
1048
        featureManager = null;
1049
        spatialManager = null;
1050

    
1051
        featureCount = null;
1052

    
1053
        mode = MODE_QUERY;
1054
        hasStrongChanges = true; // Lo deja a true por si las moscas
1055
        hasInserts = true;
1056
    }
1057

    
1058
    @Override
1059
    synchronized public void edit() throws DataException {
1060
        edit(MODE_FULLEDIT);
1061
    }
1062

    
1063
    @Override
1064
    synchronized public void edit(int mode) throws DataException {
1065
        LOG.debug("Starting editing in mode: {}", mode);
1066
        try {
1067
            if (this.mode != MODE_QUERY) {
1068
                throw new AlreadyEditingException(this.getName());
1069
            }
1070
            if (!this.provider.supportsAppendMode()) {
1071
                mode = MODE_FULLEDIT;
1072
            }
1073
            switch (mode) {
1074
            case MODE_QUERY:
1075
                throw new IllegalStateException(this.getName());
1076

    
1077
            case MODE_FULLEDIT:
1078
                if (!this.transforms.isEmpty()) {
1079
                    throw new IllegalStateException(this.getName());
1080
                }
1081
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1082
                invalidateIndexes();
1083
                featureManager = new FeatureManager();
1084
                featureTypeManager = new FeatureTypeManager(this);
1085
                spatialManager = new SpatialManager(this, provider.getEnvelope());
1086

    
1087
                commands = new DefaultFeatureCommandsStack(
1088
                        this, featureManager,
1089
                        spatialManager, featureTypeManager);
1090
                this.mode = MODE_FULLEDIT;
1091
                hasStrongChanges = false;
1092
                hasInserts = false;
1093
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1094
                break;
1095
            case MODE_APPEND:
1096
                if (!this.transforms.isEmpty()) {
1097
                    throw new IllegalStateException(this.getName());
1098
                }
1099
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1100
                invalidateIndexes();
1101
                this.provider.beginAppend();
1102
                this.mode = MODE_APPEND;
1103
                hasInserts = false;
1104
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1105
                break;
1106
            }
1107
        } catch (Exception e) {
1108
            throw new StoreEditException(e, this.getName());
1109
        }
1110
    }
1111

    
1112
    private void invalidateIndexes() {
1113
        setIndexesValidStatus(false);
1114
    }
1115

    
1116
    private void setIndexesValidStatus(boolean valid) {
1117
        FeatureIndexes theIndexes = getIndexes();
1118
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
1119
            ? Boolean.TRUE : Boolean.FALSE), theIndexes);
1120
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1121
            FeatureIndex index = (FeatureIndex) iterator.next();
1122
            if (index instanceof FeatureIndexProviderServices) {
1123
                FeatureIndexProviderServices indexServices =
1124
                    (FeatureIndexProviderServices) index;
1125
                indexServices.setValid(valid);
1126
            }
1127
        }
1128
    }
1129

    
1130
    private void updateIndexes() throws FeatureIndexException {
1131
        FeatureIndexes theIndexes = getIndexes();
1132
        LOG.debug("Refilling indexes: {}", theIndexes);
1133
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1134
            FeatureIndex index = (FeatureIndex) iterator.next();
1135
            if (index instanceof FeatureIndexProviderServices) {
1136
                FeatureIndexProviderServices indexServices =
1137
                    (FeatureIndexProviderServices) index;
1138
                indexServices.fill(true, null);
1139
            }
1140
        }
1141
    }
1142

    
1143
    private void waitForIndexes() {
1144
        FeatureIndexes theIndexes = getIndexes();
1145
        LOG.debug("Waiting for indexes to finish filling: {}", theIndexes);
1146
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1147
            FeatureIndex index = (FeatureIndex) iterator.next();
1148
            if (index instanceof FeatureIndexProviderServices) {
1149
                FeatureIndexProviderServices indexServices =
1150
                    (FeatureIndexProviderServices) index;
1151
                indexServices.waitForIndex();
1152
            }
1153
        }
1154
    }
1155

    
1156
    private void disposeIndexes() {
1157
        FeatureIndexes theIndexes = getIndexes();
1158
        LOG.debug("Disposing indexes: {}", theIndexes);
1159
        if( theIndexes==null ) {
1160
            return;
1161
        }
1162
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1163
            FeatureIndex index = (FeatureIndex) iterator.next();
1164
            if (index instanceof FeatureIndexProviderServices) {
1165
                FeatureIndexProviderServices indexServices =
1166
                    (FeatureIndexProviderServices) index;
1167
                indexServices.dispose();
1168
            }
1169
        }
1170
    }
1171

    
1172
    @Override
1173
    public boolean isEditing() {
1174
        return mode == MODE_FULLEDIT;
1175
    }
1176

    
1177
    @Override
1178
    public boolean isAppending() {
1179
        return mode == MODE_APPEND;
1180
    }
1181

    
1182
    @Override
1183
    synchronized public void update(EditableFeatureType type)
1184
        throws DataException {
1185
        try {
1186
            checkInEditingMode();
1187
            if (type == null) {
1188
                throw new NullFeatureTypeException(getName());
1189
            }
1190
            // FIXME: Comprobar que es un featureType aceptable.
1191
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
1192
            newVersionOfUpdate();
1193

    
1194
            FeatureType oldt = type.getSource().getCopy();
1195
            FeatureType newt = type.getCopy();
1196
            commands.update(newt, oldt);
1197

    
1198
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
1199
                hasStrongChanges = true;
1200
            }
1201
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1202
        } catch (Exception e) {
1203
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1204
        }
1205
    }
1206

    
1207
    @Override
1208
    public void delete(Feature feature) throws DataException {
1209
        this.commands.delete(feature);
1210
    }
1211

    
1212
    synchronized public void doDelete(Feature feature) throws DataException {
1213
        try {
1214
            checkInEditingMode();
1215
            checkIsOwnFeature(feature);
1216
            if (feature instanceof EditableFeature) {
1217
                throw new StoreDeleteEditableFeatureException(getName());
1218
            }
1219
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1220

    
1221
            //Update the featureManager and the spatialManager
1222
            featureManager.delete(feature.getReference());
1223
            spatialManager.deleteFeature(feature);
1224

    
1225
            newVersionOfUpdate();
1226
            hasStrongChanges = true;
1227
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1228
        } catch (Exception e) {
1229
            throw new StoreDeleteFeatureException(e, this.getName());
1230
        }
1231
    }
1232

    
1233
    private static EditableFeature lastChangedFeature = null;
1234

    
1235
    @Override
1236
    public synchronized void insert(EditableFeature feature)
1237
        throws DataException {
1238
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1239
        try {
1240
            switch (mode) {
1241
            case MODE_QUERY:
1242
                throw new NeedEditingModeException(this.getName());
1243

    
1244
            case MODE_APPEND:
1245
                checkIsOwnFeature(feature);
1246
                if (feature.getSource() != null) {
1247
                    throw new NoNewFeatureInsertException(this.getName());
1248
                }
1249
                this.featureCount = null;
1250
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1251
                feature.validate(Feature.UPDATE);
1252
                provider.append(((DefaultEditableFeature) feature).getData());
1253
                hasStrongChanges = true;
1254
                hasInserts = true;
1255
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1256
                break;
1257

    
1258
            case MODE_FULLEDIT:
1259
                if (feature.getSource() != null) {
1260
                    throw new NoNewFeatureInsertException(this.getName());
1261
                }
1262
                commands.insert(feature);
1263
            }
1264
        } catch (Exception e) {
1265
            throw new StoreInsertFeatureException(e, this.getName());
1266
        }
1267
    }
1268

    
1269
    synchronized public void doInsert(EditableFeature feature)
1270
        throws DataException {
1271
        checkIsOwnFeature(feature);
1272

    
1273
        waitForIndexes();
1274

    
1275
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1276
        newVersionOfUpdate();
1277
        if ((lastChangedFeature == null)
1278
            || (lastChangedFeature.getSource() != feature.getSource())) {
1279
            lastChangedFeature = feature;
1280
            feature.validate(Feature.UPDATE);
1281
            lastChangedFeature = null;
1282
        }
1283
        //Update the featureManager and the spatialManager
1284
        ((DefaultEditableFeature) feature).setInserted(true);
1285
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1286

    
1287

    
1288
        featureManager.add(newFeature);
1289
        spatialManager.insertFeature(newFeature);
1290

    
1291
        hasStrongChanges = true;
1292
        hasInserts = true;
1293
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1294
    }
1295

    
1296
    @Override
1297
    public void update(EditableFeature feature)
1298
    throws DataException {
1299
        if ((feature).getSource() == null) {
1300
            insert(feature);
1301
            return;
1302
        }
1303
        commands.update(feature, feature.getSource());
1304
    }
1305

    
1306
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1307
        throws DataException {
1308
        try {
1309
            checkInEditingMode();
1310
            checkIsOwnFeature(feature);
1311
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1312
            newVersionOfUpdate();
1313
            if ((lastChangedFeature == null)
1314
                || (lastChangedFeature.getSource() != feature.getSource())) {
1315
                lastChangedFeature = feature;
1316
                feature.validate(Feature.UPDATE);
1317
                lastChangedFeature = null;
1318
            }
1319

    
1320
            //Update the featureManager and the spatialManager
1321
            Feature newf = feature.getNotEditableCopy();
1322
            featureManager.update(newf, oldFeature);
1323
            spatialManager.updateFeature(newf, oldFeature);
1324

    
1325
            hasStrongChanges = true;
1326
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1327
        } catch (Exception e) {
1328
            throw new StoreUpdateFeatureException(e, this.getName());
1329
        }
1330
    }
1331

    
1332
    @Override
1333
    synchronized public void redo() throws RedoException {
1334
        Command redo = commands.getNextRedoCommand();
1335
        try {
1336
            checkInEditingMode();
1337
        } catch (NeedEditingModeException ex) {
1338
            throw new RedoException(redo, ex);
1339
        }
1340
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1341
        newVersionOfUpdate();
1342
        commands.redo();
1343
        hasStrongChanges = true;
1344
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1345
    }
1346

    
1347
    @Override
1348
    synchronized public void undo() throws UndoException {
1349
        Command undo = commands.getNextUndoCommand();
1350
        try {
1351
            checkInEditingMode();
1352
        } catch (NeedEditingModeException ex) {
1353
            throw new UndoException(undo, ex);
1354
        }
1355
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1356
        newVersionOfUpdate();
1357
        commands.undo();
1358
        hasStrongChanges = true;
1359
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1360
    }
1361

    
1362
    @Override
1363
    public List getRedoInfos() {
1364
        if (isEditing() && (commands != null)) {
1365
            return commands.getRedoInfos();
1366
        } else {
1367
            return null;
1368
        }
1369
    }
1370

    
1371
    @Override
1372
    public List getUndoInfos() {
1373
        if (isEditing() && (commands != null)) {
1374
            return commands.getUndoInfos();
1375
        } else {
1376
            return null;
1377
        }
1378
    }
1379

    
1380
    public synchronized FeatureCommandsStack getCommandsStack()
1381
        throws DataException {
1382
        checkInEditingMode();
1383
        return commands;
1384
    }
1385

    
1386
    @Override
1387
    synchronized public void cancelEditing() throws DataException {
1388
        if( spatialManager!=null ) {
1389
            spatialManager.cancelModifies();
1390
        }
1391
        try {
1392
            switch (mode) {
1393
            case MODE_QUERY:
1394
                throw new NeedEditingModeException(this.getName());
1395

    
1396
            case MODE_APPEND:
1397
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1398
                provider.abortAppend();
1399
                exitEditingMode();
1400
                ((FeatureSelection) this.getSelection()).deselectAll();
1401
                updateIndexes();
1402
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1403

    
1404
            case MODE_FULLEDIT:
1405
                boolean clearSelection = this.hasStrongChanges;
1406
                if (this.selection instanceof FeatureReferenceSelection) {
1407
                    clearSelection = this.hasInserts;
1408
                }
1409
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1410
                exitEditingMode();
1411
                if (clearSelection) {
1412
                    ((FeatureSelection) this.getSelection()).deselectAll();
1413
                }
1414
                updateIndexes();
1415
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1416
            }
1417
        } catch (Exception e) {
1418
            throw new StoreCancelEditingException(e, this.getName());
1419
        }
1420
    }
1421

    
1422
    @Override
1423
    synchronized public void finishEditing() throws DataException {
1424
        LOG.debug("finish editing of mode: {}", mode);
1425
        try {
1426

    
1427
            /*
1428
             * Selection needs to be cleared when editing stops
1429
             * to prevent conflicts with selection remaining from
1430
             * editing mode.
1431
             */
1432
//            ((FeatureSelection) this.getSelection()).deselectAll();
1433

    
1434
            switch (mode) {
1435
            case MODE_QUERY:
1436
                throw new NeedEditingModeException(this.getName());
1437

    
1438
            case MODE_APPEND:
1439
                if( selection!=null ) {
1440
                    selection = null;
1441
                }
1442
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1443
                provider.endAppend();
1444
                exitEditingMode();
1445
                updateIndexes();
1446
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1447
                break;
1448

    
1449
            case MODE_FULLEDIT:
1450
                if (hasStrongChanges && !this.allowWrite()) {
1451
                    throw new WriteNotAllowedException(getName());
1452
                }
1453
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1454
                    selection = null;
1455
                }
1456
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1457
                if (hasStrongChanges) {
1458
                    validateFeatures(Feature.FINISH_EDITING);
1459

    
1460
                    /*
1461
                     * This will throw a PerformEditingExceptionif the provider
1462
                     * does not accept the changes (for example, an invalid field name)
1463
                     */
1464
                    provider.performChanges(featureManager.getDeleted(),
1465
                        featureManager.getInserted(),
1466
                        featureManager.getUpdated(),
1467
                        featureTypeManager.getFeatureTypesChanged());
1468
                }
1469
                exitEditingMode();
1470
                updateIndexes();
1471
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1472
                break;
1473
            }
1474
        } catch (PerformEditingException pee) {
1475
            throw new WriteException(provider.getSourceId().toString(), pee);
1476
        } catch (Exception e) {
1477
            throw new FinishEditingException(e);
1478
        }
1479
    }
1480

    
1481
    /**
1482
     * Save changes in the provider without leaving the edit mode.
1483
     * Do not call observers to communicate a change of ediding mode.
1484
     * The operation's history is eliminated to prevent inconsistencies
1485
     * in the data.
1486
     *
1487
     * @throws DataException
1488
     */
1489
    @Override
1490
    synchronized public void commitChanges() throws DataException {
1491
      LOG.debug("commitChanges of mode: {}", mode);
1492
      if( !canCommitChanges() ) {
1493
              throw new WriteNotAllowedException(getName());
1494
      }
1495
      try {
1496
        switch (mode) {
1497
        case MODE_QUERY:
1498
          throw new NeedEditingModeException(this.getName());
1499

    
1500
        case MODE_APPEND:
1501
          this.provider.endAppend();
1502
          exitEditingMode();
1503
          invalidateIndexes();
1504
          this.provider.beginAppend();
1505
          hasInserts = false;
1506
          break;
1507

    
1508
        case MODE_FULLEDIT:
1509
          if (hasStrongChanges && !this.allowWrite()) {
1510
            throw new WriteNotAllowedException(getName());
1511
          }
1512
          if (hasStrongChanges) {
1513
            validateFeatures(Feature.FINISH_EDITING);
1514
            provider.performChanges(featureManager.getDeleted(),
1515
              featureManager.getInserted(),
1516
              featureManager.getUpdated(),
1517
              featureTypeManager.getFeatureTypesChanged());
1518
          }
1519
          invalidateIndexes();
1520
          featureManager = new FeatureManager();
1521
          featureTypeManager = new FeatureTypeManager(this);
1522
          spatialManager = new SpatialManager(this, provider.getEnvelope());
1523

    
1524
          commands =
1525
            new DefaultFeatureCommandsStack(this, featureManager,
1526
              spatialManager, featureTypeManager);
1527
          featureCount = null;
1528
          hasStrongChanges = false;
1529
          hasInserts = false;
1530
          break;
1531
        }
1532
      } catch (Exception e) {
1533
        throw new FinishEditingException(e);
1534
      }
1535
    }
1536

    
1537
    @Override
1538
    synchronized public boolean canCommitChanges() throws DataException {
1539
        if ( !this.allowWrite()) {
1540
                return false;
1541
        }
1542
            switch (mode) {
1543
            default:
1544
        case MODE_QUERY:
1545
                return false;
1546

    
1547
        case MODE_APPEND:
1548
                return true;
1549

    
1550
        case MODE_FULLEDIT:
1551
            List types = this.getFeatureTypes();
1552
            for( int i=0; i<types.size(); i++ ) {
1553
                    Object type = types.get(i);
1554
                    if( type instanceof DefaultEditableFeatureType ) {
1555
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1556
                                    return false;
1557
                            }
1558
                    }
1559
            }
1560
            return true;
1561
            }
1562
    }
1563

    
1564
    @Override
1565
    public void beginEditingGroup(String description)
1566
        throws NeedEditingModeException {
1567
        checkInEditingMode();
1568
        commands.startComplex(description);
1569
    }
1570

    
1571
    @Override
1572
    public void endEditingGroup() throws NeedEditingModeException {
1573
        checkInEditingMode();
1574
        commands.endComplex();
1575
    }
1576

    
1577
    @Override
1578
    public boolean isAppendModeSupported() {
1579
        return this.provider.supportsAppendMode();
1580
    }
1581

    
1582
    @Override
1583
    public void export(DataServerExplorer explorer, String provider,
1584
        NewFeatureStoreParameters params) throws DataException {
1585

    
1586
        if (this.getFeatureTypes().size() != 1) {
1587
            throw new NotYetImplemented(
1588
                "export whith more than one type not yet implemented");
1589
        }
1590
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1591
        FeatureStore target = null;
1592
        FeatureSet features = null;
1593
        DisposableIterator iterator = null;
1594
        try {
1595
            FeatureType type = this.getDefaultFeatureType();
1596
            if ((params.getDefaultFeatureType() == null)
1597
                || (params.getDefaultFeatureType().size() == 0)) {
1598
                params.setDefaultFeatureType(type.getEditable());
1599

    
1600
            }
1601
            explorer.add(provider, params, true);
1602

    
1603
            DataManager manager = DALLocator.getDataManager();
1604
            target = (FeatureStore) manager.openStore(provider, params);
1605
            FeatureType targetType = target.getDefaultFeatureType();
1606

    
1607
            target.edit(MODE_APPEND);
1608
            FeatureAttributeDescriptor[] pkattrs = type.getPrimaryKey();
1609
            if (featureSelection.getSize() > 0) {
1610
                features = this.getFeatureSelection();
1611
            } else {
1612
                if ((pkattrs != null) && (pkattrs.length > 0)) {
1613
                    FeatureQuery query = createFeatureQuery();
1614
                    for (FeatureAttributeDescriptor pkattr : pkattrs) {
1615
                        query.getOrder().add(pkattr.getName(), true);
1616
                    }
1617
                    features = this.getFeatureSet(query);
1618
                } else {
1619
                    features = this.getFeatureSet();
1620
                }
1621
            }
1622
            iterator = features.fastIterator();
1623
            while (iterator.hasNext()) {
1624
                DefaultFeature feature = (DefaultFeature) iterator.next();
1625
                target.insert(target.createNewFeature(targetType, feature));
1626
            }
1627
            target.finishEditing();
1628
            target.dispose();
1629
        } catch (Exception e) {
1630
            throw new DataExportException(e, params.toString());
1631
        } finally {
1632
            dispose(iterator);
1633
            dispose(features);
1634
            dispose(target);
1635
        }
1636
    }
1637

    
1638
    //
1639
    // ====================================================================
1640
    // Obtencion de datos
1641
    // getDataCollection, getFeatureCollection
1642
    //
1643

    
1644
    @Override
1645
    public DataSet getDataSet() throws DataException {
1646
        checkNotInAppendMode();
1647
        FeatureQuery query =
1648
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1649
        return new DefaultFeatureSet(this, query);
1650
    }
1651

    
1652
    @Override
1653
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1654
        checkNotInAppendMode();
1655
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1656
    }
1657

    
1658
    @Override
1659
    public void getDataSet(Observer observer) throws DataException {
1660
        checkNotInAppendMode();
1661
        this.getFeatureSet(null, observer);
1662
    }
1663

    
1664
    @Override
1665
    public void getDataSet(DataQuery dataQuery, Observer observer)
1666
        throws DataException {
1667
        checkNotInAppendMode();
1668
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1669
    }
1670

    
1671
    @Override
1672
    public FeatureSet getFeatureSet() throws DataException {
1673
        return this.getFeatureSet((FeatureQuery)null);
1674
    }
1675

    
1676
    @Override
1677
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1678
        throws DataException {
1679
        checkNotInAppendMode();
1680
        if( featureQuery==null ) {
1681
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1682
        }
1683
        return new DefaultFeatureSet(this, featureQuery);
1684
    }
1685

    
1686
    @Override
1687
    public FeatureSet getFeatureSet(String filter) throws DataException {
1688
        return this.getFeatureSet(filter, null, true);
1689
    }
1690

    
1691
    @Override
1692
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1693
        return this.getFeatureSet(filter, sortBy, true);
1694
    }
1695

    
1696
    @Override
1697
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1698
        FeatureQuery query = this.createFeatureQuery();
1699
        if( !StringUtils.isEmpty(filter) ) {
1700
            query.setFilter(filter);
1701
        }
1702
        if( !StringUtils.isEmpty(sortBy) ) {
1703
            query.getOrder().add(sortBy, asc);
1704
        }
1705
        return this.getFeatureSet(query);
1706
    }
1707
    
1708
    @Override
1709
    public List<Feature> getFeatures(String filter)  {
1710
        return this.getFeatures(filter, null, true);
1711
    }
1712

    
1713
    @Override
1714
    public List<Feature> getFeatures(String filter, String sortBy)  {
1715
        return this.getFeatures(filter, sortBy, true);
1716
    }
1717

    
1718
    @Override
1719
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1720
        FeatureQuery query = this.createFeatureQuery();
1721
        if( !StringUtils.isEmpty(filter) ) {
1722
            query.setFilter(filter);
1723
        }
1724
        if( !StringUtils.isEmpty(sortBy) ) {
1725
            query.getOrder().add(sortBy, asc);
1726
        }
1727
        return this.getFeatures(query, 100);
1728
    }
1729
    
1730
    @Override
1731
    public List<Feature> getFeatures(FeatureQuery query)  {
1732
        return this.getFeatures(query, 100);
1733
    }
1734
    
1735
    @Override
1736
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1737
        try {
1738
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1739
            return pager.asList();
1740
        } catch (BaseException ex) {
1741
            throw new RuntimeException("Can't create the list of features.", ex);
1742
        }
1743
    }
1744

    
1745
    @Override
1746
    public List<Feature> getFeatures() {
1747
        return this.getFeatures(null, 500);
1748
    }
1749

    
1750
    @Override
1751
    public Feature findFirst(String filter) throws DataException {
1752
        return this.findFirst(filter, null, true);
1753
    }
1754

    
1755
    @Override
1756
    public Feature findFirst(String filter, String sortBy) throws DataException {
1757
        return this.findFirst(filter, sortBy, true);
1758
    }
1759

    
1760
    @Override
1761
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1762
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1763
        if( set==null || set.isEmpty() ) {
1764
            return null;
1765
        }
1766
        DisposableIterator it = set.iterator();
1767
        Feature f = (Feature) it.next();
1768
        it.dispose();
1769
        return f;
1770
    }
1771
    
1772
    @Override
1773
    public void accept(Visitor visitor) throws BaseException {
1774
        FeatureSet set = getFeatureSet();
1775
        try {
1776
            set.accept(visitor);
1777
        } finally {
1778
            set.dispose();
1779
        }
1780
    }
1781

    
1782
    @Override
1783
    public void accept(Visitor visitor, DataQuery dataQuery)
1784
        throws BaseException {
1785
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1786
        try {
1787
            set.accept(visitor);
1788
        } finally {
1789
            set.dispose();
1790
        }
1791
    }
1792

    
1793
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1794
        throws DataException {
1795
        DefaultFeatureType fType =
1796
            (DefaultFeatureType) this.getFeatureType(featureQuery
1797
                .getFeatureTypeId());
1798
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1799
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1800
        }
1801
        return fType;
1802
    }
1803

    
1804
    @Override
1805
    public void getFeatureSet(Observer observer) throws DataException {
1806
        checkNotInAppendMode();
1807
        this.getFeatureSet(null, observer);
1808
    }
1809

    
1810
    @Override
1811
    public void getFeatureSet(FeatureQuery query, Observer observer)
1812
        throws DataException {
1813
        class LoadInBackGround implements Runnable {
1814

    
1815
            private final FeatureStore store;
1816
            private final FeatureQuery query;
1817
            private final Observer observer;
1818

    
1819
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1820
                Observer observer) {
1821
                this.store = store;
1822
                this.query = query;
1823
                this.observer = observer;
1824
            }
1825

    
1826
            void notify(FeatureStoreNotification theNotification) {
1827
                observer.update(store, theNotification);
1828
            }
1829

    
1830
            @Override
1831
            public void run() {
1832
                FeatureSet set = null;
1833
                try {
1834
                    set = store.getFeatureSet(query);
1835
                    notify(new DefaultFeatureStoreNotification(store,
1836
                        FeatureStoreNotification.LOAD_FINISHED, set));
1837
                } catch (Exception e) {
1838
                    notify(new DefaultFeatureStoreNotification(store,
1839
                        FeatureStoreNotification.LOAD_FINISHED, e));
1840
                } finally {
1841
                    dispose(set);
1842
                }
1843
            }
1844
        }
1845

    
1846
        checkNotInAppendMode();
1847
        if (query == null) {
1848
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1849
        }
1850
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1851
        Thread thread = new Thread(task, "Load Feature Set in background");
1852
        thread.start();
1853
    }
1854

    
1855
    @Override
1856
    public Feature getFeatureByReference(FeatureReference reference)
1857
        throws DataException {
1858
        checkNotInAppendMode();
1859
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1860
        FeatureType featureType;
1861
        if (ref.getFeatureTypeId() == null) {
1862
            featureType = this.getDefaultFeatureType();
1863
        } else {
1864
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1865
        }
1866
        return this.getFeatureByReference(reference, featureType);
1867
    }
1868

    
1869
    @Override
1870
    public Feature getFeatureByReference(FeatureReference reference,
1871
        FeatureType featureType) throws DataException {
1872
        checkNotInAppendMode();
1873
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1874
        if (this.mode == MODE_FULLEDIT) {
1875
            Feature f = featureManager.get(reference, this, featureType);
1876
            if (f != null) {
1877
                return f;
1878
            }
1879
        }
1880

    
1881
        FeatureType sourceFeatureType = featureType;
1882
        if (!this.transforms.isEmpty()) {
1883
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1884
        }
1885
        // TODO comprobar que el id es de este store
1886

    
1887
        DefaultFeature feature =
1888
            new DefaultFeature(this,
1889
                this.provider.getFeatureProviderByReference(
1890
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1891

    
1892
        if (!this.transforms.isEmpty()) {
1893
            return this.transforms.applyTransform(feature, featureType);
1894
        }
1895
        return feature;
1896
    }
1897

    
1898
    //
1899
    // ====================================================================
1900
    // Gestion de features
1901
    //
1902

    
1903
    private FeatureType fixFeatureType(DefaultFeatureType type)
1904
        throws DataException {
1905
        FeatureType original = this.getDefaultFeatureType();
1906

    
1907
        if ((type == null) || type.equals(original)) {
1908
            return original;
1909
        } else {
1910
            if (!type.isSubtypeOf(original)) {
1911
                Iterator iter = this.getFeatureTypes().iterator();
1912
                FeatureType tmpType;
1913
                boolean found = false;
1914
                while (iter.hasNext()) {
1915
                    tmpType = (FeatureType) iter.next();
1916
                    if (type.equals(tmpType)) {
1917
                        return type;
1918

    
1919
                    } else
1920
                        if (type.isSubtypeOf(tmpType)) {
1921
                            found = true;
1922
                            original = tmpType;
1923
                            break;
1924
                        }
1925

    
1926
                }
1927
                if (!found) {
1928
                    throw new IllegalFeatureTypeException(getName());
1929
                }
1930
            }
1931
        }
1932

    
1933
        // Checks that type has all fields of pk
1934
        // else add the missing attributes at the end.
1935
        if (!original.hasOID()) {
1936
            // Gets original pk attributes
1937
            DefaultEditableFeatureType edOriginal =
1938
                (DefaultEditableFeatureType) original.getEditable();
1939
            FeatureAttributeDescriptor orgAttr;
1940
            Iterator edOriginalIter = edOriginal.iterator();
1941
            while (edOriginalIter.hasNext()) {
1942
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1943
                if (!orgAttr.isPrimaryKey()) {
1944
                    edOriginalIter.remove();
1945
                }
1946
            }
1947

    
1948
            // Checks if all pk attributes are in type
1949
            Iterator typeIterator;
1950
            edOriginalIter = edOriginal.iterator();
1951
            FeatureAttributeDescriptor attr;
1952
            while (edOriginalIter.hasNext()) {
1953
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1954
                typeIterator = type.iterator();
1955
                while (typeIterator.hasNext()) {
1956
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1957
                    if (attr.getName().equals(orgAttr.getName())) {
1958
                        edOriginalIter.remove();
1959
                        break;
1960
                    }
1961
                }
1962
            }
1963

    
1964
            // add missing pk attributes if any
1965
            if (edOriginal.size() > 0) {
1966
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1967
                DefaultEditableFeatureType edType =
1968
                    (DefaultEditableFeatureType) original.getEditable();
1969
                edType.clear();
1970
                edType.addAll(type);
1971
                edType.addAll(edOriginal);
1972
                if (!isEditable) {
1973
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1974
                }
1975
            }
1976

    
1977
        }
1978

    
1979
        return type;
1980
    }
1981

    
1982
    @Override
1983
    public void validateFeatures(int mode) throws DataException {
1984
        FeatureSet collection = null;
1985
        DisposableIterator iter = null;
1986
        try {
1987
            FeatureRules rules = this.getDefaultFeatureType().getRules();
1988
            if( rules==null || rules.isEmpty() ) {
1989
                return;
1990
            }
1991
            checkNotInAppendMode();
1992
            collection = this.getFeatureSet();
1993
            iter = collection.fastIterator();
1994
            long previousVersionOfUpdate = currentVersionOfUpdate();
1995
            while (iter.hasNext()) {
1996
                ((DefaultFeature) iter.next()).validate(mode);
1997
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1998
                    throw new ConcurrentDataModificationException(getName());
1999
                }
2000
            }
2001
        } catch (Exception e) {
2002
            throw new ValidateFeaturesException(e, getName());
2003
        } finally {
2004
            DisposeUtils.disposeQuietly(iter);
2005
            DisposeUtils.disposeQuietly(collection);
2006
        }
2007
    }
2008

    
2009
    @Override
2010
    public FeatureType getDefaultFeatureType() throws DataException {
2011
        try {
2012

    
2013
            if (isEditing()) {
2014
                FeatureType auxFeatureType =
2015
                    featureTypeManager.getType(defaultFeatureType.getId());
2016
                if (auxFeatureType != null) {
2017
                    return avoidEditable(auxFeatureType);
2018
                }
2019
            }
2020
            FeatureType type = this.transforms.getDefaultFeatureType();
2021
            if (type != null) {
2022
                return avoidEditable(type);
2023
            }
2024

    
2025
            return avoidEditable(defaultFeatureType);
2026

    
2027
        } catch (Exception e) {
2028
            throw new GetFeatureTypeException(e, getName());
2029
        }
2030
    }
2031

    
2032
    private FeatureType avoidEditable(FeatureType ft) {
2033
        if (ft instanceof EditableFeatureType) {
2034
            return ((EditableFeatureType) ft).getNotEditableCopy();
2035
        } else {
2036
            return ft;
2037
        }
2038
    }
2039

    
2040
    @Override
2041
    public FeatureType getFeatureType(String featureTypeId)
2042
        throws DataException {
2043
        if (featureTypeId == null) {
2044
            return this.getDefaultFeatureType();
2045
        }
2046
        try {
2047
            if (isEditing()) {
2048
                FeatureType auxFeatureType =
2049
                    featureTypeManager.getType(featureTypeId);
2050
                if (auxFeatureType != null) {
2051
                    return auxFeatureType;
2052
                }
2053
            }
2054
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2055
            if (type != null) {
2056
                return type;
2057
            }
2058
            Iterator iter = this.featureTypes.iterator();
2059
            while (iter.hasNext()) {
2060
                type = (FeatureType) iter.next();
2061
                if (type.getId().equals(featureTypeId)) {
2062
                    return type;
2063
                }
2064
            }
2065
            return null;
2066
        } catch (Exception e) {
2067
            throw new GetFeatureTypeException(e, getName());
2068
        }
2069
    }
2070

    
2071
    public FeatureType getProviderDefaultFeatureType() {
2072
        return defaultFeatureType;
2073
    }
2074

    
2075
    @Override
2076
    public List getFeatureTypes() throws DataException {
2077
        try {
2078
            List types;
2079
            if (isEditing()) {
2080
                types = new ArrayList();
2081
                Iterator it = featureTypes.iterator();
2082
                while (it.hasNext()) {
2083
                    FeatureType type = (FeatureType) it.next();
2084
                    FeatureType typeaux =
2085
                        featureTypeManager.getType(type.getId());
2086
                    if (typeaux != null) {
2087
                        types.add(typeaux);
2088
                    } else {
2089
                        types.add(type);
2090
                    }
2091
                }
2092
                it = featureTypeManager.newsIterator();
2093
                while (it.hasNext()) {
2094
                    FeatureType type = (FeatureType) it.next();
2095
                    types.add(type);
2096
                }
2097
            } else {
2098
                types = this.transforms.getFeatureTypes();
2099
                if (types == null) {
2100
                    types = featureTypes;
2101
                }
2102
            }
2103
            return Collections.unmodifiableList(types);
2104
        } catch (Exception e) {
2105
            throw new GetFeatureTypeException(e, getName());
2106
        }
2107
    }
2108

    
2109
    public List getProviderFeatureTypes() throws DataException {
2110
        return Collections.unmodifiableList(this.featureTypes);
2111
    }
2112

    
2113
    @Override
2114
    public Feature createFeature(FeatureProvider data) throws DataException {
2115
        DefaultFeature feature = new DefaultFeature(this, data);
2116
        return feature;
2117
    }
2118

    
2119
    public Feature createFeature(FeatureProvider data, FeatureType type)
2120
        throws DataException {
2121
        // FIXME: falta por implementar
2122
        // Comprobar si es un subtipo del feature de data
2123
        // y construir un feature usando el subtipo.
2124
        // Probablemente requiera generar una copia del data.
2125
        throw new NotYetImplemented();
2126
    }
2127

    
2128
    @Override
2129
    public EditableFeature createNewFeature(FeatureType type,
2130
        Feature defaultValues) throws DataException {
2131
        try {
2132
            FeatureProvider data = createNewFeatureProvider(type);
2133
            DefaultEditableFeature feature =
2134
                new DefaultEditableFeature(this, data);
2135
            feature.initializeValues(defaultValues);
2136
            data.setNew(true);
2137

    
2138
            return feature;
2139
        } catch (Exception e) {
2140
            throw new CreateFeatureException(e, getName());
2141
        }
2142
    }
2143

    
2144
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2145
        throws DataException {
2146
        type = this.fixFeatureType((DefaultFeatureType) type);
2147
        FeatureProvider data = this.provider.createFeatureProvider(type);
2148
        data.setNew(true);
2149
        if (type.hasOID() && (data.getOID() == null)) {
2150
            data.setOID(this.provider.createNewOID());
2151
        } else {
2152
            data.setOID(this.getTemporalOID());
2153
        }
2154
        return data;
2155

    
2156
    }
2157

    
2158
    @Override
2159
    public EditableFeature createNewFeature(FeatureType type,
2160
        boolean defaultValues) throws DataException {
2161
        try {
2162
            FeatureProvider data = createNewFeatureProvider(type);
2163
            DefaultEditableFeature feature =
2164
                new DefaultEditableFeature(this, data);
2165
            if (defaultValues) {
2166
                feature.initializeValues();
2167
            }
2168
            return feature;
2169
        } catch (Exception e) {
2170
            throw new CreateFeatureException(e, getName());
2171
        }
2172
    }
2173

    
2174
    @Override
2175
    public EditableFeature createNewFeature(boolean defaultValues)
2176
        throws DataException {
2177
        return this.createNewFeature(this.getDefaultFeatureType(),
2178
            defaultValues);
2179
    }
2180

    
2181
    @Override
2182
    public EditableFeature createNewFeature() throws DataException {
2183
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2184
    }
2185

    
2186
    @Override
2187
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2188
        FeatureType ft = this.getDefaultFeatureType();
2189
        EditableFeature f = this.createNewFeature(ft, false);
2190
                for( FeatureAttributeDescriptor desc : ft ) {
2191
                        try {
2192
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2193
                        } catch(Throwable th) {
2194
                                // Ignore
2195
                        }
2196
                }
2197
        return f;
2198
    }
2199

    
2200
    @Override
2201
    public EditableFeatureType createFeatureType() {
2202
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2203
        return ftype;
2204
    }
2205

    
2206
    @Override
2207
    public EditableFeatureType createFeatureType(String id) {
2208
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2209
        return ftype;
2210
    }
2211

    
2212
    //
2213
    // ====================================================================
2214
    // Index related methods
2215
    //
2216

    
2217
    @Override
2218
    public FeatureIndexes getIndexes() {
2219
        return this.indexes;
2220
    }
2221

    
2222
    @Override
2223
    public FeatureIndex createIndex(FeatureType featureType,
2224
        String attributeName, String indexName) throws DataException {
2225
        return createIndex(null, featureType, attributeName, indexName);
2226
    }
2227

    
2228
    @Override
2229
    public FeatureIndex createIndex(String indexTypeName,
2230
        FeatureType featureType, String attributeName, String indexName)
2231
        throws DataException {
2232

    
2233
        return createIndex(indexTypeName, featureType, attributeName,
2234
            indexName, false, null);
2235
    }
2236

    
2237
    @Override
2238
    public FeatureIndex createIndex(FeatureType featureType,
2239
        String attributeName, String indexName, Observer observer)
2240
        throws DataException {
2241
        return createIndex(null, featureType, attributeName, indexName,
2242
            observer);
2243
    }
2244

    
2245
    @Override
2246
    public FeatureIndex createIndex(String indexTypeName,
2247
        FeatureType featureType, String attributeName, String indexName,
2248
        final Observer observer) throws DataException {
2249

    
2250
        return createIndex(indexTypeName, featureType, attributeName,
2251
            indexName, true, observer);
2252
    }
2253

    
2254
    private FeatureIndex createIndex(String indexTypeName,
2255
        FeatureType featureType, String attributeName, String indexName,
2256
        boolean background, final Observer observer) throws DataException {
2257

    
2258
        checkNotInAppendMode();
2259
        FeatureIndexProviderServices index;
2260
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2261
                featureType, indexName,
2262
                featureType.getAttributeDescriptor(attributeName));
2263

    
2264
        try {
2265
            index.fill(background, observer);
2266
        } catch (FeatureIndexException e) {
2267
            throw new InitializeException(index.getName(), e);
2268
        }
2269

    
2270
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2271
        return index;
2272
    }
2273

    
2274
    //
2275
    // ====================================================================
2276
    // Transforms related methods
2277
    //
2278

    
2279
    @Override
2280
    public FeatureStoreTransforms getTransforms() {
2281
        return this.transforms;
2282
    }
2283

    
2284
    @Override
2285
    public FeatureQuery createFeatureQuery() {
2286
        return new DefaultFeatureQuery();
2287
    }
2288

    
2289
    @Override
2290
    public DataQuery createQuery() {
2291
        return createFeatureQuery();
2292
    }
2293

    
2294
    //
2295
    // ====================================================================
2296
    // UndoRedo related methods
2297
    //
2298

    
2299
    @Override
2300
    public boolean canRedo() {
2301
        return commands.canRedo();
2302
    }
2303

    
2304
    @Override
2305
    public boolean canUndo() {
2306
        return commands.canUndo();
2307
    }
2308

    
2309
    @Override
2310
    public void redo(int num) throws RedoException {
2311
        for (int i = 0; i < num; i++) {
2312
            redo();
2313
        }
2314
    }
2315

    
2316
    @Override
2317
    public void undo(int num) throws UndoException {
2318
        for (int i = 0; i < num; i++) {
2319
            undo();
2320
        }
2321
    }
2322

    
2323
    //
2324
    // ====================================================================
2325
    // Metadata related methods
2326
    //
2327

    
2328
    @Override
2329
    public Object getMetadataID() {
2330
        return this.provider.getSourceId();
2331
    }
2332

    
2333
    @Override
2334
    public void delegate(DynObject dynObject) {
2335
        this.metadata.delegate(dynObject);
2336
    }
2337

    
2338
    @Override
2339
    public DynClass getDynClass() {
2340
        return this.metadata.getDynClass();
2341
    }
2342

    
2343
    @Override
2344
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2345
                if( this.transforms.hasDynValue(name) ) {
2346
                        return this.transforms.getDynValue(name);
2347
                }
2348
                if (this.metadata.hasDynValue(name)) {
2349
                        return this.metadata.getDynValue(name);
2350
                }
2351
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2352
                        return this.provider.getProviderName();
2353
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2354
                        return this.provider.getSourceId();
2355
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2356
                        try {
2357
                                return this.getDefaultFeatureType();
2358
                        } catch (DataException e) {
2359
                                return null;
2360
                        }
2361
                }
2362
                return this.metadata.getDynValue(name);
2363
        }
2364

    
2365
    @Override
2366
    public boolean hasDynValue(String name) {
2367
                if( this.transforms.hasDynValue(name) ) {
2368
                        return true;
2369
                }
2370
        return this.metadata.hasDynValue(name);
2371
    }
2372

    
2373
    @Override
2374
    public boolean hasDynMethod(String name) {
2375
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2376
    }
2377

    
2378
    @Override
2379
    public void implement(DynClass dynClass) {
2380
        this.metadata.implement(dynClass);
2381
    }
2382

    
2383
    @Override
2384
    public Object invokeDynMethod(String name, Object[] args)
2385
        throws DynMethodException {
2386
        return this.metadata.invokeDynMethod(this, name, args);
2387
    }
2388

    
2389
    @Override
2390
    public Object invokeDynMethod(int code, Object[] args)
2391
        throws DynMethodException {
2392
        return this.metadata.invokeDynMethod(this, code, args);
2393
    }
2394

    
2395
    @Override
2396
    public void setDynValue(String name, Object value)
2397
        throws DynFieldNotFoundException {
2398
                if( this.transforms.hasDynValue(name) ) {
2399
                        this.transforms.setDynValue(name, value);
2400
                        return;
2401
                }
2402
        this.metadata.setDynValue(name, value);
2403

    
2404
    }
2405

    
2406
    /*
2407
     * (non-Javadoc)
2408
     *
2409
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2410
     */
2411
    @Override
2412
    public Set getMetadataChildren() {
2413
        return this.metadataChildren;
2414
    }
2415

    
2416
    /*
2417
     * (non-Javadoc)
2418
     *
2419
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2420
     */
2421
    @Override
2422
    public String getMetadataName() {
2423
        return this.provider.getProviderName();
2424
    }
2425

    
2426
    public FeatureTypeManager getFeatureTypeManager() {
2427
        return this.featureTypeManager;
2428
    }
2429

    
2430
    @Override
2431
    public long getFeatureCount() throws DataException {
2432
        if (featureCount == null) {
2433
            featureCount = this.provider.getFeatureCount();
2434
        }
2435
        if (this.isEditing()) {
2436
            if(this.isAppending()) {
2437
                try{
2438
                    throw new IllegalStateException();
2439
                } catch(IllegalStateException e) {
2440
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND",e);
2441
                }
2442
                return -1;
2443
            } else {
2444
                return featureCount
2445
                    + this.featureManager.getDeltaSize();
2446
            }
2447
        }
2448
        return featureCount;
2449
    }
2450

    
2451
    private Long getTemporalOID() {
2452
        return this.temporalOid++;
2453
    }
2454

    
2455
    @Override
2456
    public FeatureType getProviderFeatureType(String featureTypeId) {
2457
        if (featureTypeId == null) {
2458
            return this.defaultFeatureType;
2459
        }
2460
        FeatureType type;
2461
        Iterator iter = this.featureTypes.iterator();
2462
        while (iter.hasNext()) {
2463
            type = (FeatureType) iter.next();
2464
            if (type.getId().equals(featureTypeId)) {
2465
                return type;
2466
            }
2467
        }
2468
        return null;
2469
    }
2470

    
2471
    @Override
2472
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2473
        return ((DefaultFeature) feature).getData();
2474
    }
2475

    
2476
    @Override
2477
    public DataStore getStore() {
2478
        return this;
2479
    }
2480

    
2481
    @Override
2482
    public FeatureStore getFeatureStore() {
2483
        return this;
2484
    }
2485

    
2486
    @Override
2487
    public void createCache(String name, DynObject parameters)
2488
        throws DataException {
2489
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2490
        if (cache == null) {
2491
            throw new CreateException("FeaureCacheProvider", null);
2492
        }
2493
        cache.apply(this, provider);
2494
        provider = cache;
2495

    
2496
        featureCount = null;
2497
    }
2498

    
2499
    @Override
2500
    public FeatureCache getCache() {
2501
        return cache;
2502
    }
2503

    
2504
    @Override
2505
    public void clear() {
2506
        if (metadata != null) {
2507
            metadata.clear();
2508
        }
2509
    }
2510

    
2511
    @Override
2512
    public String getName() {
2513
        if( this.provider != null ) {
2514
            return this.provider.getName();
2515
        }
2516
        if( this.parameters instanceof HasAFile ) {
2517
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2518
        }
2519
        return "unknow";
2520
    }
2521

    
2522
    @Override
2523
    public String getFullName() {
2524
        try {
2525
            if( this.provider!=null ) {
2526
                return this.provider.getFullName();
2527
            }
2528
            if( this.parameters instanceof HasAFile ) {
2529
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2530
            }
2531
            return null;
2532
        } catch(Throwable th) {
2533
            return null;
2534
        }
2535
    }
2536

    
2537
    @Override
2538
    public String getProviderName() {
2539
        if( this.provider!=null ) {
2540
            return this.provider.getProviderName();
2541
        }
2542
        if( this.parameters != null ) {
2543
            return this.parameters.getDataStoreName();
2544
        }
2545
        return null;
2546

    
2547
    }
2548

    
2549
    @Override
2550
    public boolean isKnownEnvelope() {
2551
        return this.provider.isKnownEnvelope();
2552
    }
2553

    
2554
    @Override
2555
    public boolean hasRetrievedFeaturesLimit() {
2556
        return this.provider.hasRetrievedFeaturesLimit();
2557
    }
2558

    
2559
    @Override
2560
    public int getRetrievedFeaturesLimit() {
2561
        return this.provider.getRetrievedFeaturesLimit();
2562
    }
2563

    
2564
    @Override
2565
    public Interval getInterval() {
2566
        if( this.timeSupport!=null ) {
2567
            return this.timeSupport.getInterval();
2568
        }
2569
        return this.provider.getInterval();
2570
    }
2571

    
2572
    @Override
2573
    public Collection getTimes() {
2574
        if( this.timeSupport!=null ) {
2575
            return this.timeSupport.getTimes();
2576
        }
2577
        return this.provider.getTimes();
2578
    }
2579

    
2580
    @Override
2581
    public Collection getTimes(Interval interval) {
2582
        if( this.timeSupport!=null ) {
2583
            return this.timeSupport.getTimes(interval);
2584
        }
2585
        return this.provider.getTimes(interval);
2586
    }
2587

    
2588
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2589
        if( this.isEditing() ) {
2590
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2591
        }
2592
        if( !this.transforms.isEmpty() ) {
2593
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2594
        }
2595
        FeatureType ft = this.defaultFeatureType;
2596
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2597
        if( attr == null ) {
2598
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2599
        }
2600
        EditableFeatureType eft = ft.getEditable();
2601
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2602
        if( attr != null ) {
2603
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2604
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2605
            }
2606
            eft.remove(attr.getName());
2607
        }
2608
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2609
            timeSupport.getAttributeName(), 
2610
            timeSupport.getDataType()
2611
        );
2612
        attrTime.setIsTime(true);
2613
        attrTime.setFeatureAttributeEmulator(timeSupport);
2614
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2615
        this.defaultFeatureType = eft.getNotEditableCopy();
2616
        
2617
        this.timeSupport = timeSupport;
2618
    }
2619

    
2620
    @Override
2621
    @SuppressWarnings("CloneDoesntCallSuperClone")
2622
    public Object clone() throws CloneNotSupportedException {
2623

    
2624
        DataStoreParameters dsp = getParameters();
2625

    
2626
        DefaultFeatureStore cloned_store = null;
2627

    
2628
        try {
2629
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2630
                openStore(this.getProviderName(), dsp);
2631
            if (transforms != null) {
2632
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2633
                cloned_store.transforms.setStoreForClone(cloned_store);
2634
            }
2635
        } catch (Exception e) {
2636
            throw new CloneException(e);
2637
        }
2638
        return cloned_store;
2639

    
2640
    }
2641

    
2642
    @Override
2643
    public Feature getFeature(DynObject dynobject) {
2644
        if (dynobject instanceof DynObjectFeatureFacade){
2645
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2646
            return f;
2647
        }
2648
        return null;
2649
    }
2650

    
2651
    @Override
2652
    public Iterator iterator() {
2653
        try {
2654
            return this.getFeatureSet().fastIterator();
2655
        } catch (DataException ex) {
2656
            throw new RuntimeException(ex);
2657
        }
2658
    }
2659

    
2660
    @Override
2661
    public ExpressionBuilder createExpressionBuilder() {
2662
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2663
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2664
        }
2665
        return new SQLBuilderBase();
2666
    }
2667

    
2668
    @Override
2669
    public ExpressionBuilder createExpression() {
2670
        return createExpressionBuilder();
2671
    }
2672

    
2673
    public FeatureSet features() throws DataException {
2674
        // This is to avoid jython to create a property with this name
2675
        // to access method getFeatures.
2676
        return this.getFeatureSet();
2677
    }
2678

    
2679
    @Override
2680
    public DataStoreProviderFactory getProviderFactory() {
2681
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2682
        return factory;
2683
    }
2684

    
2685
    @Override
2686
    public void useCache(String providerName, DynObject parameters) throws DataException {
2687
        throw new UnsupportedOperationException();
2688
    }
2689

    
2690
    @Override
2691
    public boolean isBroken() {
2692
        return this.state.isBroken();
2693
    }
2694

    
2695
    @Override
2696
    public Throwable getBreakingsCause() {
2697
            return this.state.getBreakingsCause();
2698
    }
2699

    
2700
    @Override
2701
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2702
      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2703
      if( !factory.supportNumericOID() ) {
2704
          return null;
2705
      }
2706
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2707
      return wrappedIndex;
2708
  }
2709

    
2710
    @Override
2711
    public FeatureReference getFeatureReference(String code) {
2712
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2713
        return featureReference;
2714
    }
2715
}