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

History | View | Annotate | Download (98.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 java.io.File;
28
import org.gvsig.fmap.dal.feature.impl.editing.memory.SpatialManager;
29
import org.gvsig.fmap.dal.feature.impl.editing.memory.FeatureTypeManager;
30
import org.gvsig.fmap.dal.feature.impl.editing.memory.FeatureManager;
31
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
32

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

    
45
import org.apache.commons.io.FilenameUtils;
46
import org.apache.commons.lang3.StringUtils;
47
import org.cresques.cts.IProjection;
48
import org.gvsig.expressionevaluator.Expression;
49
import org.gvsig.expressionevaluator.ExpressionBuilder;
50
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
51

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

    
172
import org.slf4j.Logger;
173
import org.slf4j.LoggerFactory;
174

    
175
public class DefaultFeatureStore extends AbstractDisposable implements
176
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
177

    
178
    private static final Logger LOG = LoggerFactory
179
        .getLogger(DefaultFeatureStore.class);
180

    
181
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
182

    
183
    private DataStoreParameters parameters = null;
184
    private FeatureSelection selection;
185
    private FeatureLocks locks;
186

    
187
    private DelegateWeakReferencingObservable delegateObservable =
188
        new DelegateWeakReferencingObservable(this);
189

    
190
    private FeatureCommandsStack commands;
191
    
192
    /*
193
    TODO: Sustituir estos tres manager por un EditingManager
194
    */
195
    private FeatureTypeManager featureTypeManager;
196
    private FeatureManager featureManager;
197
    private SpatialManager spatialManager;
198

    
199
    private FeatureType defaultFeatureType = null;
200
    private List featureTypes = new ArrayList();
201

    
202
    private int mode = MODE_QUERY;
203
    private long versionOfUpdate = 0;
204
    private boolean hasStrongChanges = true;
205
    private boolean hasInserts = true;
206

    
207
    private DefaultDataManager dataManager = null;
208

    
209
    private FeatureStoreProvider provider = null;
210

    
211
    private DefaultFeatureIndexes indexes;
212

    
213
    private DefaultFeatureStoreTransforms transforms;
214

    
215
    DelegatedDynObject metadata;
216

    
217
    private Set metadataChildren;
218

    
219
    private Long featureCount = null;
220

    
221
    private long temporalOid = 0;
222

    
223
    private FeatureCacheProvider cache;
224

    
225
    StateInformation state;
226

    
227
    FeatureStoreTimeSupport timeSupport;
228

    
229

    
230
    private class StateInformation extends HashMap<Object, Object> {
231

    
232
        private static final long serialVersionUID = 4109026189635185666L;
233

    
234
        private boolean broken;
235
        private Throwable breakingsCause;
236

    
237
        @SuppressWarnings("OverridableMethodCallInConstructor")
238
        public StateInformation() {
239
            this.clear();
240
        }
241

    
242
        @Override
243
        public void clear() {
244
            this.broken = false;
245
            this.breakingsCause = null;
246
            super.clear();
247
        }
248

    
249
        public boolean isBroken() {
250
            return this.broken;
251
        }
252

    
253
        public void broken() {
254
            this.broken = true;
255
        }
256

    
257
        public Throwable getBreakingsCause() {
258
            return this.breakingsCause;
259
        }
260

    
261
        public void setBreakingsCause(Throwable cause) {
262
            if( this.breakingsCause==null ) {
263
                this.breakingsCause = cause;
264
            }
265
            this.broken = true;
266
        }
267
    }
268

    
269

    
270

    
271
    /*
272
     * TODO:
273
     *
274
     * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
275
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
276
     * featureType al que se le han cambiado las reglas de validacion cuando
277
     * hasStrongChanges=false.
278
     */
279

    
280
    public DefaultFeatureStore() {
281
        this.state = new StateInformation();
282
    }
283

    
284
    @Override
285
    public void intialize(DataManager dataManager,
286
        DataStoreParameters parameters) throws InitializeException {
287

    
288
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
289

    
290
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
291
            FeatureStore.METADATA_DEFINITION_NAME,
292
            MetadataManager.METADATA_NAMESPACE
293
        );
294

    
295
        this.dataManager = (DefaultDataManager) dataManager;
296

    
297
        this.parameters = parameters;
298
        this.transforms = new DefaultFeatureStoreTransforms(this);
299
        try {
300
            indexes = new DefaultFeatureIndexes(this);
301
        } catch (DataException e) {
302
            throw new InitializeException(e);
303
        }
304

    
305
    }
306

    
307
    @Override
308
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
309
        this.provider = (FeatureStoreProvider) provider;
310
        this.delegate((DynObject) provider);
311
        this.metadataChildren = new HashSet();
312
        this.metadataChildren.add(provider);
313
        loadDALFile();
314
    }
315

    
316
    @Override
317
    public DataStoreParameters getParameters() {
318
        return parameters;
319
    }
320

    
321
    public int getMode() {
322
        return this.mode;
323
    }
324

    
325
    @Override
326
    public DataManager getManager() {
327
        return this.dataManager;
328
    }
329

    
330
    @Override
331
    public Iterator getChildren() {
332
        return this.provider.getChilds();
333
    }
334

    
335
    @Override
336
    public FeatureStoreProvider getProvider() {
337
        return this.provider;
338
    }
339

    
340
    public FeatureManager getFeatureManager() {
341
        return this.featureManager;
342
    }
343

    
344
    @Override
345
    public void setFeatureTypes(List types, FeatureType defaultType) {
346
        this.featureTypes = types;
347
        this.defaultFeatureType = defaultType;
348
    }
349

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

    
364
    @Override
365
    public void refresh() throws OpenException, InitializeException {
366
        if (this.mode != MODE_QUERY) {
367
            throw new IllegalStateException();
368
        }
369
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
370
        if( state.isBroken() ) {
371
            this.load(state);
372
        } else {
373
            this.featureCount = null;
374
            this.provider.refresh();
375
        }
376
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
377
    }
378

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

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

    
420
        if (this.featureTypeManager != null) {
421
            this.featureTypeManager.dispose();
422
            this.featureTypeManager = null;
423
        }
424

    
425
        this.featureManager = null;
426
        this.spatialManager = null;
427

    
428
        this.parameters = null;
429
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
430
        if (delegateObservable != null) {
431
            this.delegateObservable.deleteObservers();
432
            this.delegateObservable = null;
433
        }
434
    }
435

    
436
    @Override
437
    public boolean allowWrite() {
438
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
439
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
440
            return false;
441
        }
442
        return this.provider.allowWrite();
443
    }
444

    
445
    @Override
446
    public boolean canWriteGeometry(int geometryType) throws DataException {
447
        return this.provider.canWriteGeometry(geometryType, 0);
448
    }
449

    
450
    @Override
451
    public DataServerExplorer getExplorer() throws ReadException,
452
        ValidateDataParametersException {
453
        if( this.state.isBroken() ) {
454
            try {
455
                return this.provider.getExplorer();
456
            } catch(Throwable th) {
457
                return null;
458
            }
459
        } else {
460
            return this.provider.getExplorer();
461
        }
462
    }
463

    
464
    /*
465
     * public Metadata getMetadata() throws MetadataNotFoundException {
466
     * // TODO:
467
     * // Si el provider devuelbe null habria que ver de construir aqui
468
     * // los metadatos basicos, como el Envelope y el SRS.
469
     *
470
     * // TODO: Estando en edicion el Envelope deberia de
471
     * // actualizarse usando el spatialManager
472
     * return this.provider.getMetadata();
473
     * }
474
     */
475

    
476
    @Override
477
    public Envelope getEnvelope() throws DataException {
478
        if (this.mode == MODE_FULLEDIT) {
479
                // Just in case another thread tries to write in the store
480
                synchronized (this) {
481
                        return this.spatialManager.getEnvelope();
482
                        }
483
        }
484
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
485
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
486
        }
487
        return this.provider.getEnvelope();
488
    }
489

    
490
    /**
491
     * @throws org.gvsig.fmap.dal.exception.DataException
492
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
493
     */
494
    @Override
495
    public IProjection getSRSDefaultGeometry() throws DataException {
496
        return this.getDefaultFeatureType().getDefaultSRS();
497
    }
498

    
499
    @Override
500
    public FeatureSelection createDefaultFeatureSelection()
501
        throws DataException {
502
        return new DefaultFeatureSelection(this);
503
    }
504

    
505
    @Override
506
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
507
        throws DataException {
508
        if (type.hasOID()) {
509
            return new DefaultFeatureProvider(type,
510
                this.provider.createNewOID());
511
        }
512
        return new DefaultFeatureProvider(type);
513
    }
514

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

    
550
        }
551

    
552
        if (evaluatedAttr.isEmpty()) {
553
            evaluatedAttr = null;
554
        }
555

    
556
        state.set("evaluatedAttributes", evaluatedAttr);
557
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
558

    
559
    }
560

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

    
599
    private void load(StateInformation state) {
600
        this.featureTypes = new ArrayList();
601
        this.defaultFeatureType = null;
602
        this.featureCount = null;
603

    
604
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
605
        try {
606
            intialize(dataManager, params);
607
        } catch(Throwable th) {
608
            state.setBreakingsCause(th);
609
        }
610

    
611
        try {
612
            DataStoreProvider prov = dataManager.createProvider(
613
                getStoreProviderServices(),
614
                params
615
            );
616
            setProvider(prov);
617
        } catch(Throwable th) {
618
            state.setBreakingsCause(th);
619
        }
620

    
621
        try {
622
            selection = (FeatureSelection) state.get("selection");
623
        } catch(Throwable th) {
624
            state.setBreakingsCause(th);
625
        }
626

    
627
        try {
628
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
629
            this.transforms.setFeatureStore(this);
630
            for( FeatureStoreTransform transform : this.transforms ) {
631
                try {
632
                    transform.setUp();
633
                } catch(Throwable th) {
634
                    state.setBreakingsCause(th);
635
                }
636
            }
637
        } catch(Throwable th) {
638
            state.setBreakingsCause(th);
639
        }
640

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

    
672
                    }
