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 @ 43739

History | View | Annotate | Download (89.5 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.spi.SQLBuilderBase;
28

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

    
40
import org.apache.commons.io.FilenameUtils;
41
import org.apache.commons.lang3.StringUtils;
42
import org.cresques.cts.IProjection;
43

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

    
164
import org.slf4j.Logger;
165
import org.slf4j.LoggerFactory;
166

    
167
public class DefaultFeatureStore extends AbstractDisposable implements
168
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
169

    
170
    private static final Logger LOG = LoggerFactory
171
        .getLogger(DefaultFeatureStore.class);
172

    
173
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
174

    
175
    private DataStoreParameters parameters = null;
176
    private FeatureSelection selection;
177
    private FeatureLocks locks;
178

    
179
    private DelegateWeakReferencingObservable delegateObservable =
180
        new DelegateWeakReferencingObservable(this);
181

    
182
    private FeatureCommandsStack commands;
183
    private FeatureTypeManager featureTypeManager;
184
    private FeatureManager featureManager;
185
    private SpatialManager spatialManager;
186

    
187
    private FeatureType defaultFeatureType = null;
188
    private List featureTypes = new ArrayList();
189

    
190
    private int mode = MODE_QUERY;
191
    private long versionOfUpdate = 0;
192
    private boolean hasStrongChanges = true;
193
    private boolean hasInserts = true;
194

    
195
    private DefaultDataManager dataManager = null;
196

    
197
    private FeatureStoreProvider provider = null;
198

    
199
    private DefaultFeatureIndexes indexes;
200

    
201
    private DefaultFeatureStoreTransforms transforms;
202

    
203
    DelegatedDynObject metadata;
204

    
205
    private Set metadataChildren;
206

    
207
    private Long featureCount = null;
208

    
209
    private long temporalOid = 0;
210

    
211
    private FeatureCacheProvider cache;
212

    
213
    StateInformation state;
214

    
215
    FeatureStoreTimeSupport timeSupport;
216

    
217

    
218
    private class StateInformation extends HashMap<Object, Object> {
219

    
220
        private static final long serialVersionUID = 4109026189635185666L;
221

    
222
        private boolean broken;
223
        private Throwable breakingsCause;
224

    
225
        public StateInformation() {
226
            this.clear();
227
        }
228

    
229
        @Override
230
        public void clear() {
231
            this.broken = false;
232
            this.breakingsCause = null;
233
            super.clear();
234
        }
235

    
236
        public boolean isBroken() {
237
            return this.broken;
238
        }
239

    
240
        public void broken() {
241
            this.broken = true;
242
        }
243

    
244
        public Throwable getBreakingsCause() {
245
            return this.breakingsCause;
246
        }
247

    
248
        public void setBreakingsCause(Throwable cause) {
249
            if( this.breakingsCause==null ) {
250
                this.breakingsCause = cause;
251
            }
252
            this.broken = true;
253
        }
254
    }
255

    
256

    
257

    
258
    /*
259
     * TODO:
260
     *
261
     * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
262
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
263
     * featureType al que se le han cambiado las reglas de validacion cuando
264
     * hasStrongChanges=false.
265
     */
266

    
267
    public DefaultFeatureStore() {
268
        this.state = new StateInformation();
269
    }
270

    
271
    @Override
272
    public void intialize(DataManager dataManager,
273
        DataStoreParameters parameters) throws InitializeException {
274

    
275
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
276

    
277
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
278
            FeatureStore.METADATA_DEFINITION_NAME,
279
            MetadataManager.METADATA_NAMESPACE
280
        );
281

    
282
        this.dataManager = (DefaultDataManager) dataManager;
283

    
284
        this.parameters = parameters;
285
        this.transforms = new DefaultFeatureStoreTransforms(this);
286
        try {
287
            indexes = new DefaultFeatureIndexes(this);
288
        } catch (DataException e) {
289
            throw new InitializeException(e);
290
        }
291

    
292
    }
293

    
294
    @Override
295
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
296
        this.provider = (FeatureStoreProvider) provider;
297
        this.delegate((DynObject) provider);
298
        this.metadataChildren = new HashSet();
299
        this.metadataChildren.add(provider);
300
    }
301

    
302
    @Override
303
    public DataStoreParameters getParameters() {
304
        return parameters;
305
    }
