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

History | View | Annotate | Download (98.3 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
        try {
621
            selection = (FeatureSelection) state.get("selection");
622
        } catch(Throwable th) {
623
            state.setBreakingsCause(th);
624
        }
625

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

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

    
671
                    }
672

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

    
678

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
872
    }
873

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

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

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

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

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

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

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

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

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

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

    
937
    }
938

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

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

    
948
    }
949

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

    
954
    }
955

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

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

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

    
974
    }
975

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

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

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

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

    
1006
    //
1007
    // ====================================================================
1008
    // Edicion
1009
    //
1010

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

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

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

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

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

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

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

    
1051
        }
1052

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

    
1057
        featureCount = null;
1058

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1217
    @Override
1218
    public void delete(Feature feature) throws DataException {
1219
        this.commands.delete(feature);
1220
    }
1221

    
1222
    synchronized public void doDelete(Feature feature) throws DataException {
1223
        try {
1224
            checkInEditingMode();
1225
            checkIsOwnFeature(feature);
1226
            if (feature instanceof EditableFeature) {
1227
                throw new StoreDeleteEditableFeatureException(getName());
1228
            }
1229
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1230

    
1231
            //Update the featureManager and the spatialManager
1232
            featureManager.delete(feature.getReference());
1233
            spatialManager.deleteFeature(feature);
1234

    
1235
            newVersionOfUpdate();
1236
            hasStrongChanges = true;
1237
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1238
        } catch (Exception e) {
1239
            throw new StoreDeleteFeatureException(e, this.getName());
1240
        }
1241
    }
1242

    
1243
    private static EditableFeature lastChangedFeature = null;
1244

    
1245
    @Override
1246
    public synchronized void insert(EditableFeature feature)
1247
        throws DataException {
1248
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1249
        try {
1250
            switch (mode) {
1251
            case MODE_QUERY:
1252
                throw new NeedEditingModeException(this.getName());
1253

    
1254
            case MODE_APPEND:
1255
                checkIsOwnFeature(feature);
1256
                if (feature.getSource() != null) {
1257
                    throw new NoNewFeatureInsertException(this.getName());
1258
                }
1259
                this.featureCount = null;
1260
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1261
                feature.validate(Feature.UPDATE);
1262
                provider.append(((DefaultEditableFeature) feature).getData());
1263
                hasStrongChanges = true;
1264
                hasInserts = true;
1265
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1266
                break;
1267

    
1268
            case MODE_FULLEDIT:
1269
                if (feature.getSource() != null) {
1270
                    throw new NoNewFeatureInsertException(this.getName());
1271
                }
1272
                commands.insert(feature);
1273
            }
1274
        } catch (Exception e) {
1275
            throw new StoreInsertFeatureException(e, this.getName());
1276
        }
1277
    }
1278

    
1279
    synchronized public void doInsert(EditableFeature feature)
1280
        throws DataException {
1281
        checkIsOwnFeature(feature);
1282

    
1283
        waitForIndexes();
1284

    
1285
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1286
        newVersionOfUpdate();
1287
        if ((lastChangedFeature == null)
1288
            || (lastChangedFeature.getSource() != feature.getSource())) {
1289
            lastChangedFeature = feature;
1290
            feature.validate(Feature.UPDATE);
1291
            lastChangedFeature = null;
1292
        }
1293
        //Update the featureManager and the spatialManager
1294
        ((DefaultEditableFeature) feature).setInserted(true);
1295
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1296

    
1297

    
1298
        featureManager.add(newFeature);
1299
        spatialManager.insertFeature(newFeature);
1300

    
1301
        hasStrongChanges = true;
1302
        hasInserts = true;
1303
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1304
    }
1305

    
1306
    @Override
1307
    public void update(EditableFeature feature)
1308
    throws DataException {
1309
        if ((feature).getSource() == null) {
1310
            insert(feature);
1311
            return;
1312
        }
1313
        commands.update(feature, feature.getSource());
1314
    }