673

    
674
            }
675
        } catch(Throwable th) {
676
            state.setBreakingsCause(th);
677
        }
678

    
679

    
680
        try {
681
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
682
            FeatureType ftype;
683

    
684
            if (defaultFeatureType == null ||
685
                    defaultFeatureType.getId() == null ||
686
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
687

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

    
707
        LOG.info("load() broken:{}, {}, {}.",
708
                new Object[] { state.isBroken(), this.getProviderName(), params }
709
        );
710
    }
711

    
712
        public DataStoreProviderServices getStoreProviderServices() {
713
                return this;
714
        }
715

    
716
    public static void registerPersistenceDefinition() {
717
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
718
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
719
            DynStruct definition =
720
                manager.addDefinition(DefaultFeatureStore.class,
721
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
722
                        + " Persistent definition", null, null);
723
            definition.addDynFieldString("dataStoreName").setMandatory(true)
724
                .setPersistent(true);
725

    
726
            definition.addDynFieldObject("parameters")
727
                .setClassOfValue(DynObject.class).setMandatory(true)
728
                .setPersistent(true);
729

    
730
            definition.addDynFieldObject("selection")
731
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
732
                .setPersistent(true);
733

    
734
            definition.addDynFieldObject("transforms")
735
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
736
                .setMandatory(true).setPersistent(true);
737

    
738
            definition.addDynFieldMap("evaluatedAttributes")
739
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
740
                .setMandatory(false).setPersistent(true);
741

    
742
            definition.addDynFieldString("defaultFeatureTypeId")
743
                .setMandatory(true).setPersistent(true);
744
        }
745
    }
746

    
747
    public static void registerMetadataDefinition() throws MetadataException {
748
        MetadataManager manager = MetadataLocator.getMetadataManager();
749
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
750
            DynStruct metadataDefinition =
751
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
752
            metadataDefinition.extend(manager
753
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
754
        }
755
    }
756

    
757
    //
758
    // ====================================================================
759
    // Gestion de la seleccion
760
    //
761

    
762
    @Override
763
    public void setSelection(DataSet selection) throws DataException {
764
        this.setSelection((FeatureSet) selection);
765
    }
766

    
767
    @Override
768
    public DataSet createSelection() throws DataException {
769
        return createFeatureSelection();
770
    }
771

    
772
    @Override
773
    public DataSet getSelection() throws DataException {
774
        return this.getFeatureSelection();
775
    }
776

    
777
    @Override
778
    public void setSelection(FeatureSet selection) throws DataException {
779
        setSelection(selection, true);
780
    }
781

    
782
    public void setSelection(FeatureSet selection, boolean undoable)
783
        throws DataException {
784
        if (selection == null) {
785
            if (undoable) {
786
                throw new SelectionNotAllowedException(getName());
787
            }
788

    
789
        } else {
790
            if (selection.equals(this.selection)) {
791
                return;
792
            }
793
            if (!selection.isFromStore(this)) {
794
                throw new SelectionNotAllowedException(getName());
795
            }
796
        }
797

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

    
836
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
837
    }
838

    
839
    @Override
840
    public FeatureSelection createFeatureSelection() throws DataException {
841
        return this.provider.createFeatureSelection();
842
    }
843

    
844
    @Override
845
    public FeatureSelection getFeatureSelection() throws DataException {
846
        if (selection == null) {
847
            this.selection = createFeatureSelection();
848
            this.selection.addObserver(this);
849
        }
850
        return selection;
851
    }
852

    
853
    //
854
    // ====================================================================
855
    // Gestion de notificaciones
856
    //
857

    
858
    @Override
859
    public void notifyChange(FeatureStoreNotification storeNotification) {
860
        try {
861
            delegateObservable.notifyObservers(storeNotification);
862
        } catch (Throwable ex) {
863
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
864
        }
865
    }
866

    
867
    @Override
868
    public void notifyChange(String notification) {
869
        if (delegateObservable != null) {
870
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
871
        }
872

    
873
    }
874

    
875
    @Override
876
    public void notifyChange(String notification, FeatureProvider data) {
877
        Feature f = null;
878
        try {
879
            f = createFeature(data);
880
        } catch (Throwable ex) {
881
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
882
        }
883
        notifyChange(notification, f);
884
    }
885

    
886
    public void notifyChange(String notification, Feature feature) {
887
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
888
            feature));
889
    }
890

    
891
    public void notifyChange(String notification, Command command) {
892
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
893
            command));
894
    }
895

    
896
    public void notifyChange(String notification, EditableFeatureType type) {
897
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
898
            type));
899
    }
900

    
901
    @Override
902
    public void notifyChange(String notification, Resource resource) {
903
        notifyChange(new DefaultFeatureStoreNotification(this,
904
            DataStoreNotification.RESOURCE_CHANGED));
905
    }
906

    
907
    //
908
    // ====================================================================
909
    // Gestion de bloqueos
910
    //
911

    
912
    @Override
913
    public boolean isLocksSupported() {
914
        return this.provider.isLocksSupported();
915
    }
916

    
917
    @Override
918
    public FeatureLocks getLocks() throws DataException {
919
        if (!this.provider.isLocksSupported()) {
920
            LOG.warn("Locks not supported");
921
            return null;
922
        }
923
        if (locks == null) {
924
            this.locks = this.provider.createFeatureLocks();
925
        }
926
        return locks;
927
    }
928

    
929
    //
930
    // ====================================================================
931
    // Interface Observable
932
    //
933

    
934
    @Override
935
    public void disableNotifications() {
936
        this.delegateObservable.disableNotifications();
937

    
938
    }
939

    
940
    @Override
941
    public void enableNotifications() {
942
        this.delegateObservable.enableNotifications();
943
    }
944

    
945
    @Override
946
    public void beginComplexNotification() {
947
        this.delegateObservable.beginComplexNotification();
948

    
949
    }
950

    
951
    @Override
952
    public void endComplexNotification() {
953
        this.delegateObservable.endComplexNotification();
954

    
955
    }
956

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

    
964
    @Override
965
    public void deleteObserver(Observer observer) {
966
        if (delegateObservable != null) {
967
            this.delegateObservable.deleteObserver(observer);
968
        }
969
    }
970

    
971
    @Override
972
    public void deleteObservers() {
973
        this.delegateObservable.deleteObservers();
974

    
975
    }
976

    
977
    //
978
    // ====================================================================
979
    // Interface Observer
980
    //
981
    // Usado para observar:
982
    // - su seleccion
983
    // - sus bloqueos
984
    // - sus recursos
985
    //
986

    
987
    @Override
988
    public void update(Observable observable, Object notification) {
989
        if (observable instanceof FeatureSet) {
990
            if (observable == this.selection) {
991
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
992
            } else if (observable == this.locks) {
993
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
994
            }
995

    
996
        } else if (observable instanceof FeatureStoreProvider) {
997
            if (observable == this.provider) {
998

    
999
            }
1000
        } else if (observable instanceof FeatureReferenceSelection) {
1001
            if(notification instanceof String){
1002
                    this.notifyChange((String)notification);
1003
            }
1004
        }
1005
    }
1006

    
1007
    //
1008
    // ====================================================================
1009
    // Edicion
1010
    //
1011

    
1012
    private void newVersionOfUpdate() {
1013
        this.versionOfUpdate++;
1014
    }
1015

    
1016
    private long currentVersionOfUpdate() {
1017
        return this.versionOfUpdate;
1018
    }
1019

    
1020
    private void checkInEditingMode() throws NeedEditingModeException {
1021
        if (mode != MODE_FULLEDIT) {
1022
            throw new NeedEditingModeException(this.getName());
1023
        }
1024
    }
1025

    
1026
    private void checkNotInAppendMode() throws IllegalStateException {
1027
        if (mode == MODE_APPEND) {
1028
                        throw new IllegalStateException("Error: store "
1029
                                        + this.getFullName() + " is in append mode");
1030
        }
1031
    }
1032

    
1033
    private void checkIsOwnFeature(Feature feature)
1034
        throws IllegalFeatureException {
1035
        if (((DefaultFeature) feature).getStore() != this) {
1036
            throw new IllegalFeatureException(this.getName());
1037
        }
1038
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1039
        // fixFeatureType((DefaultFeatureType) feature.getType());
1040
    }
1041

    
1042
    private void exitEditingMode() {
1043
        if (commands != null) {
1044
            commands.clear();
1045
            commands = null;
1046
        }
1047

    
1048
        if (featureTypeManager != null) {
1049
            featureTypeManager.dispose();
1050
            featureTypeManager = null;
1051

    
1052
        }
1053

    
1054
        // TODO implementar un dispose para estos dos
1055
        featureManager = null;
1056
        spatialManager = null;
1057

    
1058
        featureCount = null;
1059

    
1060
        mode = MODE_QUERY;
1061
        hasStrongChanges = true; // Lo deja a true por si las moscas
1062
        hasInserts = true;
1063
    }
1064

    
1065
    @Override
1066
    synchronized public void edit() throws DataException {
1067
        edit(MODE_FULLEDIT);
1068
    }
1069

    
1070
    @Override