306

    
307
    public int getMode() {
308
        return this.mode;
309
    }
310

    
311
    @Override
312
    public DataManager getManager() {
313
        return this.dataManager;
314
    }
315

    
316
    @Override
317
    public Iterator getChildren() {
318
        return this.provider.getChilds();
319
    }
320

    
321
    @Override
322
    public FeatureStoreProvider getProvider() {
323
        return this.provider;
324
    }
325

    
326
    public FeatureManager getFeatureManager() {
327
        return this.featureManager;
328
    }
329

    
330
    @Override
331
    public void setFeatureTypes(List types, FeatureType defaultType) {
332
        this.featureTypes = types;
333
        this.defaultFeatureType = defaultType;
334
    }
335

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

    
350
    @Override
351
    public void refresh() throws OpenException, InitializeException {
352
        if (this.mode != MODE_QUERY) {
353
            throw new IllegalStateException();
354
        }
355
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
356
        if( state.isBroken() ) {
357
            this.load(state);
358
        } else {
359
            this.featureCount = null;
360
            this.provider.refresh();
361
        }
362
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
363
    }
364

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

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

    
406
        if (this.featureTypeManager != null) {
407
            this.featureTypeManager.dispose();
408
            this.featureTypeManager = null;
409
        }
410

    
411
        this.featureManager = null;
412
        this.spatialManager = null;
413

    
414
        this.parameters = null;
415
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
416
        if (delegateObservable != null) {
417
            this.delegateObservable.deleteObservers();
418
            this.delegateObservable = null;
419
        }
420
    }
421

    
422
    @Override
423
    public boolean allowWrite() {
424
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
425
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
426
            return false;
427
        }
428
        return this.provider.allowWrite();
429
    }
430

    
431
    @Override
432
    public boolean canWriteGeometry(int geometryType) throws DataException {
433
        return this.provider.canWriteGeometry(geometryType, 0);
434
    }
435

    
436
    @Override
437
    public DataServerExplorer getExplorer() throws ReadException,
438
        ValidateDataParametersException {
439
        if( this.state.isBroken() ) {
440
            try {
441
                return this.provider.getExplorer();
442
            } catch(Throwable th) {
443
                return null;
444
            }
445
        } else {
446
            return this.provider.getExplorer();
447
        }
448
    }
449

    
450
    /*
451
     * public Metadata getMetadata() throws MetadataNotFoundException {
452
     * // TODO:
453
     * // Si el provider devuelbe null habria que ver de construir aqui
454
     * // los metadatos basicos, como el Envelope y el SRS.
455
     *
456
     * // TODO: Estando en edicion el Envelope deberia de
457
     * // actualizarse usando el spatialManager
458
     * return this.provider.getMetadata();
459
     * }
460
     */
461

    
462
    @Override
463
    public Envelope getEnvelope() throws DataException {
464
        if (this.mode == MODE_FULLEDIT) {
465
                // Just in case another thread tries to write in the store
466
                synchronized (this) {
467
                        return this.spatialManager.getEnvelope();
468
                        }
469
        }
470
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
471
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
472
        }
473
        return this.provider.getEnvelope();
474
    }
475

    
476
    /**
477
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
478
     */
479
    @Override
480
    public IProjection getSRSDefaultGeometry() throws DataException {
481
        return this.getDefaultFeatureType().getDefaultSRS();
482
    }
483

    
484
    @Override
485
    public FeatureSelection createDefaultFeatureSelection()
486
        throws DataException {
487
        return new DefaultFeatureSelection(this);
488
    }
489

    
490
    @Override
491
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
492
        throws DataException {
493
        if (type.hasOID()) {
494
            return new DefaultFeatureProvider(type,
495
                this.provider.createNewOID());
496
        }
497
        return new DefaultFeatureProvider(type);
498
    }
499

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

    
535
        }
536

    
537
        if (evaluatedAttr.isEmpty()) {
538
            evaluatedAttr = null;
539
        }
540

    
541
        state.set("evaluatedAttributes", evaluatedAttr);
542
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
543

    
544
    }