1315

    
1316
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1317
        throws DataException {
1318
        try {
1319
            checkInEditingMode();
1320
            checkIsOwnFeature(feature);
1321
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1322
            newVersionOfUpdate();
1323
            if ((lastChangedFeature == null)
1324
                || (lastChangedFeature.getSource() != feature.getSource())) {
1325
                lastChangedFeature = feature;
1326
                feature.validate(Feature.UPDATE);
1327
                lastChangedFeature = null;
1328
            }
1329

    
1330
            //Update the featureManager and the spatialManager
1331
            Feature newf = feature.getNotEditableCopy();
1332
            featureManager.update(newf, oldFeature);
1333
            spatialManager.updateFeature(newf, oldFeature);
1334

    
1335
            hasStrongChanges = true;
1336
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1337
        } catch (Exception e) {
1338
            throw new StoreUpdateFeatureException(e, this.getName());
1339
        }
1340
    }
1341

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

    
1357
    @Override
1358
    synchronized public void undo() throws UndoException {
1359
        Command undo = commands.getNextUndoCommand();
1360
        try {
1361
            checkInEditingMode();
1362
        } catch (NeedEditingModeException ex) {
1363
            throw new UndoException(undo, ex);
1364
        }
1365
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1366
        newVersionOfUpdate();
1367
        commands.undo();
1368
        hasStrongChanges = true;
1369
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1370
    }
1371

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

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

    
1390
    public synchronized FeatureCommandsStack getCommandsStack()
1391
        throws DataException {
1392
        checkInEditingMode();
1393
        return commands;
1394
    }
1395

    
1396
    @Override
1397
    synchronized public void cancelEditing() throws DataException {
1398
        if( spatialManager!=null ) {
1399
            spatialManager.cancelModifies();
1400
        }
1401
        try {
1402
            switch (mode) {
1403
            case MODE_QUERY:
1404
                throw new NeedEditingModeException(this.getName());
1405

    
1406
            case MODE_APPEND:
1407
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1408
                provider.abortAppend();
1409
                exitEditingMode();
1410
                ((FeatureSelection) this.getSelection()).deselectAll();
1411
                updateIndexes();
1412
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1413

    
1414
            case MODE_FULLEDIT:
1415
                boolean clearSelection = this.hasStrongChanges;
1416
                if (this.selection instanceof FeatureReferenceSelection) {
1417
                    clearSelection = this.hasInserts;
1418
                }
1419
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1420
                exitEditingMode();
1421
                if (clearSelection) {
1422
                    ((FeatureSelection) this.getSelection()).deselectAll();
1423
                }
1424
                updateIndexes();
1425
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1426
            }
1427
        } catch (Exception e) {
1428
            throw new StoreCancelEditingException(e, this.getName());
1429
        }
1430
    }
1431

    
1432
    @Override
1433
    synchronized public void finishEditing() throws DataException {
1434
        LOG.debug("finish editing of mode: {}", mode);
1435
        try {
1436

    
1437
            /*
1438
             * Selection needs to be cleared when editing stops
1439
             * to prevent conflicts with selection remaining from
1440
             * editing mode.
1441
             */
1442
//            ((FeatureSelection) this.getSelection()).deselectAll();
1443
            Map<String,List<FeatureAttributeDescriptor>> computedFields = this.getComputedFields();
1444
            switch (mode) {
1445
            case MODE_QUERY:
1446
                throw new NeedEditingModeException(this.getName());
1447

    
1448
            case MODE_APPEND:
1449
                if( selection!=null ) {
1450
                    selection = null;
1451
                }
1452
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1453
                saveDALFile();
1454
                provider.endAppend();
1455
                exitEditingMode();
1456
                this.updateComputedFields(computedFields);
1457
                loadDALFile();
1458
                updateIndexes();
1459
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1460
                break;
1461

    
1462
            case MODE_FULLEDIT:
1463
                if (hasStrongChanges && !this.allowWrite()) {
1464
                    throw new WriteNotAllowedException(getName());
1465
                }
1466
                saveDALFile();
1467
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1468
                    selection = null;
1469
                }
1470
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1471
                if (hasStrongChanges) {
1472
                    validateFeatures(Feature.FINISH_EDITING);
1473

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

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

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

    
1611
        case MODE_APPEND:
1612
          this.provider.endAppend();
1613
          exitEditingMode();
1614
          invalidateIndexes();
1615
          this.provider.beginAppend();
1616
          hasInserts = false;
1617
          break;
1618

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

    
1635
          commands =
1636
            new DefaultFeatureCommandsStack(this, featureManager,
1637
              spatialManager, featureTypeManager);
1638
          featureCount = null;
1639
          hasStrongChanges = false;
1640
          hasInserts = false;
1641
          break;
1642
        }
1643
      } catch (Exception e) {
1644
        throw new FinishEditingException(e);
1645
      }
1646
    }