1071
    synchronized public void edit(int mode) throws DataException {
1072
        LOG.debug("Starting editing in mode: {}", mode);
1073
        try {
1074
            if (this.mode != MODE_QUERY) {
1075
                throw new AlreadyEditingException(this.getName());
1076
            }
1077
            if (!this.provider.supportsAppendMode()) {
1078
                mode = MODE_FULLEDIT;
1079
            }
1080
            switch (mode) {
1081
            case MODE_QUERY:
1082
                throw new IllegalStateException(this.getName());
1083

    
1084
            case MODE_FULLEDIT:
1085
                if (!this.transforms.isEmpty()) {
1086
                    throw new IllegalStateException(this.getName());
1087
                }
1088
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1089
                invalidateIndexes();
1090
                featureManager = new FeatureManager();
1091
                featureTypeManager = new FeatureTypeManager(this);
1092
                spatialManager = new SpatialManager(this, provider.getEnvelope());
1093

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

    
1119
    private void invalidateIndexes() {
1120
        setIndexesValidStatus(false);
1121
    }
1122

    
1123
    private void setIndexesValidStatus(boolean valid) {
1124
        FeatureIndexes theIndexes = getIndexes();
1125
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
1126
            ? Boolean.TRUE : Boolean.FALSE), theIndexes);
1127
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1128
            FeatureIndex index = (FeatureIndex) iterator.next();
1129
            if (index instanceof FeatureIndexProviderServices) {
1130
                FeatureIndexProviderServices indexServices =
1131
                    (FeatureIndexProviderServices) index;
1132
                indexServices.setValid(valid);
1133
            }
1134
        }
1135
    }
1136

    
1137
    private void updateIndexes() throws FeatureIndexException {
1138
        FeatureIndexes theIndexes = getIndexes();
1139
        LOG.debug("Refilling indexes: {}", theIndexes);
1140
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1141
            FeatureIndex index = (FeatureIndex) iterator.next();
1142
            if (index instanceof FeatureIndexProviderServices) {
1143
                FeatureIndexProviderServices indexServices =
1144
                    (FeatureIndexProviderServices) index;
1145
                indexServices.fill(true, null);
1146
            }
1147
        }
1148
    }
1149

    
1150
    private void waitForIndexes() {
1151
        FeatureIndexes theIndexes = getIndexes();
1152
        LOG.debug("Waiting for indexes to finish filling: {}", theIndexes);
1153
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1154
            FeatureIndex index = (FeatureIndex) iterator.next();
1155
            if (index instanceof FeatureIndexProviderServices) {
1156
                FeatureIndexProviderServices indexServices =
1157
                    (FeatureIndexProviderServices) index;
1158
                indexServices.waitForIndex();
1159
            }
1160
        }
1161
    }
1162

    
1163
    private void disposeIndexes() {
1164
        FeatureIndexes theIndexes = getIndexes();
1165
        LOG.debug("Disposing indexes: {}", theIndexes);
1166
        if( theIndexes==null ) {
1167
            return;
1168
        }
1169
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1170
            FeatureIndex index = (FeatureIndex) iterator.next();
1171
            if (index instanceof FeatureIndexProviderServices) {
1172
                FeatureIndexProviderServices indexServices =
1173
                    (FeatureIndexProviderServices) index;
1174
                indexServices.dispose();
1175
            }
1176
        }
1177
    }
1178

    
1179
    @Override
1180
    public boolean isEditing() {
1181
        return mode == MODE_FULLEDIT;
1182
    }
1183

    
1184
    @Override
1185
    public boolean isAppending() {
1186
        return mode == MODE_APPEND;
1187
    }
1188

    
1189
    @Override
1190
    synchronized public void update(EditableFeatureType type)
1191
        throws DataException {
1192
        try {
1193
            if (type == null) {
1194
                throw new NullFeatureTypeException(getName());
1195
            }
1196
            boolean typehasStrongChanges = ((DefaultEditableFeatureType) type).hasStrongChanges();
1197
            if (typehasStrongChanges) {
1198
                checkInEditingMode();
1199
            }  else if(this.isAppending()) {
1200
                throw new NeedEditingModeException(this.getName());
1201
            }
1202
            // FIXME: Comprobar que es un featureType aceptable.
1203
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
1204
            newVersionOfUpdate();
1205
            
1206
            if (typehasStrongChanges) { 
1207
                FeatureType oldt = type.getSource().getCopy();
1208
                FeatureType newt = type.getCopy();
1209
                commands.update(newt, oldt);
1210
                hasStrongChanges = true;
1211
            } else {
1212
                boolean ok = this.featureTypes.remove(this.defaultFeatureType);
1213
                this.defaultFeatureType = type.getNotEditableCopy();
1214
                if (ok) {
1215
                    this.featureTypes.add(this.defaultFeatureType);
1216
                }
1217
            }
1218
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1219
        } catch (Exception e) {
1220
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1221
        }
1222
    }
1223

    
1224
    @Override
1225
    public void delete(Feature feature) throws DataException {
1226
        this.commands.delete(feature);
1227
    }
1228

    
1229
    synchronized public void doDelete(Feature feature) throws DataException {
1230
        try {
1231
            checkInEditingMode();
1232
            checkIsOwnFeature(feature);
1233
            if (feature instanceof EditableFeature) {
1234
                throw new StoreDeleteEditableFeatureException(getName());
1235
            }
1236
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1237

    
1238
            //Update the featureManager and the spatialManager
1239
            featureManager.delete(feature.getReference());
1240
            spatialManager.deleteFeature(feature);
1241

    
1242
            newVersionOfUpdate();
1243
            hasStrongChanges = true;
1244
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1245
        } catch (Exception e) {
1246
            throw new StoreDeleteFeatureException(e, this.getName());
1247
        }
1248
    }
1249

    
1250
    private static EditableFeature lastChangedFeature = null;
1251

    
1252
    @Override
1253
    public synchronized void insert(EditableFeature feature)
1254
        throws DataException {
1255
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1256
        try {
1257
            switch (mode) {
1258
            case MODE_QUERY:
1259
                throw new NeedEditingModeException(this.getName());
1260

    
1261
            case MODE_APPEND:
1262
                checkIsOwnFeature(feature);
1263
                if (feature.getSource() != null) {
1264
                    throw new NoNewFeatureInsertException(this.getName());
1265
                }
1266
                this.featureCount = null;
1267
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1268
                feature.validate(Feature.UPDATE);
1269
                provider.append(((DefaultEditableFeature) feature).getData());
1270
                hasStrongChanges = true;
1271
                hasInserts = true;
1272
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1273
                break;
1274

    
1275
            case MODE_FULLEDIT:
1276
                if (feature.getSource() != null) {
1277
                    throw new NoNewFeatureInsertException(this.getName());
1278
                }
1279
                commands.insert(feature);
1280
            }
1281
        } catch (Exception e) {
1282
            throw new StoreInsertFeatureException(e, this.getName());
1283
        }
1284
    }
1285

    
1286
    synchronized public void doInsert(EditableFeature feature)
1287
        throws DataException {
1288
        checkIsOwnFeature(feature);
1289

    
1290
        waitForIndexes();
1291

    
1292
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1293
        newVersionOfUpdate();
1294
        if ((lastChangedFeature == null)
1295
            || (lastChangedFeature.getSource() != feature.getSource())) {
1296
            lastChangedFeature = feature;
1297
            feature.validate(Feature.UPDATE);
1298
            lastChangedFeature = null;
1299
        }
1300
        //Update the featureManager and the spatialManager
1301
        ((DefaultEditableFeature) feature).setInserted(true);
1302
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1303

    
1304

    
1305
        featureManager.add(newFeature);
1306
        spatialManager.insertFeature(newFeature);
1307

    
1308
        hasStrongChanges = true;
1309
        hasInserts = true;
1310
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1311
    }
1312

    
1313
    @Override
1314
    public void update(EditableFeature feature)
1315
    throws DataException {
1316
        if ((feature).getSource() == null) {
1317
            insert(feature);
1318
            return;
1319
        }
1320
        commands.update(feature, feature.getSource());
1321
    }
1322

    
1323
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1324
        throws DataException {
1325
        try {
1326
            checkInEditingMode();
1327
            checkIsOwnFeature(feature);
1328
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1329
            newVersionOfUpdate();
1330
            if ((lastChangedFeature == null)
1331
                || (lastChangedFeature.getSource() != feature.getSource())) {
1332
                lastChangedFeature = feature;
1333
                feature.validate(Feature.UPDATE);
1334
                lastChangedFeature = null;
1335
            }
1336

    
1337
            //Update the featureManager and the spatialManager
1338
            Feature newf = feature.getNotEditableCopy();
1339
            featureManager.update(newf, oldFeature);
1340
            spatialManager.updateFeature(newf, oldFeature);
1341

    
1342
            hasStrongChanges = true;
1343
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1344
        } catch (Exception e) {
1345
            throw new StoreUpdateFeatureException(e, this.getName());
1346
        }
1347
    }
1348

    
1349
    @Override
1350
    synchronized public void redo() throws RedoException {
1351
        Command redo = commands.getNextRedoCommand();
1352
        try {
1353
            checkInEditingMode();
1354
        } catch (NeedEditingModeException ex) {
1355
            throw new RedoException(redo, ex);
1356
        }
1357
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1358
        newVersionOfUpdate();
1359
        commands.redo();
1360
        hasStrongChanges = true;
1361
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1362
    }
1363

    
1364
    @Override
1365
    synchronized public void undo() throws UndoException {
1366
        Command undo = commands.getNextUndoCommand();
1367
        try {
1368
            checkInEditingMode();
1369
        } catch (NeedEditingModeException ex) {
1370
            throw new UndoException(undo, ex);
1371
        }
1372
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1373
        newVersionOfUpdate();
1374
        commands.undo();
1375
        hasStrongChanges = true;
1376
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1377
    }
1378

    
1379
    @Override
1380
    public List getRedoInfos() {
1381
        if (isEditing() && (commands != null)) {
1382
            return commands.getRedoInfos();
1383
        } else {
1384
            return null;
1385
        }
1386
    }
1387

    
1388
    @Override
1389
    public List getUndoInfos() {
1390
        if (isEditing() && (commands != null)) {
1391
            return commands.getUndoInfos();
1392
        } else {
1393
            return null;
1394
        }
1395
    }
1396

    
1397
    public synchronized FeatureCommandsStack getCommandsStack()
1398
        throws DataException {
1399
        checkInEditingMode();
1400
        return commands;
1401
    }
1402

    
1403
    @Override