545

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

    
584
    private void load(StateInformation state) {
585
        this.featureTypes = new ArrayList();
586
        this.defaultFeatureType = null;
587
        this.featureCount = null;
588

    
589
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
590
        try {
591
            intialize(dataManager, params);
592
        } catch(Throwable th) {
593
            state.setBreakingsCause(th);
594
        }
595

    
596
        try {
597
            DataStoreProvider prov = dataManager.createProvider(
598
                getStoreProviderServices(),
599
                params
600
            );
601
            setProvider(prov);
602
        } catch(Throwable th) {
603
            state.setBreakingsCause(th);
604
        }
605

    
606
        try {
607
            selection = (FeatureSelection) state.get("selection");
608
        } catch(Throwable th) {
609
            state.setBreakingsCause(th);
610
        }
611

    
612
        try {
613
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
614
            this.transforms.setFeatureStore(this);
615
            for( FeatureStoreTransform transform : this.transforms ) {
616
                try {
617
                    transform.setUp();
618
                } catch(Throwable th) {
619
                    state.setBreakingsCause(th);
620
                }
621
            }
622
        } catch(Throwable th) {
623
            state.setBreakingsCause(th);
624
        }
625

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

    
657
                    }
658

    
659
            }
660
        } catch(Throwable th) {
661
            state.setBreakingsCause(th);
662
        }
663

    
664

    
665
        try {
666
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
667
            FeatureType ftype;
668

    
669
            if (defaultFeatureType == null ||
670
                    defaultFeatureType.getId() == null ||
671
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
672

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

    
692
        LOG.info("load() broken:{}, {}, {}.",
693
                new Object[] { state.isBroken(), this.getProviderName(), params }
694
        );
695
    }
696

    
697
        public DataStoreProviderServices getStoreProviderServices() {
698
                return this;
699
        }
700

    
701
    public static void registerPersistenceDefinition() {
702
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
703
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
704
            DynStruct definition =
705
                manager.addDefinition(DefaultFeatureStore.class,
706
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
707
                        + " Persistent definition", null, null);
708
            definition.addDynFieldString("dataStoreName").setMandatory(true)
709
                .setPersistent(true);
710

    
711
            definition.addDynFieldObject("parameters")
712
                .setClassOfValue(DynObject.class).setMandatory(true)
713
                .setPersistent(true);
714

    
715
            definition.addDynFieldObject("selection")
716
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
717
                .setPersistent(true);
718

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

    
723
            definition.addDynFieldMap("evaluatedAttributes")
724
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
725
                .setMandatory(false).setPersistent(true);
726

    
727
            definition.addDynFieldString("defaultFeatureTypeId")
728
                .setMandatory(true).setPersistent(true);
729
        }
730
    }
731

    
732
    public static void registerMetadataDefinition() throws MetadataException {
733
        MetadataManager manager = MetadataLocator.getMetadataManager();
734
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
735
            DynStruct metadataDefinition =
736
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
737
            metadataDefinition.extend(manager
738
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
739
        }
740
    }
741

    
742
    //
743
    // ====================================================================
744
    // Gestion de la seleccion
745
    //
746

    
747
    @Override
748
    public void setSelection(DataSet selection) throws DataException {
749
        this.setSelection((FeatureSet) selection);
750
    }
751

    
752
    @Override
753
    public DataSet createSelection() throws DataException {
754
        return createFeatureSelection();
755
    }
756

    
757
    @Override
758
    public DataSet getSelection() throws DataException {
759
        return this.getFeatureSelection();
760
    }
761

    
762
    @Override
763
    public void setSelection(FeatureSet selection) throws DataException {
764
        setSelection(selection, true);
765
    }
766

    
767
    public void setSelection(FeatureSet selection, boolean undoable)