1647

    
1648
    @Override
1649
    synchronized public boolean canCommitChanges() throws DataException {
1650
        if ( !this.allowWrite()) {
1651
                return false;
1652
        }
1653
            switch (mode) {
1654
            default:
1655
        case MODE_QUERY:
1656
                return false;
1657

    
1658
        case MODE_APPEND:
1659
                return true;
1660

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

    
1675
    @Override
1676
    public void beginEditingGroup(String description)
1677
        throws NeedEditingModeException {
1678
        checkInEditingMode();
1679
        commands.startComplex(description);
1680
    }
1681

    
1682
    @Override
1683
    public void endEditingGroup() throws NeedEditingModeException {
1684
        checkInEditingMode();
1685
        commands.endComplex();
1686
    }
1687

    
1688
    @Override
1689
    public boolean isAppendModeSupported() {
1690
        return this.provider.supportsAppendMode();
1691
    }
1692

    
1693
    @Override
1694
    public void export(DataServerExplorer explorer, String provider,
1695
        NewFeatureStoreParameters params) throws DataException {
1696

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

    
1711
            }
1712
            explorer.add(provider, params, true);
1713

    
1714
            DataManager manager = DALLocator.getDataManager();
1715
            target = (FeatureStore) manager.openStore(provider, params);
1716
            FeatureType targetType = target.getDefaultFeatureType();
1717

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

    
1749
    //
1750
    // ====================================================================
1751
    // Obtencion de datos
1752
    // getDataCollection, getFeatureCollection
1753
    //
1754

    
1755
    @Override
1756
    public DataSet getDataSet() throws DataException {
1757
        checkNotInAppendMode();
1758
        FeatureQuery query =
1759
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1760
        return new DefaultFeatureSet(this, query);
1761
    }
1762

    
1763
    @Override
1764
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1765
        checkNotInAppendMode();
1766
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1767
    }
1768

    
1769
    @Override
1770
    public void getDataSet(Observer observer) throws DataException {
1771
        checkNotInAppendMode();
1772
        this.getFeatureSet(null, observer);
1773
    }
1774

    
1775
    @Override
1776
    public void getDataSet(DataQuery dataQuery, Observer observer)
1777
        throws DataException {
1778
        checkNotInAppendMode();
1779
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1780
    }
1781

    
1782
    @Override
1783
    public FeatureSet getFeatureSet() throws DataException {
1784
        return this.getFeatureSet((FeatureQuery)null);
1785
    }
1786

    
1787
    @Override
1788
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1789
        throws DataException {
1790
        checkNotInAppendMode();
1791
        if( featureQuery==null ) {
1792
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1793
        }
1794
        return new DefaultFeatureSet(this, featureQuery);
1795
    }
1796

    
1797
    @Override
1798
    public FeatureSet getFeatureSet(String filter) throws DataException {
1799
        return this.getFeatureSet(filter, null, true);
1800
    }
1801

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

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

    
1855
    @Override
1856
    public List<Feature> getFeatures(String filter, String sortBy)  {
1857
        return this.getFeatures(filter, sortBy, true);
1858
    }
1859

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

    
1877
    @Override
1878
    public List<Feature> getFeatures(Expression filter, String sortBy)  {
1879
        return this.getFeatures(filter, sortBy, true);
1880
    }
1881

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

    
1909
    @Override
1910
    public List<Feature> getFeatures() {
1911
        return this.getFeatures(null, 500);
1912
    }
1913

    
1914
    @Override
1915
    public Feature first() throws DataException {
1916
        return this.findFirst((String)null, null, true);
1917
    }
1918
    
1919
    @Override
1920
    public Feature findFirst(String filter) throws DataException {
1921
        return this.findFirst(filter, null, true);
1922
    }
1923

    
1924
    @Override
1925
    public Feature findFirst(String filter, String sortBy) throws DataException {
1926
        return this.findFirst(filter, sortBy, true);
1927
    }
1928

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

    
1946
    @Override
1947
    public Feature findFirst(Expression filter, String sortBy) throws DataException {
1948
        return this.findFirst(filter, sortBy, true);
1949
    }
1950

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

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

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

    
1998
    @Override
1999
    public void getFeatureSet(Observer observer) throws DataException {
2000
        checkNotInAppendMode();
2001
        this.getFeatureSet(null, observer);
2002
    }
2003

    
2004
    @Override
2005
    public void getFeatureSet(FeatureQuery query, Observer observer)
2006
        throws DataException {
2007
        class LoadInBackGround implements Runnable {
2008

    
2009
            private final FeatureStore store;
2010
            private final FeatureQuery query;
2011
            private final Observer observer;
2012

    
2013
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
2014
                Observer observer) {
2015
                this.store = store;
2016
                this.query = query;
2017
                this.observer = observer;
2018
            }
2019

    
2020
            void notify(FeatureStoreNotification theNotification) {
2021
                observer.update(store, theNotification);
2022
            }
2023

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

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

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

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

    
2075
        FeatureType sourceFeatureType = featureType;
2076
        if (!this.transforms.isEmpty()) {
2077
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
2078
        }
2079
        // TODO comprobar que el id es de este store
2080

    
2081
        DefaultFeature feature =
2082
            new DefaultFeature(this,
2083
                this.provider.getFeatureProviderByReference(
2084
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
2085

    
2086
        if (!this.transforms.isEmpty()) {
2087
            return this.transforms.applyTransform(feature, featureType);
2088
        }
2089
        return feature;
2090
    }
2091

    
2092
    //
2093
    // ====================================================================
2094
    // Gestion de features
2095
    //
2096

    
2097
    private FeatureType fixFeatureType(DefaultFeatureType type)
2098
        throws DataException {
2099
        FeatureType original = this.getDefaultFeatureType();
2100

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

    
2113
                    } else
2114
                        if (type.isSubtypeOf(tmpType)) {
2115
                            found = true;
2116
                            original = tmpType;
2117
                            break;
2118
                        }
2119

    
2120
                }
2121
                if (!found) {
2122
                    throw new IllegalFeatureTypeException(getName());
2123
                }
2124
            }
2125
        }