1404
    synchronized public void cancelEditing() throws DataException {
1405
        if( spatialManager!=null ) {
1406
            spatialManager.cancelModifies();
1407
        }
1408
        try {
1409
            switch (mode) {
1410
            case MODE_QUERY:
1411
                throw new NeedEditingModeException(this.getName());
1412

    
1413
            case MODE_APPEND:
1414
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1415
                provider.abortAppend();
1416
                exitEditingMode();
1417
                ((FeatureSelection) this.getSelection()).deselectAll();
1418
                updateIndexes();
1419
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1420

    
1421
            case MODE_FULLEDIT:
1422
                boolean clearSelection = this.hasStrongChanges;
1423
                if (this.selection instanceof FeatureReferenceSelection) {
1424
                    clearSelection = this.hasInserts;
1425
                }
1426
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1427
                exitEditingMode();
1428
                if (clearSelection) {
1429
                    ((FeatureSelection) this.getSelection()).deselectAll();
1430
                }
1431
                updateIndexes();
1432
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1433
            }
1434
        } catch (Exception e) {
1435
            throw new StoreCancelEditingException(e, this.getName());
1436
        }
1437
    }
1438

    
1439
    @Override
1440
    synchronized public void finishEditing() throws DataException {
1441
        LOG.debug("finish editing of mode: {}", mode);
1442
        try {
1443

    
1444
            /*
1445
             * Selection needs to be cleared when editing stops
1446
             * to prevent conflicts with selection remaining from
1447
             * editing mode.
1448
             */
1449
//            ((FeatureSelection) this.getSelection()).deselectAll();
1450
            Map<String,List<FeatureAttributeDescriptor>> computedFields = this.getComputedFields();
1451
            switch (mode) {
1452
            case MODE_QUERY:
1453
                throw new NeedEditingModeException(this.getName());
1454

    
1455
            case MODE_APPEND:
1456
                if( selection!=null ) {
1457
                    selection = null;
1458
                }
1459
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1460
                provider.endAppend();
1461
                exitEditingMode();
1462
                this.updateComputedFields(computedFields);
1463
                saveDALFile();
1464
                updateIndexes();
1465
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1466
                break;
1467

    
1468
            case MODE_FULLEDIT:
1469
                if (hasStrongChanges && !this.allowWrite()) {
1470
                    throw new WriteNotAllowedException(getName());
1471
                }
1472
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1473
                    selection = null;
1474
                }
1475
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1476
                if (hasStrongChanges) {
1477
                    validateFeatures(Feature.FINISH_EDITING);
1478

    
1479
                    /*
1480
                     * This will throw a PerformEditingExceptionif the provider
1481
                     * does not accept the changes (for example, an invalid field name)
1482
                     */
1483
                    provider.performChanges(featureManager.getDeleted(),
1484
                        featureManager.getInserted(),
1485
                        featureManager.getUpdated(),
1486
                        removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1487
                    
1488
                }  
1489
                exitEditingMode();
1490
                this.updateComputedFields(computedFields);
1491
                saveDALFile();
1492
                updateIndexes();
1493
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1494
                break;
1495
            }
1496
        } catch (PerformEditingException pee) {
1497
            throw new WriteException(provider.getSourceId().toString(), pee);
1498
        } catch (Exception e) {
1499
            throw new FinishEditingException(e);
1500
        }
1501
    }
1502
    private Map<String,List<FeatureAttributeDescriptor>> getComputedFields() throws DataException {
1503
        Map<String,List<FeatureAttributeDescriptor>> r = new HashMap<>();
1504
        
1505
        List<FeatureType> theTypes = new ArrayList<>();
1506
        theTypes.addAll(this.getFeatureTypes());
1507
        theTypes.add(this.getDefaultFeatureType());
1508
        for( int n=0; n<theTypes.size(); n++ ) {
1509
            FeatureType type = theTypes.get(n);
1510
                for (FeatureAttributeDescriptor attrdesc : type) {
1511
                    FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
1512
                    if( emulator!= null) {
1513
                        List<FeatureAttributeDescriptor> l = r.get(type.getId());
1514
                        if (l==null) {
1515
                            l = new ArrayList<>();
1516
                            r.put(type.getId(), l);
1517
                        }
1518
                        l.add(attrdesc);
1519
                    }
1520
            }
1521
        }
1522
        return r;
1523
    }
1524
    private void updateComputedFields(Map<String,List<FeatureAttributeDescriptor>> computedFields) throws DataException {
1525

    
1526
        List<FeatureType> theTypes = new ArrayList<>();
1527
        theTypes.addAll(this.getFeatureTypes());
1528
        theTypes.add(this.getDefaultFeatureType());
1529
        for( int n=0; n<theTypes.size(); n++ ) {
1530
            DefaultFeatureType type = (DefaultFeatureType) theTypes.get(n);
1531
            List<FeatureAttributeDescriptor> x = computedFields.get(type.getId());
1532
            if(x!=null && !x.isEmpty()) {
1533
                for (FeatureAttributeDescriptor attrdesc : x) {
1534
                    if (type.get(attrdesc.getName())==null) {
1535
                        type.add(attrdesc);
1536
                    }
1537
                }
1538
            }
1539
        }
1540
        
1541
    }
1542
    private List<FeatureStoreProvider.FeatureTypeChanged> removeCalculatedAttributes(List<FeatureStoreProvider.FeatureTypeChanged> ftypes) {
1543
        // FIXME: Falta por implementar
1544
//        for (FeatureStoreProvider.FeatureTypeChanged ftype : ftypes) {
1545
//            EditableFeatureType target = (EditableFeatureType) ftype.getTarget();
1546
//            for (FeatureAttributeDescriptor attributeDescriptor : ftype.getSource().getAttributeDescriptors()) {
1547
//                if (attributeDescriptor.isComputed()) {
1548
//                    target.remove(attributeDescriptor.getName());
1549
//                }
1550
//            }
1551
//        }
1552
        return ftypes;
1553
    }
1554
    
1555

    
1556
    @SuppressWarnings("UseSpecificCatch")
1557
    private void saveDALFile() {       
1558
        try {
1559
            DataServerExplorer explorer = this.getExplorer();
1560
            if( explorer == null ) {
1561
                return;
1562
            }
1563
            DataResource resource = explorer.getResource(this, "dal");
1564
            if( resource == null ) {
1565
                return;
1566
            }
1567
            DALFile dalFile = DALFile.getDALFile();
1568
            dalFile.setStore(this);
1569
            if( !dalFile.isEmpty() ) {
1570
                dalFile.write(resource);
1571
            }
1572
        } catch (Exception ex) {
1573
            LOG.warn("Can't save DAL File", ex);
1574
        }
1575
    }
1576
    
1577
    @SuppressWarnings("UseSpecificCatch")
1578
    private void loadDALFile() {
1579
        try {
1580
            DataServerExplorer explorer = this.getExplorer();
1581
            if( explorer == null ) {
1582
                return;
1583
            }
1584
            DataResource resource = explorer.getResource(this, "dal");
1585
            if( resource == null || !resource.exists() ) {
1586
                return;
1587
            }
1588
            DALFile dalFile = DALFile.getDALFile(resource);
1589
            if( !dalFile.isEmpty() ) {
1590
                dalFile.updateStore(this);
1591
            }
1592
        } catch (Exception ex) {
1593
            LOG.warn("Can't load DAL File", ex);
1594
        }
1595
    }
1596
    
1597
    /**
1598
     * Save changes in the provider without leaving the edit mode.
1599
     * Do not call observers to communicate a change of ediding mode.
1600
     * The operation's history is eliminated to prevent inconsistencies
1601
     * in the data.
1602
     *
1603
     * @throws DataException
1604
     */
1605
    @Override
1606
    synchronized public void commitChanges() throws DataException {
1607
      LOG.debug("commitChanges of mode: {}", mode);
1608
      if( !canCommitChanges() ) {
1609
              throw new WriteNotAllowedException(getName());
1610
      }
1611
      try {
1612
        switch (mode) {
1613
        case MODE_QUERY:
1614
          throw new NeedEditingModeException(this.getName());
1615

    
1616
        case MODE_APPEND:
1617
          this.provider.endAppend();
1618
          exitEditingMode();
1619
          invalidateIndexes();
1620
          this.provider.beginAppend();
1621
          hasInserts = false;
1622
          break;
1623

    
1624
        case MODE_FULLEDIT:
1625
          if (hasStrongChanges && !this.allowWrite()) {
1626
            throw new WriteNotAllowedException(getName());
1627
          }
1628
          if (hasStrongChanges) {
1629
            validateFeatures(Feature.FINISH_EDITING);
1630
            provider.performChanges(featureManager.getDeleted(),
1631
              featureManager.getInserted(),
1632
              featureManager.getUpdated(),
1633
              removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1634
          }
1635
          invalidateIndexes();
1636
          featureManager = new FeatureManager();
1637
          featureTypeManager = new FeatureTypeManager(this);
1638
          spatialManager = new SpatialManager(this, provider.getEnvelope());
1639

    
1640
          commands =
1641
            new DefaultFeatureCommandsStack(this, featureManager,
1642
              spatialManager, featureTypeManager);
1643
          featureCount = null;
1644
          hasStrongChanges = false;
1645
          hasInserts = false;
1646
          break;
1647
        }
1648
      } catch (Exception e) {
1649
        throw new FinishEditingException(e);
1650
      }
1651
    }
1652

    
1653
    @Override
1654
    synchronized public boolean canCommitChanges() throws DataException {
1655
        if ( !this.allowWrite()) {
1656
                return false;
1657
        }
1658
            switch (mode) {
1659
            default:
1660
        case MODE_QUERY:
1661
                return false;
1662

    
1663
        case MODE_APPEND:
1664
                return true;
1665

    
1666
        case MODE_FULLEDIT:
1667
            List types = this.getFeatureTypes();
1668
            for( int i=0; i<types.size(); i++ ) {
1669
                    Object type = types.get(i);
1670
                    if( type instanceof DefaultEditableFeatureType ) {
1671
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1672
                                    return false;
1673
                            }
1674
                    }
1675
            }
1676
            return true;
1677
            }
1678
    }