768
        throws DataException {
769
        if (selection == null) {
770
            if (undoable) {
771
                throw new SelectionNotAllowedException(getName());
772
            }
773

    
774
        } else {
775
            if (selection.equals(this.selection)) {
776
                return;
777
            }
778
            if (!selection.isFromStore(this)) {
779
                throw new SelectionNotAllowedException(getName());
780
            }
781
        }
782

    
783
        if (this.selection != null) {
784
            this.selection.deleteObserver(this);
785
        }
786
        if (selection == null) {
787
            if (this.selection != null) {
788
                this.selection.dispose();
789
            }
790
            this.selection = null;
791
            return;
792
        }
793
        if (selection instanceof FeatureSelection) {
794
            if (undoable && isEditing()) {
795
                commands.selectionSet(this, this.selection,
796
                    (FeatureSelection) selection);
797
            }
798
            if (this.selection != null) {
799
                this.selection.dispose();
800
            }
801
            this.selection = (FeatureSelection) selection;
802
        } else {
803
            if (undoable && isEditing()) {
804
                commands.startComplex("_selectionSet");
805
            }
806
            if (selection instanceof DefaultFeatureSelection) {
807
                DefaultFeatureSelection defSelection =
808
                    (DefaultFeatureSelection) selection;
809
                defSelection.deselectAll(undoable);
810
                defSelection.select(selection, undoable);
811
            } else {
812
                this.selection.deselectAll();
813
                this.selection.select(selection);
814
            }
815
            if (undoable && isEditing()) {
816
                commands.endComplex();
817
            }
818
        }
819
        this.selection.addObserver(this);
820

    
821
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
822
    }
823

    
824
    @Override
825
    public FeatureSelection createFeatureSelection() throws DataException {
826
        return this.provider.createFeatureSelection();
827
    }
828

    
829
    @Override
830
    public FeatureSelection getFeatureSelection() throws DataException {
831
        if (selection == null) {
832
            this.selection = createFeatureSelection();
833
            this.selection.addObserver(this);
834
        }
835
        return selection;
836
    }
837

    
838
    //
839
    // ====================================================================
840
    // Gestion de notificaciones
841
    //
842

    
843
    @Override
844
    public void notifyChange(FeatureStoreNotification storeNotification) {
845
        try {
846
            delegateObservable.notifyObservers(storeNotification);
847
        } catch (Throwable ex) {
848
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
849
        }
850
    }
851

    
852
    @Override
853
    public void notifyChange(String notification) {
854
        if (delegateObservable != null) {
855
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
856
        }
857

    
858
    }
859

    
860
    @Override
861
    public void notifyChange(String notification, FeatureProvider data) {
862
        Feature f = null;
863
        try {
864
            f = createFeature(data);
865
        } catch (Throwable ex) {
866
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
867
        }
868
        notifyChange(notification, f);
869
    }
870

    
871
    public void notifyChange(String notification, Feature feature) {
872
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
873
            feature));
874
    }
875

    
876
    public void notifyChange(String notification, Command command) {
877
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
878
            command));
879
    }
880

    
881
    public void notifyChange(String notification, EditableFeatureType type) {
882
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
883
            type));
884
    }
885

    
886
    @Override
887
    public void notifyChange(String notification, Resource resource) {
888
        notifyChange(new DefaultFeatureStoreNotification(this,
889
            DataStoreNotification.RESOURCE_CHANGED));
890
    }
891

    
892
    //
893
    // ====================================================================
894
    // Gestion de bloqueos
895
    //
896

    
897
    @Override
898
    public boolean isLocksSupported() {
899
        return this.provider.isLocksSupported();
900
    }
901

    
902
    @Override
903
    public FeatureLocks getLocks() throws DataException {
904
        if (!this.provider.isLocksSupported()) {
905
            LOG.warn("Locks not supported");
906
            return null;
907
        }
908
        if (locks == null) {
909
            this.locks = this.provider.createFeatureLocks();
910
        }
911
        return locks;
912
    }
913

    
914
    //
915
    // ====================================================================
916
    // Interface Observable
917
    //
918

    
919
    @Override
920
    public void disableNotifications() {
921
        this.delegateObservable.disableNotifications();
922

    
923
    }
924

    
925
    @Override
926
    public void enableNotifications() {
927
        this.delegateObservable.enableNotifications();
928
    }
929

    
930
    @Override
931
    public void beginComplexNotification() {
932
        this.delegateObservable.beginComplexNotification();
933

    
934
    }
935

    
936
    @Override
937
    public void endComplexNotification() {
938
        this.delegateObservable.endComplexNotification();
939

    
940
    }
941

    
942
    @Override
943
    public void addObserver(Observer observer) {
944
        if (delegateObservable != null) {
945
            this.delegateObservable.addObserver(observer);
946
        }
947
    }
948

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

    
956
    @Override
957
    public void deleteObservers() {
958
        this.delegateObservable.deleteObservers();
959

    
960
    }
961

    
962
    //
963
    // ====================================================================