2126

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

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

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

    
2171
        }
2172

    
2173
        return type;
2174
    }
2175

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

    
2203
    @Override
2204
    public FeatureType getDefaultFeatureType() throws DataException {
2205
        try {
2206

    
2207
            if (isEditing()) {
2208
                FeatureType auxFeatureType =
2209
                    featureTypeManager.getType(defaultFeatureType.getId());
2210
                if (auxFeatureType != null) {
2211
                    return avoidEditable(auxFeatureType);
2212
                }
2213
            }
2214
            FeatureType type = this.transforms.getDefaultFeatureType();
2215
                if (type != null) {
2216
                return avoidEditable(type);
2217
                }
2218

    
2219
            return avoidEditable(defaultFeatureType);
2220

    
2221
        } catch (Exception e) {
2222
            throw new GetFeatureTypeException(e, getName());
2223
        }
2224
    }
2225

    
2226
    private FeatureType avoidEditable(FeatureType ft) {
2227
        if (ft instanceof EditableFeatureType) {
2228
            return ((EditableFeatureType) ft).getNotEditableCopy();
2229
        } else {
2230
            return ft;
2231
        }
2232
    }
2233

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

    
2265
    public FeatureType getProviderDefaultFeatureType() {
2266
        return defaultFeatureType;
2267
    }