1679

    
1680
    @Override
1681
    public void beginEditingGroup(String description)
1682
        throws NeedEditingModeException {
1683
        checkInEditingMode();
1684
        commands.startComplex(description);
1685
    }
1686

    
1687
    @Override
1688
    public void endEditingGroup() throws NeedEditingModeException {
1689
        checkInEditingMode();
1690
        commands.endComplex();
1691
    }
1692

    
1693
    @Override
1694
    public boolean isAppendModeSupported() {
1695
        return this.provider.supportsAppendMode();
1696
    }
1697

    
1698
    @Override
1699
    public void export(DataServerExplorer explorer, String provider,
1700
        NewFeatureStoreParameters params) throws DataException {
1701

    
1702
        if (this.getFeatureTypes().size() != 1) {
1703
            throw new NotYetImplemented(
1704
                "export whith more than one type not yet implemented");
1705
        }
1706
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1707
        FeatureStore target = null;
1708
        FeatureSet features = null;
1709
        DisposableIterator iterator = null;
1710
        try {
1711
            FeatureType type = this.getDefaultFeatureType();
1712
            if ((params.getDefaultFeatureType() == null)
1713
                || (params.getDefaultFeatureType().size() == 0)) {
1714
                params.setDefaultFeatureType(type.getEditable());
1715

    
1716
            }
1717
            explorer.add(provider, params, true);
1718

    
1719
            DataManager manager = DALLocator.getDataManager();
1720
            target = (FeatureStore) manager.openStore(provider, params);
1721
            FeatureType targetType = target.getDefaultFeatureType();
1722

    
1723
            target.edit(MODE_APPEND);
1724
            FeatureAttributeDescriptor[] pkattrs = type.getPrimaryKey();
1725
            if (featureSelection.getSize() > 0) {
1726
                features = this.getFeatureSelection();
1727
            } else {
1728
                if ((pkattrs != null) && (pkattrs.length > 0)) {
1729
                    FeatureQuery query = createFeatureQuery();
1730
                    for (FeatureAttributeDescriptor pkattr : pkattrs) {
1731
                        query.getOrder().add(pkattr.getName(), true);
1732
                    }
1733
                    features = this.getFeatureSet(query);
1734
                } else {
1735
                    features = this.getFeatureSet();
1736
                }
1737
            }
1738
            iterator = features.fastIterator();
1739
            while (iterator.hasNext()) {
1740
                DefaultFeature feature = (DefaultFeature) iterator.next();
1741
                target.insert(target.createNewFeature(targetType, feature));
1742
            }
1743
            target.finishEditing();
1744
            target.dispose();
1745
        } catch (Exception e) {
1746
            throw new DataExportException(e, params.toString());
1747
        } finally {
1748
            dispose(iterator);
1749
            dispose(features);
1750
            dispose(target);
1751
        }
1752
    }
1753

    
1754
    //
1755
    // ====================================================================
1756
    // Obtencion de datos
1757
    // getDataCollection, getFeatureCollection
1758
    //
1759

    
1760
    @Override
1761
    public DataSet getDataSet() throws DataException {
1762
        checkNotInAppendMode();
1763
        FeatureQuery query =
1764
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1765
        return new DefaultFeatureSet(this, query);
1766
    }
1767

    
1768
    @Override
1769
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1770
        checkNotInAppendMode();
1771
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1772
    }
1773

    
1774
    @Override
1775
    public void getDataSet(Observer observer) throws DataException {
1776
        checkNotInAppendMode();
1777
        this.getFeatureSet(null, observer);
1778
    }
1779

    
1780
    @Override
1781
    public void getDataSet(DataQuery dataQuery, Observer observer)
1782
        throws DataException {
1783
        checkNotInAppendMode();
1784
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1785
    }
1786

    
1787
    @Override
1788
    public FeatureSet getFeatureSet() throws DataException {
1789
        return this.getFeatureSet((FeatureQuery)null);
1790
    }
1791

    
1792
    @Override
1793
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1794
        throws DataException {
1795
        checkNotInAppendMode();
1796
        if( featureQuery==null ) {
1797
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1798
        }
1799
        return new DefaultFeatureSet(this, featureQuery);
1800
    }
1801

    
1802
    @Override
1803
    public FeatureSet getFeatureSet(String filter) throws DataException {
1804
        return this.getFeatureSet(filter, null, true);
1805
    }
1806

    
1807
    @Override
1808
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1809
        return this.getFeatureSet(filter, sortBy, true);
1810
    }
1811

    
1812
    @Override
1813
    public FeatureSet getFeatureSet(Expression filter) throws DataException {
1814
        return this.getFeatureSet(filter, null, true);
1815
    }
1816
    
1817
    @Override
1818
    public FeatureSet getFeatureSet(Expression filter, String sortBy) throws DataException {
1819
        return this.getFeatureSet(filter, sortBy, true);
1820
    }
1821
    
1822
    @Override
1823
    public FeatureSet getFeatureSet(Expression filter, String sortBy, boolean asc) throws DataException {
1824
        FeatureQuery query = this.createFeatureQuery();
1825
        if( filter!=null ) {
1826
            query.setFilter(filter);
1827
        }
1828
        if( !StringUtils.isEmpty(sortBy) ) {
1829
            query.getOrder().add(sortBy, asc);
1830
        }
1831
        query.retrievesAllAttributes();
1832
        return this.getFeatureSet(query);
1833
    }
1834
    
1835
    @Override
1836
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1837
        FeatureQuery query = null;
1838
        if( !StringUtils.isEmpty(filter) ) {
1839
            query = this.createFeatureQuery();
1840
            query.setFilter(filter);
1841
        }
1842
        if( !StringUtils.isEmpty(sortBy) ) {
1843
            if( query == null ) {
1844
                query = this.createFeatureQuery();
1845
            }
1846
            query.getOrder().add(sortBy, asc);
1847
        }
1848
        if( query == null ) {
1849
            return this.getFeatureSet();
1850
        }
1851
        return this.getFeatureSet(query);
1852
    }
1853
    
1854
    @Override
1855
    public List<Feature> getFeatures(String filter)  {
1856
        return this.getFeatures(filter, null, true);
1857
    }
1858

    
1859
    @Override
1860
    public List<Feature> getFeatures(String filter, String sortBy)  {
1861
        return this.getFeatures(filter, sortBy, true);
1862
    }
1863

    
1864
    @Override
1865
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1866
        FeatureQuery query = this.createFeatureQuery();
1867
        if( !StringUtils.isEmpty(filter) ) {
1868
            query.setFilter(filter);
1869
        }
1870
        if( !StringUtils.isEmpty(sortBy) ) {
1871
            query.getOrder().add(sortBy, asc);
1872
        }
1873
        return this.getFeatures(query, 100);
1874
    }
1875
    
1876
    @Override
1877
    public List<Feature> getFeatures(Expression filter)  {
1878
        return this.getFeatures(filter, null, true);
1879
    }
1880

    
1881
    @Override
1882
    public List<Feature> getFeatures(Expression filter, String sortBy)  {
1883
        return this.getFeatures(filter, sortBy, true);
1884
    }
1885

    
1886
    @Override
1887
    public List<Feature> getFeatures(Expression filter, String sortBy, boolean asc)  {
1888
        FeatureQuery query = this.createFeatureQuery();
1889
        if( filter!=null ) {
1890
            query.setFilter(filter);
1891
        }
1892
        if( !StringUtils.isEmpty(sortBy) ) {
1893
            query.getOrder().add(sortBy, asc);
1894
        }
1895
        return this.getFeatures(query, 100);
1896
    }
1897
    
1898
    @Override
1899
    public List<Feature> getFeatures(FeatureQuery query)  {
1900
        return this.getFeatures(query, 100);
1901
    }
1902
    
1903
    @Override
1904
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1905
        try {
1906
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1907
            return pager.asList();
1908
        } catch (BaseException ex) {
1909
            throw new RuntimeException("Can't create the list of features.", ex);
1910
        }
1911
    }
1912

    
1913
    @Override
1914
    public List<Feature> getFeatures() {
1915
        return this.getFeatures(null, 500);
1916
    }
1917

    
1918
    @Override
1919
    public Feature first() throws DataException {
1920
        return this.findFirst((String)null, null, true);
1921
    }
1922
    
1923
    @Override
1924
    public Feature findFirst(String filter) throws DataException {
1925
        return this.findFirst(filter, null, true);
1926
    }
1927

    
1928
    @Override
1929
    public Feature findFirst(String filter, String sortBy) throws DataException {
1930
        return this.findFirst(filter, sortBy, true);
1931
    }
1932

    
1933
    @Override
1934
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1935
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1936
        if( set==null || set.isEmpty() ) {
1937
            return null;
1938
        }
1939
        DisposableIterator it = set.iterator();
1940
        Feature f = (Feature) it.next();
1941
        it.dispose();
1942
        return f;
1943
    }
1944
    
1945
    @Override
1946
    public Feature findFirst(Expression filter) throws DataException {
1947
        return this.findFirst(filter, null, true);
1948
    }
1949

    
1950
    @Override
1951
    public Feature findFirst(Expression filter, String sortBy) throws DataException {
1952
        return this.findFirst(filter, sortBy, true);
1953
    }
1954

    
1955
    @Override
1956
    public Feature findFirst(Expression filter, String sortBy, boolean asc) throws DataException {
1957
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1958
        if( set==null || set.isEmpty() ) {
1959
            return null;
1960
        }
1961
        DisposableIterator it = set.iterator();
1962
        Feature f = (Feature) it.next();
1963
        it.dispose();
1964
        return f;
1965
    }
1966
    
1967
    @Override
1968
    public void accept(Visitor visitor) throws BaseException {
1969
        FeatureSet set = getFeatureSet();
1970
        try {
1971
            set.accept(visitor);
1972
        } finally {
1973
            set.dispose();
1974
        }
1975
    }