964
    // Interface Observer
965
    //
966
    // Usado para observar:
967
    // - su seleccion
968
    // - sus bloqueos
969
    // - sus recursos
970
    //
971

    
972
    @Override
973
    public void update(Observable observable, Object notification) {
974
        if (observable instanceof FeatureSet) {
975
            if (observable == this.selection) {
976
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
977
            } else if (observable == this.locks) {
978
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
979
            }
980

    
981
        } else if (observable instanceof FeatureStoreProvider) {
982
            if (observable == this.provider) {
983

    
984
            }
985
        } else if (observable instanceof FeatureReferenceSelection) {
986
            if(notification instanceof String){
987
                    this.notifyChange((String)notification);
988
            }
989
        }
990
    }
991

    
992
    //
993
    // ====================================================================
994
    // Edicion
995
    //
996

    
997
    private void newVersionOfUpdate() {
998
        this.versionOfUpdate++;
999
    }
1000

    
1001
    private long currentVersionOfUpdate() {
1002
        return this.versionOfUpdate;
1003
    }
1004

    
1005
    private void checkInEditingMode() throws NeedEditingModeException {
1006
        if (mode != MODE_FULLEDIT) {
1007
            throw new NeedEditingModeException(this.getName());
1008
        }
1009
    }
1010

    
1011
    private void checkNotInAppendMode() throws IllegalStateException {
1012
        if (mode == MODE_APPEND) {
1013
                        throw new IllegalStateException("Error: store "
1014
                                        + this.getFullName() + " is in append mode");
1015
        }
1016
    }
1017

    
1018
    private void checkIsOwnFeature(Feature feature)
1019
        throws IllegalFeatureException {
1020
        if (((DefaultFeature) feature).getStore() != this) {
1021
            throw new IllegalFeatureException(this.getName());
1022
        }
1023
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1024
        // fixFeatureType((DefaultFeatureType) feature.getType());
1025
    }
1026

    
1027
    private void exitEditingMode() {
1028
        if (commands != null) {
1029
            commands.clear();
1030
            commands = null;
1031
        }
1032

    
1033
        if (featureTypeManager != null) {
1034
            featureTypeManager.dispose();
1035
            featureTypeManager = null;
1036

    
1037
        }
1038

    
1039
        // TODO implementar un dispose para estos dos
1040
        featureManager = null;
1041
        spatialManager = null;
1042

    
1043
        featureCount = null;
1044

    
1045
        mode = MODE_QUERY;
1046
        hasStrongChanges = true; // Lo deja a true por si las moscas
1047
        hasInserts = true;
1048
    }
1049

    
1050
    @Override
1051
    synchronized public void edit() throws DataException {
1052
        edit(MODE_FULLEDIT);
1053
    }
1054

    
1055
    @Override
1056
    synchronized public void edit(int mode) throws DataException {
1057
        LOG.debug("Starting editing in mode: {}", mode);
1058
        try {
1059
            if (this.mode != MODE_QUERY) {
1060
                throw new AlreadyEditingException(this.getName());
1061
            }
1062
            if (!this.provider.supportsAppendMode()) {
1063
                mode = MODE_FULLEDIT;
1064
            }
1065
            switch (mode) {
1066
            case MODE_QUERY:
1067
                throw new IllegalStateException(this.getName());
1068

    
1069
            case MODE_FULLEDIT:
1070
                if (!this.transforms.isEmpty()) {
1071
                    throw new IllegalStateException(this.getName());
1072
                }
1073
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1074
                invalidateIndexes();
1075
                featureManager =
1076
                    new FeatureManager(new MemoryExpansionAdapter());
1077
                featureTypeManager =
1078
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
1079
                spatialManager =
1080
                    new SpatialManager(this, provider.getEnvelope());
1081

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

    
1107
    private void invalidateIndexes() {
1108
        setIndexesValidStatus(false);
1109
    }
1110

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

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

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

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

    
1167
    @Override
1168
    public boolean isEditing() {
1169
        return mode == MODE_FULLEDIT;
1170
    }
1171

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

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

    
1189
            FeatureType oldt = type.getSource().getCopy();
1190
            FeatureType newt = type.getCopy();
1191
            commands.update(newt, oldt);
1192

    
1193
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
1194
                hasStrongChanges = true;
1195
            }
1196
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1197
        } catch (Exception e) {
1198
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1199
        }
1200
    }