2268

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

    
2303
    public List getProviderFeatureTypes() throws DataException {
2304
        return Collections.unmodifiableList(this.featureTypes);
2305
    }
2306

    
2307
    @Override
2308
    public Feature createFeature(FeatureProvider data) throws DataException {
2309
        DefaultFeature feature = new DefaultFeature(this, data);
2310
        return feature;
2311
    }
2312

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

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

    
2332
            return feature;
2333
        } catch (Exception e) {
2334
            throw new CreateFeatureException(e, getName());
2335
        }
2336
    }
2337

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

    
2350
    }
2351

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

    
2368
    @Override
2369
    public EditableFeature createNewFeature(boolean defaultValues)
2370
        throws DataException {
2371
        return this.createNewFeature(this.getDefaultFeatureType(),
2372
            defaultValues);
2373
    }
2374

    
2375
    @Override
2376
    public EditableFeature createNewFeature() throws DataException {
2377
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2378
    }
2379

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

    
2394
    @Override
2395
    public EditableFeatureType createFeatureType() {
2396
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2397
        return ftype;
2398
    }
2399

    
2400
    @Override
2401
    public EditableFeatureType createFeatureType(String id) {
2402
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2403
        return ftype;
2404
    }
2405

    
2406
    //
2407
    // ====================================================================
2408
    // Index related methods
2409
    //
2410

    
2411
    @Override
2412
    public FeatureIndexes getIndexes() {
2413
        return this.indexes;
2414
    }
2415

    
2416
    @Override
2417
    public FeatureIndex createIndex(FeatureType featureType,
2418
        String attributeName, String indexName) throws DataException {
2419
        return createIndex(null, featureType, attributeName, indexName);
2420
    }
2421

    
2422
    @Override
2423
    public FeatureIndex createIndex(String indexTypeName,
2424
        FeatureType featureType, String attributeName, String indexName)
2425
        throws DataException {
2426

    
2427
        return createIndex(indexTypeName, featureType, attributeName,
2428
            indexName, false, null);
2429
    }
2430

    
2431
    @Override
2432
    public FeatureIndex createIndex(FeatureType featureType,
2433
        String attributeName, String indexName, Observer observer)
2434
        throws DataException {
2435
        return createIndex(null, featureType, attributeName, indexName,
2436
            observer);
2437
    }
2438

    
2439
    @Override
2440
    public FeatureIndex createIndex(String indexTypeName,
2441
        FeatureType featureType, String attributeName, String indexName,
2442
        final Observer observer) throws DataException {
2443

    
2444
        return createIndex(indexTypeName, featureType, attributeName,
2445
            indexName, true, observer);
2446
    }
2447

    
2448
    private FeatureIndex createIndex(String indexTypeName,
2449
        FeatureType featureType, String attributeName, String indexName,
2450
        boolean background, final Observer observer) throws DataException {
2451

    
2452
        checkNotInAppendMode();
2453
        FeatureIndexProviderServices index;
2454
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2455
                featureType, indexName,
2456
                featureType.getAttributeDescriptor(attributeName));
2457

    
2458
        try {
2459
            index.fill(background, observer);
2460
        } catch (FeatureIndexException e) {
2461
            throw new InitializeException(index.getName(), e);
2462
        }
2463

    
2464
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2465
        return index;
2466
    }
2467

    
2468
    //