1976

    
1977
    @Override
1978
    public void accept(Visitor visitor, DataQuery dataQuery)
1979
        throws BaseException {
1980
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1981
        try {
1982
            set.accept(visitor);
1983
        } finally {
1984
            set.dispose();
1985
        }
1986
    }
1987

    
1988
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1989
        throws DataException {
1990
        DefaultFeatureType fType =
1991
            (DefaultFeatureType) this.getFeatureType(featureQuery
1992
                .getFeatureTypeId());
1993
        if( featureQuery.hasAttributeNames() || 
1994
            featureQuery.hasConstantsAttributeNames() ||
1995
            fType.hasRequiredFields()    
1996
            ) {
1997
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1998
        }
1999
        return fType;
2000
    }
2001

    
2002
    @Override
2003
    public void getFeatureSet(Observer observer) throws DataException {
2004
        checkNotInAppendMode();
2005
        this.getFeatureSet(null, observer);
2006
    }
2007

    
2008
    @Override
2009
    public void getFeatureSet(FeatureQuery query, Observer observer)
2010
        throws DataException {
2011
        class LoadInBackGround implements Runnable {
2012

    
2013
            private final FeatureStore store;
2014
            private final FeatureQuery query;
2015
            private final Observer observer;
2016

    
2017
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
2018
                Observer observer) {
2019
                this.store = store;
2020
                this.query = query;
2021
                this.observer = observer;
2022
            }
2023

    
2024
            void notify(FeatureStoreNotification theNotification) {
2025
                observer.update(store, theNotification);
2026
            }
2027

    
2028
            @Override
2029
            public void run() {
2030
                FeatureSet set = null;
2031
                try {
2032
                    set = store.getFeatureSet(query);
2033
                    notify(new DefaultFeatureStoreNotification(store,
2034
                        FeatureStoreNotification.LOAD_FINISHED, set));
2035
                } catch (Exception e) {
2036
                    notify(new DefaultFeatureStoreNotification(store,
2037
                        FeatureStoreNotification.LOAD_FINISHED, e));
2038
                } finally {
2039
                    dispose(set);
2040
                }
2041
            }
2042
        }
2043

    
2044
        checkNotInAppendMode();
2045
        if (query == null) {
2046
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
2047
        }
2048
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
2049
        Thread thread = new Thread(task, "Load Feature Set in background");
2050
        thread.start();
2051
    }
2052

    
2053
    @Override
2054
    public Feature getFeatureByReference(FeatureReference reference)
2055
        throws DataException {
2056
        checkNotInAppendMode();
2057
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
2058
        FeatureType featureType;
2059
        if (ref.getFeatureTypeId() == null) {
2060
            featureType = this.getDefaultFeatureType();
2061
        } else {
2062
            featureType = this.getFeatureType(ref.getFeatureTypeId());
2063
        }
2064
        return this.getFeatureByReference(reference, featureType);
2065
    }
2066

    
2067
    @Override
2068
    public Feature getFeatureByReference(FeatureReference reference,
2069
        FeatureType featureType) throws DataException {
2070
        checkNotInAppendMode();
2071
        featureType = fixFeatureType((DefaultFeatureType) featureType);
2072
        if (this.mode == MODE_FULLEDIT) {
2073
            Feature f = featureManager.get(reference, this, featureType);
2074
            if (f != null) {
2075
                return f;
2076
            }
2077
        }
2078

    
2079
        FeatureType sourceFeatureType = featureType;
2080
        if (!this.transforms.isEmpty()) {
2081
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
2082
        }
2083
        // TODO comprobar que el id es de este store
2084

    
2085
        DefaultFeature feature =
2086
            new DefaultFeature(this,
2087
                this.provider.getFeatureProviderByReference(
2088
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
2089

    
2090
        if (!this.transforms.isEmpty()) {
2091
            return this.transforms.applyTransform(feature, featureType);
2092
        }
2093
        return feature;
2094
    }
2095

    
2096
    //
2097
    // ====================================================================
2098
    // Gestion de features
2099
    //
2100

    
2101
    private FeatureType fixFeatureType(DefaultFeatureType type)
2102
        throws DataException {
2103
        FeatureType original = this.getDefaultFeatureType();
2104

    
2105
        if ((type == null) || type.equals(original)) {
2106
            return original;
2107
        } else {
2108
            if (!type.isSubtypeOf(original)) {
2109
                Iterator iter = this.getFeatureTypes().iterator();
2110
                FeatureType tmpType;
2111
                boolean found = false;
2112
                while (iter.hasNext()) {
2113
                    tmpType = (FeatureType) iter.next();
2114
                    if (type.equals(tmpType)) {
2115
                        return type;
2116

    
2117
                    } else
2118
                        if (type.isSubtypeOf(tmpType)) {
2119
                            found = true;
2120
                            original = tmpType;
2121
                            break;
2122
                        }
2123

    
2124
                }
2125
                if (!found) {
2126
                    throw new IllegalFeatureTypeException(getName());
2127
                }
2128
            }
2129
        }
2130

    
2131
        // Checks that type has all fields of pk
2132
        // else add the missing attributes at the end.
2133
        if (!original.hasOID()) {
2134
            // Gets original pk attributes
2135
            DefaultEditableFeatureType edOriginal =
2136
                (DefaultEditableFeatureType) original.getEditable();
2137
            FeatureAttributeDescriptor orgAttr;
2138
            Iterator edOriginalIter = edOriginal.iterator();
2139
            while (edOriginalIter.hasNext()) {
2140
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2141
                if (!orgAttr.isPrimaryKey()) {
2142
                    edOriginalIter.remove();
2143
                }
2144
            }
2145

    
2146
            // Checks if all pk attributes are in type
2147
            Iterator typeIterator;
2148
            edOriginalIter = edOriginal.iterator();
2149
            FeatureAttributeDescriptor attr;
2150
            while (edOriginalIter.hasNext()) {
2151
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2152
                typeIterator = type.iterator();
2153
                while (typeIterator.hasNext()) {
2154
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
2155
                    if (attr.getName().equals(orgAttr.getName())) {
2156
                        edOriginalIter.remove();
2157
                        break;
2158
                    }
2159
                }
2160
            }
2161

    
2162
            // add missing pk attributes if any
2163
            if (edOriginal.size() > 0) {
2164
                boolean isEditable = type instanceof DefaultEditableFeatureType;
2165
                DefaultEditableFeatureType edType =
2166
                    (DefaultEditableFeatureType) original.getEditable();
2167
                edType.clear();
2168
                edType.addAll(type);
2169
                edType.addAll(edOriginal);
2170
                if (!isEditable) {
2171
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
2172
                }
2173
            }
2174

    
2175
        }
2176

    
2177
        return type;
2178
    }
2179

    
2180
    @Override
2181
    public void validateFeatures(int mode) throws DataException {
2182
        FeatureSet collection = null;
2183
        DisposableIterator iter = null;
2184
        try {
2185
            FeatureRules rules = this.getDefaultFeatureType().getRules();
2186
            if( rules==null || rules.isEmpty() ) {
2187
                return;
2188
            }
2189
            checkNotInAppendMode();
2190
            collection = this.getFeatureSet();
2191
            iter = collection.fastIterator();
2192
            long previousVersionOfUpdate = currentVersionOfUpdate();
2193
            while (iter.hasNext()) {
2194
                ((DefaultFeature) iter.next()).validate(mode);
2195
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
2196
                    throw new ConcurrentDataModificationException(getName());
2197
                }
2198
            }
2199
        } catch (Exception e) {
2200
            throw new ValidateFeaturesException(e, getName());
2201
        } finally {
2202
            DisposeUtils.disposeQuietly(iter);
2203
            DisposeUtils.disposeQuietly(collection);
2204
        }
2205
    }
2206

    
2207
    @Override
2208
    public FeatureType getDefaultFeatureType() throws DataException {
2209
        try {
2210

    
2211
            if (isEditing()) {
2212
                FeatureType auxFeatureType =
2213
                    featureTypeManager.getType(defaultFeatureType.getId());
2214
                if (auxFeatureType != null) {
2215
                    return avoidEditable(auxFeatureType);
2216
                }
2217
            }
2218
            FeatureType type = this.transforms.getDefaultFeatureType();
2219
                if (type != null) {
2220
                return avoidEditable(type);
2221
                }
2222

    
2223
            return avoidEditable(defaultFeatureType);
2224

    
2225
        } catch (Exception e) {
2226
            throw new GetFeatureTypeException(e, getName());
2227
        }
2228
    }
2229

    
2230
    private FeatureType avoidEditable(FeatureType ft) {
2231
        if (ft instanceof EditableFeatureType) {
2232
            return ((EditableFeatureType) ft).getNotEditableCopy();
2233
        } else {
2234
            return ft;
2235
        }
2236
    }
2237

    
2238
    @Override
2239
    public FeatureType getFeatureType(String featureTypeId)
2240
        throws DataException {
2241
        if (featureTypeId == null) {
2242
            return this.getDefaultFeatureType();
2243
        }
2244
        try {
2245
            if (isEditing()) {
2246
                FeatureType auxFeatureType =
2247
                    featureTypeManager.getType(featureTypeId);
2248
                if (auxFeatureType != null) {
2249
                    return auxFeatureType;
2250
                }
2251
            }
2252
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2253
            if (type != null) {
2254
                return type;
2255
            }
2256
            Iterator iter = this.featureTypes.iterator();
2257
            while (iter.hasNext()) {
2258
                type = (FeatureType) iter.next();
2259
                if (type.getId().equals(featureTypeId)) {
2260
                    return type;
2261
                }
2262
            }
2263
            return null;
2264
        } catch (Exception e) {
2265
            throw new GetFeatureTypeException(e, getName());
2266
        }
2267
    }
2268

    
2269
    public FeatureType getProviderDefaultFeatureType() {
2270
        return defaultFeatureType;
2271
    }
2272

    
2273
    @Override
2274
    public List getFeatureTypes() throws DataException {
2275
        try {
2276
            List types;
2277
            if (isEditing()) {
2278
                types = new ArrayList();
2279
                Iterator it = featureTypes.iterator();
2280
                while (it.hasNext()) {
2281
                    FeatureType type = (FeatureType) it.next();
2282
                    FeatureType typeaux =
2283
                        featureTypeManager.getType(type.getId());
2284
                    if (typeaux != null) {
2285
                        types.add(typeaux);
2286
                    } else {
2287
                        types.add(type);
2288
                    }
2289
                }
2290
                it = featureTypeManager.newsIterator();
2291
                while (it.hasNext()) {
2292
                    FeatureType type = (FeatureType) it.next();
2293
                    types.add(type);
2294
                }
2295
            } else {
2296
                types = this.transforms.getFeatureTypes();
2297
                if (types == null) {
2298
                    types = featureTypes;
2299
                }
2300
            }
2301
            return Collections.unmodifiableList(types);
2302
        } catch (Exception e) {
2303
            throw new GetFeatureTypeException(e, getName());
2304
        }
2305
    }
2306

    
2307
    public List getProviderFeatureTypes() throws DataException {
2308
        return Collections.unmodifiableList(this.featureTypes);
2309
    }
2310

    
2311
    @Override
2312
    public Feature createFeature(FeatureProvider data) throws DataException {
2313
        DefaultFeature feature = new DefaultFeature(this, data);
2314
        return feature;
2315
    }
2316

    
2317
    public Feature createFeature(FeatureProvider data, FeatureType type)
2318
        throws DataException {
2319
        // FIXME: falta por implementar
2320
        // Comprobar si es un subtipo del feature de data
2321
        // y construir un feature usando el subtipo.
2322
        // Probablemente requiera generar una copia del data.
2323
        throw new NotYetImplemented();
2324
    }
2325

    
2326
    @Override
2327
    public EditableFeature createNewFeature(FeatureType type,
2328
        Feature defaultValues) throws DataException {
2329
        try {
2330
            FeatureProvider data = createNewFeatureProvider(type);
2331
            DefaultEditableFeature feature =
2332
                new DefaultEditableFeature(this, data);
2333
            feature.initializeValues(defaultValues);
2334
            data.setNew(true);
2335

    
2336
            return feature;
2337
        } catch (Exception e) {
2338
            throw new CreateFeatureException(e, getName());
2339
        }
2340
    }
2341

    
2342
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2343
        throws DataException {
2344
        type = this.fixFeatureType((DefaultFeatureType) type);
2345
        FeatureProvider data = this.provider.createFeatureProvider(type);
2346
        data.setNew(true);
2347
        if (type.hasOID() && (data.getOID() == null)) {
2348
            data.setOID(this.provider.createNewOID());
2349
        } else {
2350
            data.setOID(this.getTemporalOID());
2351
        }
2352
        return data;
2353

    
2354
    }
2355

    
2356
    @Override
2357
    public EditableFeature createNewFeature(FeatureType type,
2358
        boolean defaultValues) throws DataException {
2359
        try {
2360
            FeatureProvider data = createNewFeatureProvider(type);
2361
            DefaultEditableFeature feature =
2362
                new DefaultEditableFeature(this, data);
2363
            if (defaultValues) {
2364
                feature.initializeValues();
2365
            }
2366
            return feature;
2367
        } catch (Exception e) {
2368
            throw new CreateFeatureException(e, getName());
2369
        }
2370
    }
2371

    
2372
    @Override
2373
    public EditableFeature createNewFeature(boolean defaultValues)
2374
        throws DataException {
2375
        return this.createNewFeature(this.getDefaultFeatureType(),
2376
            defaultValues);
2377
    }
2378

    
2379
    @Override
2380
    public EditableFeature createNewFeature() throws DataException {
2381
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2382
    }
2383

    
2384
    @Override
2385
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2386
        FeatureType ft = this.getDefaultFeatureType();
2387
        EditableFeature f = this.createNewFeature(ft, false);
2388
                for( FeatureAttributeDescriptor desc : ft ) {
2389
                        try {
2390
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2391
                        } catch(Throwable th) {
2392
                                // Ignore
2393
                        }
2394
                }
2395
        return f;
2396
    }