1201

    
1202
    @Override
1203
    public void delete(Feature feature) throws DataException {
1204
        this.commands.delete(feature);
1205
    }
1206

    
1207
    synchronized public void doDelete(Feature feature) throws DataException {
1208
        try {
1209
            checkInEditingMode();
1210
            checkIsOwnFeature(feature);
1211
            if (feature instanceof EditableFeature) {
1212
                throw new StoreDeleteEditableFeatureException(getName());
1213
            }
1214
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1215

    
1216
            //Update the featureManager and the spatialManager
1217
            featureManager.delete(feature.getReference());
1218
            spatialManager.deleteFeature(feature);
1219

    
1220
            newVersionOfUpdate();
1221
            hasStrongChanges = true;
1222
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1223
        } catch (Exception e) {
1224
            throw new StoreDeleteFeatureException(e, this.getName());
1225
        }
1226
    }
1227

    
1228
    private static EditableFeature lastChangedFeature = null;
1229

    
1230
    @Override
1231
    public synchronized void insert(EditableFeature feature)
1232
        throws DataException {
1233
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1234
        try {
1235
            switch (mode) {
1236
            case MODE_QUERY:
1237
                throw new NeedEditingModeException(this.getName());
1238

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

    
1253
            case MODE_FULLEDIT:
1254
                if (feature.getSource() != null) {
1255
                    throw new NoNewFeatureInsertException(this.getName());
1256
                }
1257
                commands.insert(feature);
1258
            }
1259
        } catch (Exception e) {
1260
            throw new StoreInsertFeatureException(e, this.getName());
1261
        }
1262
    }
1263

    
1264
    synchronized public void doInsert(EditableFeature feature)
1265
        throws DataException {
1266
        checkIsOwnFeature(feature);
1267

    
1268
        waitForIndexes();
1269

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

    
1282

    
1283
        featureManager.add(newFeature);
1284
        spatialManager.insertFeature(newFeature);
1285

    
1286
        hasStrongChanges = true;
1287
        hasInserts = true;
1288
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1289
    }
1290

    
1291
    @Override
1292
    public void update(EditableFeature feature)
1293
    throws DataException {
1294
        if ((feature).getSource() == null) {
1295
            insert(feature);
1296
            return;
1297
        }
1298
        commands.update(feature, feature.getSource());
1299
    }
1300

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

    
1315
            //Update the featureManager and the spatialManager
1316
            Feature newf = feature.getNotEditableCopy();
1317
            featureManager.update(newf, oldFeature);
1318
            spatialManager.updateFeature(newf, oldFeature);
1319

    
1320
            hasStrongChanges = true;
1321
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1322
        } catch (Exception e) {
1323
            throw new StoreUpdateFeatureException(e, this.getName());
1324
        }
1325
    }
1326

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

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

    
1357
    @Override
1358
    public List getRedoInfos() {
1359
        if (isEditing() && (commands != null)) {
1360
            return commands.getRedoInfos();
1361
        } else {
1362
            return null;
1363
        }
1364
    }
1365

    
1366
    @Override
1367
    public List getUndoInfos() {
1368
        if (isEditing() && (commands != null)) {
1369
            return commands.getUndoInfos();
1370
        } else {
1371
            return null;
1372
        }
1373
    }
1374

    
1375
    public synchronized FeatureCommandsStack getCommandsStack()
1376
        throws DataException {
1377
        checkInEditingMode();
1378
        return commands;
1379
    }
1380

    
1381
    @Override