2469
    // ====================================================================
2470
    // Transforms related methods
2471
    //
2472

    
2473
    @Override
2474
    public FeatureStoreTransforms getTransforms() {
2475
        return this.transforms;
2476
    }
2477

    
2478
    @Override
2479
    public FeatureQuery createFeatureQuery() {
2480
        return new DefaultFeatureQuery();
2481
    }
2482

    
2483
    @Override
2484
    public DataQuery createQuery() {
2485
        return createFeatureQuery();
2486
    }
2487

    
2488
    //
2489
    // ====================================================================
2490
    // UndoRedo related methods
2491
    //
2492

    
2493
    @Override
2494
    public boolean canRedo() {
2495
        return commands.canRedo();
2496
    }
2497

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

    
2503
    @Override
2504
    public void redo(int num) throws RedoException {
2505
        for (int i = 0; i < num; i++) {
2506
            redo();
2507
        }
2508
    }
2509

    
2510
    @Override
2511
    public void undo(int num) throws UndoException {
2512
        for (int i = 0; i < num; i++) {
2513
            undo();
2514
        }
2515
    }
2516

    
2517
    //
2518
    // ====================================================================
2519
    // Metadata related methods
2520
    //
2521

    
2522
    @Override
2523
    public Object getMetadataID() {
2524
        return this.provider.getSourceId();
2525
    }
2526

    
2527
    @Override
2528
    public void delegate(DynObject dynObject) {
2529
        this.metadata.delegate(dynObject);
2530
    }
2531

    
2532
    @Override
2533
    public DynClass getDynClass() {
2534
        return this.metadata.getDynClass();
2535
    }
2536

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

    
2564
    @Override
2565
    public boolean hasDynValue(String name) {
2566
        if (this.transforms.hasDynValue(name)) {
2567
            return true;
2568
        }
2569
        return this.metadata.hasDynValue(name);
2570
    }
2571

    
2572
    @Override
2573
    public boolean hasDynMethod(String name) {
2574
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2575
    }
2576

    
2577
    @Override
2578
    public void implement(DynClass dynClass) {
2579
        this.metadata.implement(dynClass);
2580
    }
2581

    
2582
    @Override
2583
    public Object invokeDynMethod(String name, Object[] args)
2584
        throws DynMethodException {
2585
        return this.metadata.invokeDynMethod(this, name, args);
2586
    }
2587

    
2588
    @Override
2589
    public Object invokeDynMethod(int code, Object[] args)
2590
        throws DynMethodException {
2591
        return this.metadata.invokeDynMethod(this, code, args);
2592
    }
2593

    
2594
    @Override
2595
    public void setDynValue(String name, Object value)
2596
        throws DynFieldNotFoundException {
2597
                if( this.transforms.hasDynValue(name) ) {
2598
                        this.transforms.setDynValue(name, value);
2599
                        return;
2600
                }
2601
        this.metadata.setDynValue(name, value);
2602

    
2603
    }
2604

    
2605
    /*
2606
     * (non-Javadoc)
2607
     *
2608
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2609
     */
2610
    @Override
2611
    public Set getMetadataChildren() {
2612
        return this.metadataChildren;
2613
    }
2614

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

    
2625
    public FeatureTypeManager getFeatureTypeManager() {
2626
        return this.featureTypeManager;
2627
    }
2628

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

    
2650
    private Long getTemporalOID() {
2651
        return this.temporalOid++;
2652
    }
2653

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

    
2670
    @Override
2671
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2672
        return ((DefaultFeature) feature).getData();
2673
    }
2674

    
2675
    @Override
2676
    public DataStore getStore() {
2677
        return this;
2678
    }
2679

    
2680
    @Override
2681
    public FeatureStore getFeatureStore() {
2682
        return this;
2683
    }
2684

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

    
2695
        featureCount = null;
2696
    }
2697

    
2698
    @Override
2699
    public FeatureCache getCache() {
2700
        return cache;
2701
    }