2397

    
2398
    @Override
2399
    public EditableFeatureType createFeatureType() {
2400
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2401
        return ftype;
2402
    }
2403

    
2404
    @Override
2405
    public EditableFeatureType createFeatureType(String id) {
2406
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2407
        return ftype;
2408
    }
2409

    
2410
    //
2411
    // ====================================================================
2412
    // Index related methods
2413
    //
2414

    
2415
    @Override
2416
    public FeatureIndexes getIndexes() {
2417
        return this.indexes;
2418
    }
2419

    
2420
    @Override
2421
    public FeatureIndex createIndex(FeatureType featureType,
2422
        String attributeName, String indexName) throws DataException {
2423
        return createIndex(null, featureType, attributeName, indexName);
2424
    }
2425

    
2426
    @Override
2427
    public FeatureIndex createIndex(String indexTypeName,
2428
        FeatureType featureType, String attributeName, String indexName)
2429
        throws DataException {
2430

    
2431
        return createIndex(indexTypeName, featureType, attributeName,
2432
            indexName, false, null);
2433
    }
2434

    
2435
    @Override
2436
    public FeatureIndex createIndex(FeatureType featureType,
2437
        String attributeName, String indexName, Observer observer)
2438
        throws DataException {
2439
        return createIndex(null, featureType, attributeName, indexName,
2440
            observer);
2441
    }
2442

    
2443
    @Override
2444
    public FeatureIndex createIndex(String indexTypeName,
2445
        FeatureType featureType, String attributeName, String indexName,
2446
        final Observer observer) throws DataException {
2447

    
2448
        return createIndex(indexTypeName, featureType, attributeName,
2449
            indexName, true, observer);
2450
    }
2451

    
2452
    private FeatureIndex createIndex(String indexTypeName,
2453
        FeatureType featureType, String attributeName, String indexName,
2454
        boolean background, final Observer observer) throws DataException {
2455

    
2456
        checkNotInAppendMode();
2457
        FeatureIndexProviderServices index;
2458
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2459
                featureType, indexName,
2460
                featureType.getAttributeDescriptor(attributeName));
2461

    
2462
        try {
2463
            index.fill(background, observer);
2464
        } catch (FeatureIndexException e) {
2465
            throw new InitializeException(index.getName(), e);
2466
        }
2467

    
2468
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2469
        return index;
2470
    }
2471

    
2472
    //
2473
    // ====================================================================
2474
    // Transforms related methods
2475
    //
2476

    
2477
    @Override
2478
    public FeatureStoreTransforms getTransforms() {
2479
        return this.transforms;
2480
    }
2481

    
2482
    @Override
2483
    public FeatureQuery createFeatureQuery() {
2484
        return new DefaultFeatureQuery();
2485
    }
2486

    
2487
    @Override
2488
    public DataQuery createQuery() {
2489
        return createFeatureQuery();
2490
    }
2491

    
2492
    //
2493
    // ====================================================================
2494
    // UndoRedo related methods
2495
    //
2496

    
2497
    @Override
2498
    public boolean canRedo() {
2499
        return commands.canRedo();
2500
    }
2501

    
2502
    @Override
2503
    public boolean canUndo() {
2504
        return commands.canUndo();
2505
    }
2506

    
2507
    @Override
2508
    public void redo(int num) throws RedoException {
2509
        for (int i = 0; i < num; i++) {
2510
            redo();
2511
        }
2512
    }
2513

    
2514
    @Override
2515
    public void undo(int num) throws UndoException {
2516
        for (int i = 0; i < num; i++) {
2517
            undo();
2518
        }
2519
    }
2520

    
2521
    //
2522
    // ====================================================================
2523
    // Metadata related methods
2524
    //
2525

    
2526
    @Override
2527
    public Object getMetadataID() {
2528
        return this.provider.getSourceId();
2529
    }
2530

    
2531
    @Override
2532
    public void delegate(DynObject dynObject) {
2533
        this.metadata.delegate(dynObject);
2534
    }
2535

    
2536
    @Override
2537
    public DynClass getDynClass() {
2538
        return this.metadata.getDynClass();
2539
    }
2540

    
2541
    @Override
2542
    public Object getDynValue(String name) throws DynFieldNotFoundException {
2543
        try {
2544
            if (this.transforms.hasDynValue(name)) {
2545
                return this.transforms.getDynValue(name);
2546
            }
2547
            if (this.metadata.hasDynValue(name)) {
2548
                return this.metadata.getDynValue(name);
2549
            }
2550
            if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2551
                return this.provider.getProviderName();
2552
            } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2553
                return this.provider.getSourceId();
2554
            } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2555
                try {
2556
                    return this.getDefaultFeatureType();
2557
                } catch (DataException e) {
2558
                    return null;
2559
                }
2560
            }
2561
            return this.metadata.getDynValue(name);
2562
        } catch(Exception ex ) {
2563
            LOG.debug("Can't retrieve the value of '"+name+"' in store '"+this.getName()+"'.",ex);
2564
            return null;
2565
        }
2566
    }
2567

    
2568
    @Override
2569
    public boolean hasDynValue(String name) {
2570
        if (this.transforms.hasDynValue(name)) {
2571
            return true;
2572
        }
2573
        return this.metadata.hasDynValue(name);
2574
    }
2575

    
2576
    @Override
2577
    public boolean hasDynMethod(String name) {
2578
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2579
    }
2580

    
2581
    @Override
2582
    public void implement(DynClass dynClass) {
2583
        this.metadata.implement(dynClass);
2584
    }
2585

    
2586
    @Override
2587
    public Object invokeDynMethod(String name, Object[] args)
2588
        throws DynMethodException {
2589
        return this.metadata.invokeDynMethod(this, name, args);
2590
    }