1382
    synchronized public void cancelEditing() throws DataException {
1383
        if( spatialManager!=null ) {
1384
            spatialManager.cancelModifies();
1385
        }
1386
        try {
1387
            switch (mode) {
1388
            case MODE_QUERY:
1389
                throw new NeedEditingModeException(this.getName());
1390

    
1391
            case MODE_APPEND:
1392
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1393
                provider.abortAppend();
1394
                exitEditingMode();
1395
                ((FeatureSelection) this.getSelection()).deselectAll();
1396
                updateIndexes();
1397
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1398

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

    
1417
    @Override
1418
    synchronized public void finishEditing() throws DataException {
1419
        LOG.debug("finish editing of mode: {}", mode);
1420
        try {
1421

    
1422
            /*
1423
             * Selection needs to be cleared when editing stops
1424
             * to prevent conflicts with selection remaining from
1425
             * editing mode.
1426
             */
1427
//            ((FeatureSelection) this.getSelection()).deselectAll();
1428

    
1429
            switch (mode) {
1430
            case MODE_QUERY:
1431
                throw new NeedEditingModeException(this.getName());
1432

    
1433
            case MODE_APPEND:
1434
                if( selection!=null ) {
1435
                    selection = null;
1436
                }
1437
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1438
                provider.endAppend();
1439
                exitEditingMode();
1440
                updateIndexes();
1441
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1442
                break;
1443

    
1444
            case MODE_FULLEDIT:
1445
                if (hasStrongChanges && !this.allowWrite()) {
1446
                    throw new WriteNotAllowedException(getName());
1447
                }
1448
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1449
                    selection = null;
1450
                }
1451
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1452
                if (hasStrongChanges) {
1453
                    validateFeatures(Feature.FINISH_EDITING);
1454

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

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

    
1495
        case MODE_APPEND:
1496
          this.provider.endAppend();
1497
          exitEditingMode();
1498
          invalidateIndexes();
1499
          this.provider.beginAppend();
1500
          hasInserts = false;
1501
          break;
1502

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

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

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

    
1545
        case MODE_APPEND:
1546
                return true;
1547

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

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

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

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

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

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

    
1598
            }
1599
            explorer.add(provider, params, true);
1600

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

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

    
1636
    //
1637
    // ====================================================================
1638
    // Obtencion de datos
1639
    // getDataCollection, getFeatureCollection
1640
    //
1641

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1813
            private final FeatureStore store;
1814
            private final FeatureQuery query;
1815
            private final Observer observer;
1816

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

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

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

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

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

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

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

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

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

    
1896
    //
1897
    // ====================================================================
1898
    // Gestion de features
1899
    //
1900

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

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

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

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

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

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

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

    
1975
        }
1976

    
1977
        return type;
1978
    }
1979

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

    
2007
    @Override
2008
    public FeatureType getDefaultFeatureType() throws DataException {
2009
        try {
2010

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

    
2023
            return avoidEditable(defaultFeatureType);
2024

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

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

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

    
2069
    public FeatureType getProviderDefaultFeatureType() {
2070
        return defaultFeatureType;
2071
    }
2072

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

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

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

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

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

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

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

    
2154
    }
2155

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

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

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

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

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

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

    
2210
    //
2211
    // ====================================================================
2212
    // Index related methods
2213
    //
2214

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

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

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

    
2231
        return createIndex(indexTypeName, featureType, attributeName,
2232
            indexName, false, null);
2233
    }
2234

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

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

    
2248
        return createIndex(indexTypeName, featureType, attributeName,
2249
            indexName, true, observer);
2250
    }
2251

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

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

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

    
2268
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2269
        return index;
2270
    }
2271

    
2272
    //
2273
    // ====================================================================
2274
    // Transforms related methods
2275
    //
2276

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

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

    
2287
    @Override
2288
    public DataQuery createQuery() {
2289
        return createFeatureQuery();
2290
    }
2291

    
2292
    //
2293
    // ====================================================================
2294
    // UndoRedo related methods
2295
    //
2296

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

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

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

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

    
2321
    //
2322
    // ====================================================================
2323
    // Metadata related methods
2324
    //
2325

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

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

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

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

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

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

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

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

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

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

    
2402
    }
2403

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

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

    
2424
    public FeatureTypeManager getFeatureTypeManager() {
2425
        return this.featureTypeManager;
2426
    }
2427

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

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

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

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

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

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

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

    
2495
        featureCount = null;
2496
    }
2497

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

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

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

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

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

    
2546
    }
2547

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

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

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

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

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

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

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

    
2619
    @Override
2620
    public Object clone() throws CloneNotSupportedException {
2621

    
2622
        DataStoreParameters dsp = getParameters();
2623

    
2624
        DefaultFeatureStore cloned_store = null;
2625

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

    
2638
    }
2639

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

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

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

    
2666
    @Override
2667
    public ExpressionBuilder createExpression() {
2668
        return createExpressionBuilder();
2669
    }
2670

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

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

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

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

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

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