2702

    
2703
    @Override
2704
    public void clear() {
2705
        if (metadata != null) {
2706
            metadata.clear();
2707
        }
2708
    }
2709

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

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

    
2736
    @Override
2737
    public String getProviderName() {
2738
        if( this.provider!=null ) {
2739
            return this.provider.getProviderName();
2740
        }
2741
        if( this.parameters != null ) {
2742
            return this.parameters.getDataStoreName();
2743
        }
2744
        return null;
2745

    
2746
    }
2747

    
2748
    @Override
2749
    public boolean isKnownEnvelope() {
2750
        return this.provider.isKnownEnvelope();
2751
    }
2752

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

    
2758
    @Override
2759
    public int getRetrievedFeaturesLimit() {
2760
        return this.provider.getRetrievedFeaturesLimit();
2761
    }
2762

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

    
2782
    @Override
2783
    public Collection getTimes() {
2784
        if( this.timeSupport!=null ) {
2785
            return this.timeSupport.getTimes();
2786
        }
2787
        return this.provider.getTimes();
2788
    }
2789

    
2790
    @Override
2791
    public Collection getTimes(Interval interval) {
2792
        if( this.timeSupport!=null ) {
2793
            return this.timeSupport.getTimes(interval);
2794
        }
2795
        return this.provider.getTimes(interval);
2796
    }
2797

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

    
2830
    @Override
2831
    @SuppressWarnings("CloneDoesntCallSuperClone")
2832
    public Object clone() throws CloneNotSupportedException {
2833

    
2834
        DataStoreParameters dsp = getParameters();
2835

    
2836
        DefaultFeatureStore cloned_store = null;
2837

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

    
2850
    }
2851

    
2852
    @Override
2853
    public Feature getFeature(DynObject dynobject) {
2854
        if (dynobject instanceof DynObjectFeatureFacade){
2855
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2856
            return f;
2857
        }
2858
        return null;
2859
    }
2860

    
2861
    @Override
2862
    public Iterator iterator() {
2863
        try {
2864
            return this.getFeatureSet().fastIterator();
2865
        } catch (DataException ex) {
2866
            throw new RuntimeException(ex);
2867
        }
2868
    }
2869

    
2870
    @Override
2871
    public ExpressionBuilder createExpressionBuilder() {
2872
        ExpressionBuilder builder = null;
2873
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2874
            builder = ((FeatureStoreProvider_v2)this.provider).createExpression();
2875
        }
2876
        if( builder==null ) {
2877
            builder = ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2878
        }
2879
        return builder;
2880
    }
2881

    
2882
    @Override
2883
    public ExpressionBuilder createExpression() {
2884
        return createExpressionBuilder();
2885
    }
2886

    
2887
    public FeatureSet features() throws DataException {
2888
        // This is to avoid jython to create a property with this name
2889
        // to access method getFeatures.
2890
        return this.getFeatureSet();
2891
    }
2892

    
2893
    @Override
2894
    public DataStoreProviderFactory getProviderFactory() {
2895
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2896
        return factory;
2897
    }
2898

    
2899
    @Override
2900
    public void useCache(String providerName, DynObject parameters) throws DataException {
2901
        throw new UnsupportedOperationException();
2902
    }
2903

    
2904
    @Override
2905
    public boolean isBroken() {
2906
        return this.state.isBroken();
2907
    }
2908

    
2909
    @Override
2910
    public Throwable getBreakingsCause() {
2911
            return this.state.getBreakingsCause();
2912
    }
2913

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

    
2924
    @Override
2925
    public FeatureReference getFeatureReference(String code) {
2926
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2927
        return featureReference;
2928
    }
2929

    
2930
    @Override
2931
    public long getPendingChangesCount() {
2932
        if( this.featureManager==null ) {
2933
            return 0;
2934
        }
2935
        return this.featureManager.getPendingChangesCount();
2936
    }
2937
    
2938
    
2939
}