2591

    
2592
    @Override
2593
    public Object invokeDynMethod(int code, Object[] args)
2594
        throws DynMethodException {
2595
        return this.metadata.invokeDynMethod(this, code, args);
2596
    }
2597

    
2598
    @Override
2599
    public void setDynValue(String name, Object value)
2600
        throws DynFieldNotFoundException {
2601
                if( this.transforms.hasDynValue(name) ) {
2602
                        this.transforms.setDynValue(name, value);
2603
                        return;
2604
                }
2605
        this.metadata.setDynValue(name, value);
2606

    
2607
    }
2608

    
2609
    /*
2610
     * (non-Javadoc)
2611
     *
2612
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2613
     */
2614
    @Override
2615
    public Set getMetadataChildren() {
2616
        return this.metadataChildren;
2617
    }
2618

    
2619
    /*
2620
     * (non-Javadoc)
2621
     *
2622
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2623
     */
2624
    @Override
2625
    public String getMetadataName() {
2626
        return this.provider.getProviderName();
2627
    }
2628

    
2629
    public FeatureTypeManager getFeatureTypeManager() {
2630
        return this.featureTypeManager;
2631
    }
2632

    
2633
    @Override
2634
    public long getFeatureCount() throws DataException {
2635
        if (featureCount == null) {
2636
            featureCount = this.provider.getFeatureCount();
2637
        }
2638
        if (this.isEditing()) {
2639
            if(this.isAppending()) {
2640
                try{
2641
                    throw new IllegalStateException();
2642
                } catch(IllegalStateException e) {
2643
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND",e);
2644
                }
2645
                return -1;
2646
            } else {
2647
                return featureCount
2648
                    + this.featureManager.getDeltaSize();
2649
            }
2650
        }
2651
        return featureCount;
2652
    }
2653

    
2654
    private Long getTemporalOID() {
2655
        return this.temporalOid++;
2656
    }
2657

    
2658
    @Override
2659
    public FeatureType getProviderFeatureType(String featureTypeId) {
2660
        if (featureTypeId == null) {
2661
            return this.defaultFeatureType;
2662
        }
2663
        FeatureType type;
2664
        Iterator iter = this.featureTypes.iterator();
2665
        while (iter.hasNext()) {
2666
            type = (FeatureType) iter.next();
2667
            if (type.getId().equals(featureTypeId)) {
2668
                return type;
2669
            }
2670
        }
2671
        return null;
2672
    }
2673

    
2674
    @Override
2675
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2676
        return ((DefaultFeature) feature).getData();
2677
    }
2678

    
2679
    @Override
2680
    public DataStore getStore() {
2681
        return this;
2682
    }
2683

    
2684
    @Override
2685
    public FeatureStore getFeatureStore() {
2686
        return this;
2687
    }
2688

    
2689
    @Override
2690
    public void createCache(String name, DynObject parameters)
2691
        throws DataException {
2692
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2693
        if (cache == null) {
2694
            throw new CreateException("FeaureCacheProvider", null);
2695
        }
2696
        cache.apply(this, provider);
2697
        provider = cache;
2698

    
2699
        featureCount = null;
2700
    }
2701

    
2702
    @Override
2703
    public FeatureCache getCache() {
2704
        return cache;
2705
    }
2706

    
2707
    @Override
2708
    public void clear() {
2709
        if (metadata != null) {
2710
            metadata.clear();
2711
        }
2712
    }
2713

    
2714
    @Override
2715
    public String getName() {
2716
        if( this.provider != null ) {
2717
            return this.provider.getName();
2718
        }
2719
        if( this.parameters instanceof HasAFile ) {
2720
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2721
        }
2722
        return "unknow";
2723
    }
2724

    
2725
    @Override
2726
    public String getFullName() {
2727
        try {
2728
            if( this.provider!=null ) {
2729
                return this.provider.getFullName();
2730
            }
2731
            if( this.parameters instanceof HasAFile ) {
2732
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2733
            }
2734
            return null;
2735
        } catch(Throwable th) {
2736
            return null;
2737
        }
2738
    }
2739

    
2740
    @Override
2741
    public String getProviderName() {
2742
        if( this.provider!=null ) {
2743
            return this.provider.getProviderName();
2744
        }
2745
        if( this.parameters != null ) {
2746
            return this.parameters.getDataStoreName();
2747
        }
2748
        return null;
2749

    
2750
    }
2751

    
2752
    @Override
2753
    public boolean isKnownEnvelope() {
2754
        return this.provider.isKnownEnvelope();
2755
    }
2756

    
2757
    @Override
2758
    public boolean hasRetrievedFeaturesLimit() {
2759
        return this.provider.hasRetrievedFeaturesLimit();
2760
    }
2761

    
2762
    @Override
2763
    public int getRetrievedFeaturesLimit() {
2764
        return this.provider.getRetrievedFeaturesLimit();
2765
    }
2766

    
2767
    @Override
2768
    public Interval getInterval() {
2769
        if( this.timeSupport!=null ) {
2770
            return this.timeSupport.getInterval();
2771
        }
2772
        try {
2773
            FeatureType type = this.getDefaultFeatureType();
2774
            FeatureAttributeDescriptor attr = type.getDefaultTimeAttribute();
2775
            if( attr!=null ) {
2776
                Interval interval = attr.getInterval();
2777
                if( interval!=null ) {
2778
                    return interval;
2779
                }
2780
            }
2781
        } catch (DataException ex) {
2782
        }
2783
        return this.provider.getInterval();
2784
    }
2785

    
2786
    @Override
2787
    public Collection getTimes() {
2788
        if( this.timeSupport!=null ) {
2789
            return this.timeSupport.getTimes();
2790
        }
2791
        return this.provider.getTimes();
2792
    }
2793

    
2794
    @Override
2795
    public Collection getTimes(Interval interval) {
2796
        if( this.timeSupport!=null ) {
2797
            return this.timeSupport.getTimes(interval);
2798
        }
2799
        return this.provider.getTimes(interval);
2800
    }
2801

    
2802
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2803
        if( this.isEditing() ) {
2804
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2805
        }
2806
        if( !this.transforms.isEmpty() ) {
2807
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2808
        }
2809
        FeatureType ft = this.defaultFeatureType;
2810
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2811
        if( attr == null ) {
2812
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2813
        }
2814
        EditableFeatureType eft = ft.getEditable();
2815
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2816
        if( attr != null ) {
2817
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2818
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2819
            }
2820
            eft.remove(attr.getName());
2821
        }
2822
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2823
            timeSupport.getAttributeName(), 
2824
            timeSupport.getDataType()
2825
        );
2826
        attrTime.setIsTime(true);
2827
        attrTime.setFeatureAttributeEmulator(timeSupport);
2828
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2829
        this.defaultFeatureType = eft.getNotEditableCopy();
2830
        
2831
        this.timeSupport = timeSupport;
2832
    }
2833

    
2834
    @Override
2835
    @SuppressWarnings("CloneDoesntCallSuperClone")
2836
    public Object clone() throws CloneNotSupportedException {
2837

    
2838
        DataStoreParameters dsp = getParameters();
2839

    
2840
        DefaultFeatureStore cloned_store = null;
2841

    
2842
        try {
2843
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2844
                openStore(this.getProviderName(), dsp);
2845
            if (transforms != null) {
2846
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2847
                cloned_store.transforms.setStoreForClone(cloned_store);
2848
            }
2849
        } catch (Exception e) {
2850
            throw new CloneException(e);
2851
        }
2852
        return cloned_store;
2853

    
2854
    }
2855

    
2856
    @Override
2857
    public Feature getFeature(DynObject dynobject) {
2858
        if (dynobject instanceof DynObjectFeatureFacade){
2859
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2860
            return f;
2861
        }
2862
        return null;
2863
    }
2864

    
2865
    @Override
2866
    public Iterator iterator() {
2867
        try {
2868
            return this.getFeatureSet().fastIterator();
2869
        } catch (DataException ex) {
2870
            throw new RuntimeException(ex);
2871
        }
2872
    }
2873

    
2874
    @Override
2875
    public ExpressionBuilder createExpressionBuilder() {
2876
        ExpressionBuilder builder = null;
2877
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2878
            builder = ((FeatureStoreProvider_v2)this.provider).createExpression();
2879
        }
2880
        if( builder==null ) {
2881
            builder = ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2882
        }
2883
        return builder;
2884
    }
2885

    
2886
    @Override
2887
    public ExpressionBuilder createExpression() {
2888
        return createExpressionBuilder();
2889
    }
2890

    
2891
    public FeatureSet features() throws DataException {
2892
        // This is to avoid jython to create a property with this name
2893
        // to access method getFeatures.
2894
        return this.getFeatureSet();
2895
    }
2896

    
2897
    @Override
2898
    public DataStoreProviderFactory getProviderFactory() {
2899
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2900
        return factory;
2901
    }
2902

    
2903
    @Override
2904
    public void useCache(String providerName, DynObject parameters) throws DataException {
2905
        throw new UnsupportedOperationException();
2906
    }
2907

    
2908
    @Override
2909
    public boolean isBroken() {
2910
        return this.state.isBroken();
2911
    }
2912

    
2913
    @Override
2914
    public Throwable getBreakingsCause() {
2915
            return this.state.getBreakingsCause();
2916
    }
2917

    
2918
    @Override
2919
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2920
      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2921
      if( !factory.supportNumericOID() ) {
2922
          return null;
2923
      }
2924
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2925
      return wrappedIndex;
2926
  }
2927

    
2928
    @Override
2929
    public FeatureReference getFeatureReference(String code) {
2930
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2931
        return featureReference;
2932
    }
2933

    
2934
    @Override
2935
    public long getPendingChangesCount() {
2936
        if( this.featureManager==null ) {
2937
            return 0;
2938
        }
2939
        return this.featureManager.getPendingChangesCount();
2940
    }
2941
    
2942
    
2943
}