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

History | View | Annotate | Download (92 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

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

    
168
import org.slf4j.Logger;
169
import org.slf4j.LoggerFactory;
170

    
171
public class DefaultFeatureStore extends AbstractDisposable implements
172
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
173

    
174
    private static final Logger LOG = LoggerFactory
175
        .getLogger(DefaultFeatureStore.class);
176

    
177
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
178

    
179
    private DataStoreParameters parameters = null;
180
    private FeatureSelection selection;
181
    private FeatureLocks locks;
182

    
183
    private DelegateWeakReferencingObservable delegateObservable =
184
        new DelegateWeakReferencingObservable(this);
185

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

    
195
    private FeatureType defaultFeatureType = null;
196
    private List featureTypes = new ArrayList();
197

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

    
203
    private DefaultDataManager dataManager = null;
204

    
205
    private FeatureStoreProvider provider = null;
206

    
207
    private DefaultFeatureIndexes indexes;
208

    
209
    private DefaultFeatureStoreTransforms transforms;
210

    
211
    DelegatedDynObject metadata;
212

    
213
    private Set metadataChildren;
214

    
215
    private Long featureCount = null;
216

    
217
    private long temporalOid = 0;
218

    
219
    private FeatureCacheProvider cache;
220

    
221
    StateInformation state;
222

    
223
    FeatureStoreTimeSupport timeSupport;
224

    
225

    
226
    private class StateInformation extends HashMap<Object, Object> {
227

    
228
        private static final long serialVersionUID = 4109026189635185666L;
229

    
230
        private boolean broken;
231
        private Throwable breakingsCause;
232

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

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

    
245
        public boolean isBroken() {
246
            return this.broken;
247
        }
248

    
249
        public void broken() {
250
            this.broken = true;
251
        }
252

    
253
        public Throwable getBreakingsCause() {
254
            return this.breakingsCause;
255
        }
256

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

    
265

    
266

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

    
276
    public DefaultFeatureStore() {
277
        this.state = new StateInformation();
278
    }
279

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

    
284
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
285

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

    
291
        this.dataManager = (DefaultDataManager) dataManager;
292

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

    
301
    }
302

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

    
312
    @Override
313
    public DataStoreParameters getParameters() {
314
        return parameters;
315
    }
316

    
317
    public int getMode() {
318
        return this.mode;
319
    }
320

    
321
    @Override
322
    public DataManager getManager() {
323
        return this.dataManager;
324
    }
325

    
326
    @Override
327
    public Iterator getChildren() {
328
        return this.provider.getChilds();
329
    }
330

    
331
    @Override
332
    public FeatureStoreProvider getProvider() {
333
        return this.provider;
334
    }
335

    
336
    public FeatureManager getFeatureManager() {
337
        return this.featureManager;
338
    }
339

    
340
    @Override
341
    public void setFeatureTypes(List types, FeatureType defaultType) {
342
        this.featureTypes = types;
343
        this.defaultFeatureType = defaultType;
344
    }
345

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

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

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

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

    
416
        if (this.featureTypeManager != null) {
417
            this.featureTypeManager.dispose();
418
            this.featureTypeManager = null;
419
        }
420

    
421
        this.featureManager = null;
422
        this.spatialManager = null;
423

    
424
        this.parameters = null;
425
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
426
        if (delegateObservable != null) {
427
            this.delegateObservable.deleteObservers();
428
            this.delegateObservable = null;
429
        }
430
    }
431

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

    
441
    @Override
442
    public boolean canWriteGeometry(int geometryType) throws DataException {
443
        return this.provider.canWriteGeometry(geometryType, 0);
444
    }
445

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

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

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

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

    
495
    @Override
496
    public FeatureSelection createDefaultFeatureSelection()
497
        throws DataException {
498
        return new DefaultFeatureSelection(this);
499
    }
500

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

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

    
546
        }
547

    
548
        if (evaluatedAttr.isEmpty()) {
549
            evaluatedAttr = null;
550
        }
551

    
552
        state.set("evaluatedAttributes", evaluatedAttr);
553
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
554

    
555
    }
556

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

    
595
    private void load(StateInformation state) {
596
        this.featureTypes = new ArrayList();
597
        this.defaultFeatureType = null;
598
        this.featureCount = null;
599

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

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

    
617
        try {
618
            selection = (FeatureSelection) state.get("selection");
619
        } catch(Throwable th) {
620
            state.setBreakingsCause(th);
621
        }
622

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

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

    
668
                    }
669

    
670
            }
671
        } catch(Throwable th) {
672
            state.setBreakingsCause(th);
673
        }
674

    
675

    
676
        try {
677
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
678
            FeatureType ftype;
679

    
680
            if (defaultFeatureType == null ||
681
                    defaultFeatureType.getId() == null ||
682
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
683

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

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

    
708
        public DataStoreProviderServices getStoreProviderServices() {
709
                return this;
710
        }
711

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

    
722
            definition.addDynFieldObject("parameters")
723
                .setClassOfValue(DynObject.class).setMandatory(true)
724
                .setPersistent(true);
725

    
726
            definition.addDynFieldObject("selection")
727
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
728
                .setPersistent(true);
729

    
730
            definition.addDynFieldObject("transforms")
731
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
732
                .setMandatory(true).setPersistent(true);
733

    
734
            definition.addDynFieldMap("evaluatedAttributes")
735
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
736
                .setMandatory(false).setPersistent(true);
737

    
738
            definition.addDynFieldString("defaultFeatureTypeId")
739
                .setMandatory(true).setPersistent(true);
740
        }
741
    }
742

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

    
753
    //
754
    // ====================================================================
755
    // Gestion de la seleccion
756
    //
757

    
758
    @Override
759
    public void setSelection(DataSet selection) throws DataException {
760
        this.setSelection((FeatureSet) selection);
761
    }
762

    
763
    @Override
764
    public DataSet createSelection() throws DataException {
765
        return createFeatureSelection();
766
    }
767

    
768
    @Override
769
    public DataSet getSelection() throws DataException {
770
        return this.getFeatureSelection();
771
    }
772

    
773
    @Override
774
    public void setSelection(FeatureSet selection) throws DataException {
775
        setSelection(selection, true);
776
    }
777

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

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

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

    
832
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
833
    }
834

    
835
    @Override
836
    public FeatureSelection createFeatureSelection() throws DataException {
837
        return this.provider.createFeatureSelection();
838
    }
839

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

    
849
    //
850
    // ====================================================================
851
    // Gestion de notificaciones
852
    //
853

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

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

    
869
    }
870

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

    
882
    public void notifyChange(String notification, Feature feature) {
883
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
884
            feature));
885
    }
886

    
887
    public void notifyChange(String notification, Command command) {
888
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
889
            command));
890
    }
891

    
892
    public void notifyChange(String notification, EditableFeatureType type) {
893
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
894
            type));
895
    }
896

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

    
903
    //
904
    // ====================================================================
905
    // Gestion de bloqueos
906
    //
907

    
908
    @Override
909
    public boolean isLocksSupported() {
910
        return this.provider.isLocksSupported();
911
    }
912

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

    
925
    //
926
    // ====================================================================
927
    // Interface Observable
928
    //
929

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

    
934
    }
935

    
936
    @Override
937
    public void enableNotifications() {
938
        this.delegateObservable.enableNotifications();
939
    }
940

    
941
    @Override
942
    public void beginComplexNotification() {
943
        this.delegateObservable.beginComplexNotification();
944

    
945
    }
946

    
947
    @Override
948
    public void endComplexNotification() {
949
        this.delegateObservable.endComplexNotification();
950

    
951
    }
952

    
953
    @Override
954
    public void addObserver(Observer observer) {
955
        if (delegateObservable != null) {
956
            this.delegateObservable.addObserver(observer);
957
        }
958
    }
959

    
960
    @Override
961
    public void deleteObserver(Observer observer) {
962
        if (delegateObservable != null) {
963
            this.delegateObservable.deleteObserver(observer);
964
        }
965
    }
966

    
967
    @Override
968
    public void deleteObservers() {
969
        this.delegateObservable.deleteObservers();
970

    
971
    }
972

    
973
    //
974
    // ====================================================================
975
    // Interface Observer
976
    //
977
    // Usado para observar:
978
    // - su seleccion
979
    // - sus bloqueos
980
    // - sus recursos
981
    //
982

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

    
992
        } else if (observable instanceof FeatureStoreProvider) {
993
            if (observable == this.provider) {
994

    
995
            }
996
        } else if (observable instanceof FeatureReferenceSelection) {
997
            if(notification instanceof String){
998
                    this.notifyChange((String)notification);
999
            }
1000
        }
1001
    }
1002

    
1003
    //
1004
    // ====================================================================
1005
    // Edicion
1006
    //
1007

    
1008
    private void newVersionOfUpdate() {
1009
        this.versionOfUpdate++;
1010
    }
1011

    
1012
    private long currentVersionOfUpdate() {
1013
        return this.versionOfUpdate;
1014
    }
1015

    
1016
    private void checkInEditingMode() throws NeedEditingModeException {
1017
        if (mode != MODE_FULLEDIT) {
1018
            throw new NeedEditingModeException(this.getName());
1019
        }
1020
    }
1021

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

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

    
1038
    private void exitEditingMode() {
1039
        if (commands != null) {
1040
            commands.clear();
1041
            commands = null;
1042
        }
1043

    
1044
        if (featureTypeManager != null) {
1045
            featureTypeManager.dispose();
1046
            featureTypeManager = null;
1047

    
1048
        }
1049

    
1050
        // TODO implementar un dispose para estos dos
1051
        featureManager = null;
1052
        spatialManager = null;
1053

    
1054
        featureCount = null;
1055

    
1056
        mode = MODE_QUERY;
1057
        hasStrongChanges = true; // Lo deja a true por si las moscas
1058
        hasInserts = true;
1059
    }
1060

    
1061
    @Override
1062
    synchronized public void edit() throws DataException {
1063
        edit(MODE_FULLEDIT);
1064
    }
1065

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

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

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

    
1115
    private void invalidateIndexes() {
1116
        setIndexesValidStatus(false);
1117
    }
1118

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

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

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

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

    
1175
    @Override
1176
    public boolean isEditing() {
1177
        return mode == MODE_FULLEDIT;
1178
    }
1179

    
1180
    @Override
1181
    public boolean isAppending() {
1182
        return mode == MODE_APPEND;
1183
    }
1184

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

    
1197
            FeatureType oldt = type.getSource().getCopy();
1198
            FeatureType newt = type.getCopy();
1199
            commands.update(newt, oldt);
1200

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

    
1210
    @Override
1211
    public void delete(Feature feature) throws DataException {
1212
        this.commands.delete(feature);
1213
    }
1214

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

    
1224
            //Update the featureManager and the spatialManager
1225
            featureManager.delete(feature.getReference());
1226
            spatialManager.deleteFeature(feature);
1227

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

    
1236
    private static EditableFeature lastChangedFeature = null;
1237

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

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

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

    
1272
    synchronized public void doInsert(EditableFeature feature)
1273
        throws DataException {
1274
        checkIsOwnFeature(feature);
1275

    
1276
        waitForIndexes();
1277

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

    
1290

    
1291
        featureManager.add(newFeature);
1292
        spatialManager.insertFeature(newFeature);
1293

    
1294
        hasStrongChanges = true;
1295
        hasInserts = true;
1296
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1297
    }
1298

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

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

    
1323
            //Update the featureManager and the spatialManager
1324
            Feature newf = feature.getNotEditableCopy();
1325
            featureManager.update(newf, oldFeature);
1326
            spatialManager.updateFeature(newf, oldFeature);
1327

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

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

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

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

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

    
1383
    public synchronized FeatureCommandsStack getCommandsStack()
1384
        throws DataException {
1385
        checkInEditingMode();
1386
        return commands;
1387
    }
1388

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

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

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

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

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

    
1437
            switch (mode) {
1438
            case MODE_QUERY:
1439
                throw new NeedEditingModeException(this.getName());
1440

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

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

    
1463
                    /*
1464
                     * This will throw a PerformEditingExceptionif the provider
1465
                     * does not accept the changes (for example, an invalid field name)
1466
                     */
1467
                    provider.performChanges(featureManager.getDeleted(),
1468
                        featureManager.getInserted(),
1469
                        featureManager.getUpdated(),
1470
                        removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1471
                }  
1472
                saveDALFile();
1473
                exitEditingMode();
1474
                updateIndexes();
1475
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1476
                break;
1477
            }
1478
        } catch (PerformEditingException pee) {
1479
            throw new WriteException(provider.getSourceId().toString(), pee);
1480
        } catch (Exception e) {
1481
            throw new FinishEditingException(e);
1482
        }
1483
    }
1484
    
1485
    private List<FeatureStoreProvider.FeatureTypeChanged> removeCalculatedAttributes(List<FeatureStoreProvider.FeatureTypeChanged> ftypes) {
1486
        // FIXME: Falta por implementar
1487
//        for (FeatureStoreProvider.FeatureTypeChanged ftype : ftypes) {
1488
//            EditableFeatureType target = (EditableFeatureType) ftype.getTarget();
1489
//            for (FeatureAttributeDescriptor attributeDescriptor : ftype.getSource().getAttributeDescriptors()) {
1490
//                if (attributeDescriptor.isComputed()) {
1491
//                    target.remove(attributeDescriptor.getName());
1492
//                }
1493
//            }
1494
//        }
1495
        return ftypes;
1496
    }
1497
    
1498

    
1499
    @SuppressWarnings("UseSpecificCatch")
1500
    private void saveDALFile() {       
1501
        try {
1502
            DataServerExplorer explorer = this.getExplorer();
1503
            if( explorer == null ) {
1504
                return;
1505
            }
1506
            File f = explorer.getResourcePath(this, "dal");
1507
            if( f == null ) {
1508
                return;
1509
            }
1510
            DALFile dalFile = DALFile.getDALFile();
1511
            dalFile.setStore(this);
1512
            if( !dalFile.isEmpty() ) {
1513
                dalFile.write(f);
1514
            }
1515
        } catch (Exception ex) {
1516
            LOG.warn("Can't save DAL File", ex);
1517
        }
1518
    }
1519
    
1520
    @SuppressWarnings("UseSpecificCatch")
1521
    private void loadDALFile() {
1522
        try {
1523
            DataServerExplorer explorer = this.getExplorer();
1524
            if( explorer == null ) {
1525
                return;
1526
            }
1527
            File f = explorer.getResourcePath(this, "dal");
1528
            if( f == null || !f.exists() ) {
1529
                return;
1530
            }
1531
            DALFile dalFile = DALFile.getDALFile(f);
1532
            if( !dalFile.isEmpty() ) {
1533
                dalFile.updateStore(this);
1534
            }
1535
        } catch (Exception ex) {
1536
            LOG.warn("Can't load DAL File", ex);
1537
        }
1538
    }
1539
    
1540
    /**
1541
     * Save changes in the provider without leaving the edit mode.
1542
     * Do not call observers to communicate a change of ediding mode.
1543
     * The operation's history is eliminated to prevent inconsistencies
1544
     * in the data.
1545
     *
1546
     * @throws DataException
1547
     */
1548
    @Override
1549
    synchronized public void commitChanges() throws DataException {
1550
      LOG.debug("commitChanges of mode: {}", mode);
1551
      if( !canCommitChanges() ) {
1552
              throw new WriteNotAllowedException(getName());
1553
      }
1554
      try {
1555
        switch (mode) {
1556
        case MODE_QUERY:
1557
          throw new NeedEditingModeException(this.getName());
1558

    
1559
        case MODE_APPEND:
1560
          this.provider.endAppend();
1561
          exitEditingMode();
1562
          invalidateIndexes();
1563
          this.provider.beginAppend();
1564
          hasInserts = false;
1565
          break;
1566

    
1567
        case MODE_FULLEDIT:
1568
          if (hasStrongChanges && !this.allowWrite()) {
1569
            throw new WriteNotAllowedException(getName());
1570
          }
1571
          if (hasStrongChanges) {
1572
            validateFeatures(Feature.FINISH_EDITING);
1573
            provider.performChanges(featureManager.getDeleted(),
1574
              featureManager.getInserted(),
1575
              featureManager.getUpdated(),
1576
              removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1577
          }
1578
          invalidateIndexes();
1579
          featureManager = new FeatureManager();
1580
          featureTypeManager = new FeatureTypeManager(this);
1581
          spatialManager = new SpatialManager(this, provider.getEnvelope());
1582

    
1583
          commands =
1584
            new DefaultFeatureCommandsStack(this, featureManager,
1585
              spatialManager, featureTypeManager);
1586
          featureCount = null;
1587
          hasStrongChanges = false;
1588
          hasInserts = false;
1589
          break;
1590
        }
1591
      } catch (Exception e) {
1592
        throw new FinishEditingException(e);
1593
      }
1594
    }
1595

    
1596
    @Override
1597
    synchronized public boolean canCommitChanges() throws DataException {
1598
        if ( !this.allowWrite()) {
1599
                return false;
1600
        }
1601
            switch (mode) {
1602
            default:
1603
        case MODE_QUERY:
1604
                return false;
1605

    
1606
        case MODE_APPEND:
1607
                return true;
1608

    
1609
        case MODE_FULLEDIT:
1610
            List types = this.getFeatureTypes();
1611
            for( int i=0; i<types.size(); i++ ) {
1612
                    Object type = types.get(i);
1613
                    if( type instanceof DefaultEditableFeatureType ) {
1614
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1615
                                    return false;
1616
                            }
1617
                    }
1618
            }
1619
            return true;
1620
            }
1621
    }
1622

    
1623
    @Override
1624
    public void beginEditingGroup(String description)
1625
        throws NeedEditingModeException {
1626
        checkInEditingMode();
1627
        commands.startComplex(description);
1628
    }
1629

    
1630
    @Override
1631
    public void endEditingGroup() throws NeedEditingModeException {
1632
        checkInEditingMode();
1633
        commands.endComplex();
1634
    }
1635

    
1636
    @Override
1637
    public boolean isAppendModeSupported() {
1638
        return this.provider.supportsAppendMode();
1639
    }
1640

    
1641
    @Override
1642
    public void export(DataServerExplorer explorer, String provider,
1643
        NewFeatureStoreParameters params) throws DataException {
1644

    
1645
        if (this.getFeatureTypes().size() != 1) {
1646
            throw new NotYetImplemented(
1647
                "export whith more than one type not yet implemented");
1648
        }
1649
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1650
        FeatureStore target = null;
1651
        FeatureSet features = null;
1652
        DisposableIterator iterator = null;
1653
        try {
1654
            FeatureType type = this.getDefaultFeatureType();
1655
            if ((params.getDefaultFeatureType() == null)
1656
                || (params.getDefaultFeatureType().size() == 0)) {
1657
                params.setDefaultFeatureType(type.getEditable());
1658

    
1659
            }
1660
            explorer.add(provider, params, true);
1661

    
1662
            DataManager manager = DALLocator.getDataManager();
1663
            target = (FeatureStore) manager.openStore(provider, params);
1664
            FeatureType targetType = target.getDefaultFeatureType();
1665

    
1666
            target.edit(MODE_APPEND);
1667
            FeatureAttributeDescriptor[] pkattrs = type.getPrimaryKey();
1668
            if (featureSelection.getSize() > 0) {
1669
                features = this.getFeatureSelection();
1670
            } else {
1671
                if ((pkattrs != null) && (pkattrs.length > 0)) {
1672
                    FeatureQuery query = createFeatureQuery();
1673
                    for (FeatureAttributeDescriptor pkattr : pkattrs) {
1674
                        query.getOrder().add(pkattr.getName(), true);
1675
                    }
1676
                    features = this.getFeatureSet(query);
1677
                } else {
1678
                    features = this.getFeatureSet();
1679
                }
1680
            }
1681
            iterator = features.fastIterator();
1682
            while (iterator.hasNext()) {
1683
                DefaultFeature feature = (DefaultFeature) iterator.next();
1684
                target.insert(target.createNewFeature(targetType, feature));
1685
            }
1686
            target.finishEditing();
1687
            target.dispose();
1688
        } catch (Exception e) {
1689
            throw new DataExportException(e, params.toString());
1690
        } finally {
1691
            dispose(iterator);
1692
            dispose(features);
1693
            dispose(target);
1694
        }
1695
    }
1696

    
1697
    //
1698
    // ====================================================================
1699
    // Obtencion de datos
1700
    // getDataCollection, getFeatureCollection
1701
    //
1702

    
1703
    @Override
1704
    public DataSet getDataSet() throws DataException {
1705
        checkNotInAppendMode();
1706
        FeatureQuery query =
1707
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1708
        return new DefaultFeatureSet(this, query);
1709
    }
1710

    
1711
    @Override
1712
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1713
        checkNotInAppendMode();
1714
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1715
    }
1716

    
1717
    @Override
1718
    public void getDataSet(Observer observer) throws DataException {
1719
        checkNotInAppendMode();
1720
        this.getFeatureSet(null, observer);
1721
    }
1722

    
1723
    @Override
1724
    public void getDataSet(DataQuery dataQuery, Observer observer)
1725
        throws DataException {
1726
        checkNotInAppendMode();
1727
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1728
    }
1729

    
1730
    @Override
1731
    public FeatureSet getFeatureSet() throws DataException {
1732
        return this.getFeatureSet((FeatureQuery)null);
1733
    }
1734

    
1735
    @Override
1736
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1737
        throws DataException {
1738
        checkNotInAppendMode();
1739
        if( featureQuery==null ) {
1740
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1741
        }
1742
        return new DefaultFeatureSet(this, featureQuery);
1743
    }
1744

    
1745
    @Override
1746
    public FeatureSet getFeatureSet(String filter) throws DataException {
1747
        return this.getFeatureSet(filter, null, true);
1748
    }
1749

    
1750
    @Override
1751
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1752
        return this.getFeatureSet(filter, sortBy, true);
1753
    }
1754

    
1755
    @Override
1756
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1757
        FeatureQuery query = this.createFeatureQuery();
1758
        if( !StringUtils.isEmpty(filter) ) {
1759
            query.setFilter(filter);
1760
        }
1761
        if( !StringUtils.isEmpty(sortBy) ) {
1762
            query.getOrder().add(sortBy, asc);
1763
        }
1764
        return this.getFeatureSet(query);
1765
    }
1766
    
1767
    @Override
1768
    public List<Feature> getFeatures(String filter)  {
1769
        return this.getFeatures(filter, null, true);
1770
    }
1771

    
1772
    @Override
1773
    public List<Feature> getFeatures(String filter, String sortBy)  {
1774
        return this.getFeatures(filter, sortBy, true);
1775
    }
1776

    
1777
    @Override
1778
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1779
        FeatureQuery query = this.createFeatureQuery();
1780
        if( !StringUtils.isEmpty(filter) ) {
1781
            query.setFilter(filter);
1782
        }
1783
        if( !StringUtils.isEmpty(sortBy) ) {
1784
            query.getOrder().add(sortBy, asc);
1785
        }
1786
        return this.getFeatures(query, 100);
1787
    }
1788
    
1789
    @Override
1790
    public List<Feature> getFeatures(FeatureQuery query)  {
1791
        return this.getFeatures(query, 100);
1792
    }
1793
    
1794
    @Override
1795
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1796
        try {
1797
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1798
            return pager.asList();
1799
        } catch (BaseException ex) {
1800
            throw new RuntimeException("Can't create the list of features.", ex);
1801
        }
1802
    }
1803

    
1804
    @Override
1805
    public List<Feature> getFeatures() {
1806
        return this.getFeatures(null, 500);
1807
    }
1808

    
1809
    @Override
1810
    public Feature findFirst(String filter) throws DataException {
1811
        return this.findFirst(filter, null, true);
1812
    }
1813

    
1814
    @Override
1815
    public Feature findFirst(String filter, String sortBy) throws DataException {
1816
        return this.findFirst(filter, sortBy, true);
1817
    }
1818

    
1819
    @Override
1820
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1821
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1822
        if( set==null || set.isEmpty() ) {
1823
            return null;
1824
        }
1825
        DisposableIterator it = set.iterator();
1826
        Feature f = (Feature) it.next();
1827
        it.dispose();
1828
        return f;
1829
    }
1830
    
1831
    @Override
1832
    public void accept(Visitor visitor) throws BaseException {
1833
        FeatureSet set = getFeatureSet();
1834
        try {
1835
            set.accept(visitor);
1836
        } finally {
1837
            set.dispose();
1838
        }
1839
    }
1840

    
1841
    @Override
1842
    public void accept(Visitor visitor, DataQuery dataQuery)
1843
        throws BaseException {
1844
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1845
        try {
1846
            set.accept(visitor);
1847
        } finally {
1848
            set.dispose();
1849
        }
1850
    }
1851

    
1852
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1853
        throws DataException {
1854
        DefaultFeatureType fType =
1855
            (DefaultFeatureType) this.getFeatureType(featureQuery
1856
                .getFeatureTypeId());
1857
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1858
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1859
        }
1860
        return fType;
1861
    }
1862

    
1863
    @Override
1864
    public void getFeatureSet(Observer observer) throws DataException {
1865
        checkNotInAppendMode();
1866
        this.getFeatureSet(null, observer);
1867
    }
1868

    
1869
    @Override
1870
    public void getFeatureSet(FeatureQuery query, Observer observer)
1871
        throws DataException {
1872
        class LoadInBackGround implements Runnable {
1873

    
1874
            private final FeatureStore store;
1875
            private final FeatureQuery query;
1876
            private final Observer observer;
1877

    
1878
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1879
                Observer observer) {
1880
                this.store = store;
1881
                this.query = query;
1882
                this.observer = observer;
1883
            }
1884

    
1885
            void notify(FeatureStoreNotification theNotification) {
1886
                observer.update(store, theNotification);
1887
            }
1888

    
1889
            @Override
1890
            public void run() {
1891
                FeatureSet set = null;
1892
                try {
1893
                    set = store.getFeatureSet(query);
1894
                    notify(new DefaultFeatureStoreNotification(store,
1895
                        FeatureStoreNotification.LOAD_FINISHED, set));
1896
                } catch (Exception e) {
1897
                    notify(new DefaultFeatureStoreNotification(store,
1898
                        FeatureStoreNotification.LOAD_FINISHED, e));
1899
                } finally {
1900
                    dispose(set);
1901
                }
1902
            }
1903
        }
1904

    
1905
        checkNotInAppendMode();
1906
        if (query == null) {
1907
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1908
        }
1909
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1910
        Thread thread = new Thread(task, "Load Feature Set in background");
1911
        thread.start();
1912
    }
1913

    
1914
    @Override
1915
    public Feature getFeatureByReference(FeatureReference reference)
1916
        throws DataException {
1917
        checkNotInAppendMode();
1918
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1919
        FeatureType featureType;
1920
        if (ref.getFeatureTypeId() == null) {
1921
            featureType = this.getDefaultFeatureType();
1922
        } else {
1923
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1924
        }
1925
        return this.getFeatureByReference(reference, featureType);
1926
    }
1927

    
1928
    @Override
1929
    public Feature getFeatureByReference(FeatureReference reference,
1930
        FeatureType featureType) throws DataException {
1931
        checkNotInAppendMode();
1932
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1933
        if (this.mode == MODE_FULLEDIT) {
1934
            Feature f = featureManager.get(reference, this, featureType);
1935
            if (f != null) {
1936
                return f;
1937
            }
1938
        }
1939

    
1940
        FeatureType sourceFeatureType = featureType;
1941
        if (!this.transforms.isEmpty()) {
1942
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1943
        }
1944
        // TODO comprobar que el id es de este store
1945

    
1946
        DefaultFeature feature =
1947
            new DefaultFeature(this,
1948
                this.provider.getFeatureProviderByReference(
1949
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1950

    
1951
        if (!this.transforms.isEmpty()) {
1952
            return this.transforms.applyTransform(feature, featureType);
1953
        }
1954
        return feature;
1955
    }
1956

    
1957
    //
1958
    // ====================================================================
1959
    // Gestion de features
1960
    //
1961

    
1962
    private FeatureType fixFeatureType(DefaultFeatureType type)
1963
        throws DataException {
1964
        FeatureType original = this.getDefaultFeatureType();
1965

    
1966
        if ((type == null) || type.equals(original)) {
1967
            return original;
1968
        } else {
1969
            if (!type.isSubtypeOf(original)) {
1970
                Iterator iter = this.getFeatureTypes().iterator();
1971
                FeatureType tmpType;
1972
                boolean found = false;
1973
                while (iter.hasNext()) {
1974
                    tmpType = (FeatureType) iter.next();
1975
                    if (type.equals(tmpType)) {
1976
                        return type;
1977

    
1978
                    } else
1979
                        if (type.isSubtypeOf(tmpType)) {
1980
                            found = true;
1981
                            original = tmpType;
1982
                            break;
1983
                        }
1984

    
1985
                }
1986
                if (!found) {
1987
                    throw new IllegalFeatureTypeException(getName());
1988
                }
1989
            }
1990
        }
1991

    
1992
        // Checks that type has all fields of pk
1993
        // else add the missing attributes at the end.
1994
        if (!original.hasOID()) {
1995
            // Gets original pk attributes
1996
            DefaultEditableFeatureType edOriginal =
1997
                (DefaultEditableFeatureType) original.getEditable();
1998
            FeatureAttributeDescriptor orgAttr;
1999
            Iterator edOriginalIter = edOriginal.iterator();
2000
            while (edOriginalIter.hasNext()) {
2001
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2002
                if (!orgAttr.isPrimaryKey()) {
2003
                    edOriginalIter.remove();
2004
                }
2005
            }
2006

    
2007
            // Checks if all pk attributes are in type
2008
            Iterator typeIterator;
2009
            edOriginalIter = edOriginal.iterator();
2010
            FeatureAttributeDescriptor attr;
2011
            while (edOriginalIter.hasNext()) {
2012
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2013
                typeIterator = type.iterator();
2014
                while (typeIterator.hasNext()) {
2015
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
2016
                    if (attr.getName().equals(orgAttr.getName())) {
2017
                        edOriginalIter.remove();
2018
                        break;
2019
                    }
2020
                }
2021
            }
2022

    
2023
            // add missing pk attributes if any
2024
            if (edOriginal.size() > 0) {
2025
                boolean isEditable = type instanceof DefaultEditableFeatureType;
2026
                DefaultEditableFeatureType edType =
2027
                    (DefaultEditableFeatureType) original.getEditable();
2028
                edType.clear();
2029
                edType.addAll(type);
2030
                edType.addAll(edOriginal);
2031
                if (!isEditable) {
2032
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
2033
                }
2034
            }
2035

    
2036
        }
2037

    
2038
        return type;
2039
    }
2040

    
2041
    @Override
2042
    public void validateFeatures(int mode) throws DataException {
2043
        FeatureSet collection = null;
2044
        DisposableIterator iter = null;
2045
        try {
2046
            FeatureRules rules = this.getDefaultFeatureType().getRules();
2047
            if( rules==null || rules.isEmpty() ) {
2048
                return;
2049
            }
2050
            checkNotInAppendMode();
2051
            collection = this.getFeatureSet();
2052
            iter = collection.fastIterator();
2053
            long previousVersionOfUpdate = currentVersionOfUpdate();
2054
            while (iter.hasNext()) {
2055
                ((DefaultFeature) iter.next()).validate(mode);
2056
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
2057
                    throw new ConcurrentDataModificationException(getName());
2058
                }
2059
            }
2060
        } catch (Exception e) {
2061
            throw new ValidateFeaturesException(e, getName());
2062
        } finally {
2063
            DisposeUtils.disposeQuietly(iter);
2064
            DisposeUtils.disposeQuietly(collection);
2065
        }
2066
    }
2067

    
2068
    @Override
2069
    public FeatureType getDefaultFeatureType() throws DataException {
2070
        try {
2071

    
2072
            if (isEditing()) {
2073
                FeatureType auxFeatureType =
2074
                    featureTypeManager.getType(defaultFeatureType.getId());
2075
                if (auxFeatureType != null) {
2076
                    return avoidEditable(auxFeatureType);
2077
                }
2078
            }
2079
            FeatureType type = this.transforms.getDefaultFeatureType();
2080
            if (type != null) {
2081
                return avoidEditable(type);
2082
            }
2083

    
2084
            return avoidEditable(defaultFeatureType);
2085

    
2086
        } catch (Exception e) {
2087
            throw new GetFeatureTypeException(e, getName());
2088
        }
2089
    }
2090

    
2091
    private FeatureType avoidEditable(FeatureType ft) {
2092
        if (ft instanceof EditableFeatureType) {
2093
            return ((EditableFeatureType) ft).getNotEditableCopy();
2094
        } else {
2095
            return ft;
2096
        }
2097
    }
2098

    
2099
    @Override
2100
    public FeatureType getFeatureType(String featureTypeId)
2101
        throws DataException {
2102
        if (featureTypeId == null) {
2103
            return this.getDefaultFeatureType();
2104
        }
2105
        try {
2106
            if (isEditing()) {
2107
                FeatureType auxFeatureType =
2108
                    featureTypeManager.getType(featureTypeId);
2109
                if (auxFeatureType != null) {
2110
                    return auxFeatureType;
2111
                }
2112
            }
2113
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2114
            if (type != null) {
2115
                return type;
2116
            }
2117
            Iterator iter = this.featureTypes.iterator();
2118
            while (iter.hasNext()) {
2119
                type = (FeatureType) iter.next();
2120
                if (type.getId().equals(featureTypeId)) {
2121
                    return type;
2122
                }
2123
            }
2124
            return null;
2125
        } catch (Exception e) {
2126
            throw new GetFeatureTypeException(e, getName());
2127
        }
2128
    }
2129

    
2130
    public FeatureType getProviderDefaultFeatureType() {
2131
        return defaultFeatureType;
2132
    }
2133

    
2134
    @Override
2135
    public List getFeatureTypes() throws DataException {
2136
        try {
2137
            List types;
2138
            if (isEditing()) {
2139
                types = new ArrayList();
2140
                Iterator it = featureTypes.iterator();
2141
                while (it.hasNext()) {
2142
                    FeatureType type = (FeatureType) it.next();
2143
                    FeatureType typeaux =
2144
                        featureTypeManager.getType(type.getId());
2145
                    if (typeaux != null) {
2146
                        types.add(typeaux);
2147
                    } else {
2148
                        types.add(type);
2149
                    }
2150
                }
2151
                it = featureTypeManager.newsIterator();
2152
                while (it.hasNext()) {
2153
                    FeatureType type = (FeatureType) it.next();
2154
                    types.add(type);
2155
                }
2156
            } else {
2157
                types = this.transforms.getFeatureTypes();
2158
                if (types == null) {
2159
                    types = featureTypes;
2160
                }
2161
            }
2162
            return Collections.unmodifiableList(types);
2163
        } catch (Exception e) {
2164
            throw new GetFeatureTypeException(e, getName());
2165
        }
2166
    }
2167

    
2168
    public List getProviderFeatureTypes() throws DataException {
2169
        return Collections.unmodifiableList(this.featureTypes);
2170
    }
2171

    
2172
    @Override
2173
    public Feature createFeature(FeatureProvider data) throws DataException {
2174
        DefaultFeature feature = new DefaultFeature(this, data);
2175
        return feature;
2176
    }
2177

    
2178
    public Feature createFeature(FeatureProvider data, FeatureType type)
2179
        throws DataException {
2180
        // FIXME: falta por implementar
2181
        // Comprobar si es un subtipo del feature de data
2182
        // y construir un feature usando el subtipo.
2183
        // Probablemente requiera generar una copia del data.
2184
        throw new NotYetImplemented();
2185
    }
2186

    
2187
    @Override
2188
    public EditableFeature createNewFeature(FeatureType type,
2189
        Feature defaultValues) throws DataException {
2190
        try {
2191
            FeatureProvider data = createNewFeatureProvider(type);
2192
            DefaultEditableFeature feature =
2193
                new DefaultEditableFeature(this, data);
2194
            feature.initializeValues(defaultValues);
2195
            data.setNew(true);
2196

    
2197
            return feature;
2198
        } catch (Exception e) {
2199
            throw new CreateFeatureException(e, getName());
2200
        }
2201
    }
2202

    
2203
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2204
        throws DataException {
2205
        type = this.fixFeatureType((DefaultFeatureType) type);
2206
        FeatureProvider data = this.provider.createFeatureProvider(type);
2207
        data.setNew(true);
2208
        if (type.hasOID() && (data.getOID() == null)) {
2209
            data.setOID(this.provider.createNewOID());
2210
        } else {
2211
            data.setOID(this.getTemporalOID());
2212
        }
2213
        return data;
2214

    
2215
    }
2216

    
2217
    @Override
2218
    public EditableFeature createNewFeature(FeatureType type,
2219
        boolean defaultValues) throws DataException {
2220
        try {
2221
            FeatureProvider data = createNewFeatureProvider(type);
2222
            DefaultEditableFeature feature =
2223
                new DefaultEditableFeature(this, data);
2224
            if (defaultValues) {
2225
                feature.initializeValues();
2226
            }
2227
            return feature;
2228
        } catch (Exception e) {
2229
            throw new CreateFeatureException(e, getName());
2230
        }
2231
    }
2232

    
2233
    @Override
2234
    public EditableFeature createNewFeature(boolean defaultValues)
2235
        throws DataException {
2236
        return this.createNewFeature(this.getDefaultFeatureType(),
2237
            defaultValues);
2238
    }
2239

    
2240
    @Override
2241
    public EditableFeature createNewFeature() throws DataException {
2242
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2243
    }
2244

    
2245
    @Override
2246
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2247
        FeatureType ft = this.getDefaultFeatureType();
2248
        EditableFeature f = this.createNewFeature(ft, false);
2249
                for( FeatureAttributeDescriptor desc : ft ) {
2250
                        try {
2251
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2252
                        } catch(Throwable th) {
2253
                                // Ignore
2254
                        }
2255
                }
2256
        return f;
2257
    }
2258

    
2259
    @Override
2260
    public EditableFeatureType createFeatureType() {
2261
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2262
        return ftype;
2263
    }
2264

    
2265
    @Override
2266
    public EditableFeatureType createFeatureType(String id) {
2267
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2268
        return ftype;
2269
    }
2270

    
2271
    //
2272
    // ====================================================================
2273
    // Index related methods
2274
    //
2275

    
2276
    @Override
2277
    public FeatureIndexes getIndexes() {
2278
        return this.indexes;
2279
    }
2280

    
2281
    @Override
2282
    public FeatureIndex createIndex(FeatureType featureType,
2283
        String attributeName, String indexName) throws DataException {
2284
        return createIndex(null, featureType, attributeName, indexName);
2285
    }
2286

    
2287
    @Override
2288
    public FeatureIndex createIndex(String indexTypeName,
2289
        FeatureType featureType, String attributeName, String indexName)
2290
        throws DataException {
2291

    
2292
        return createIndex(indexTypeName, featureType, attributeName,
2293
            indexName, false, null);
2294
    }
2295

    
2296
    @Override
2297
    public FeatureIndex createIndex(FeatureType featureType,
2298
        String attributeName, String indexName, Observer observer)
2299
        throws DataException {
2300
        return createIndex(null, featureType, attributeName, indexName,
2301
            observer);
2302
    }
2303

    
2304
    @Override
2305
    public FeatureIndex createIndex(String indexTypeName,
2306
        FeatureType featureType, String attributeName, String indexName,
2307
        final Observer observer) throws DataException {
2308

    
2309
        return createIndex(indexTypeName, featureType, attributeName,
2310
            indexName, true, observer);
2311
    }
2312

    
2313
    private FeatureIndex createIndex(String indexTypeName,
2314
        FeatureType featureType, String attributeName, String indexName,
2315
        boolean background, final Observer observer) throws DataException {
2316

    
2317
        checkNotInAppendMode();
2318
        FeatureIndexProviderServices index;
2319
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2320
                featureType, indexName,
2321
                featureType.getAttributeDescriptor(attributeName));
2322

    
2323
        try {
2324
            index.fill(background, observer);
2325
        } catch (FeatureIndexException e) {
2326
            throw new InitializeException(index.getName(), e);
2327
        }
2328

    
2329
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2330
        return index;
2331
    }
2332

    
2333
    //
2334
    // ====================================================================
2335
    // Transforms related methods
2336
    //
2337

    
2338
    @Override
2339
    public FeatureStoreTransforms getTransforms() {
2340
        return this.transforms;
2341
    }
2342

    
2343
    @Override
2344
    public FeatureQuery createFeatureQuery() {
2345
        return new DefaultFeatureQuery();
2346
    }
2347

    
2348
    @Override
2349
    public DataQuery createQuery() {
2350
        return createFeatureQuery();
2351
    }
2352

    
2353
    //
2354
    // ====================================================================
2355
    // UndoRedo related methods
2356
    //
2357

    
2358
    @Override
2359
    public boolean canRedo() {
2360
        return commands.canRedo();
2361
    }
2362

    
2363
    @Override
2364
    public boolean canUndo() {
2365
        return commands.canUndo();
2366
    }
2367

    
2368
    @Override
2369
    public void redo(int num) throws RedoException {
2370
        for (int i = 0; i < num; i++) {
2371
            redo();
2372
        }
2373
    }
2374

    
2375
    @Override
2376
    public void undo(int num) throws UndoException {
2377
        for (int i = 0; i < num; i++) {
2378
            undo();
2379
        }
2380
    }
2381

    
2382
    //
2383
    // ====================================================================
2384
    // Metadata related methods
2385
    //
2386

    
2387
    @Override
2388
    public Object getMetadataID() {
2389
        return this.provider.getSourceId();
2390
    }
2391

    
2392
    @Override
2393
    public void delegate(DynObject dynObject) {
2394
        this.metadata.delegate(dynObject);
2395
    }
2396

    
2397
    @Override
2398
    public DynClass getDynClass() {
2399
        return this.metadata.getDynClass();
2400
    }
2401

    
2402
    @Override
2403
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2404
                if( this.transforms.hasDynValue(name) ) {
2405
                        return this.transforms.getDynValue(name);
2406
                }
2407
                if (this.metadata.hasDynValue(name)) {
2408
                        return this.metadata.getDynValue(name);
2409
                }
2410
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2411
                        return this.provider.getProviderName();
2412
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2413
                        return this.provider.getSourceId();
2414
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2415
                        try {
2416
                                return this.getDefaultFeatureType();
2417
                        } catch (DataException e) {
2418
                                return null;
2419
                        }
2420
                }
2421
                return this.metadata.getDynValue(name);
2422
        }
2423

    
2424
    @Override
2425
    public boolean hasDynValue(String name) {
2426
                if( this.transforms.hasDynValue(name) ) {
2427
                        return true;
2428
                }
2429
        return this.metadata.hasDynValue(name);
2430
    }
2431

    
2432
    @Override
2433
    public boolean hasDynMethod(String name) {
2434
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2435
    }
2436

    
2437
    @Override
2438
    public void implement(DynClass dynClass) {
2439
        this.metadata.implement(dynClass);
2440
    }
2441

    
2442
    @Override
2443
    public Object invokeDynMethod(String name, Object[] args)
2444
        throws DynMethodException {
2445
        return this.metadata.invokeDynMethod(this, name, args);
2446
    }
2447

    
2448
    @Override
2449
    public Object invokeDynMethod(int code, Object[] args)
2450
        throws DynMethodException {
2451
        return this.metadata.invokeDynMethod(this, code, args);
2452
    }
2453

    
2454
    @Override
2455
    public void setDynValue(String name, Object value)
2456
        throws DynFieldNotFoundException {
2457
                if( this.transforms.hasDynValue(name) ) {
2458
                        this.transforms.setDynValue(name, value);
2459
                        return;
2460
                }
2461
        this.metadata.setDynValue(name, value);
2462

    
2463
    }
2464

    
2465
    /*
2466
     * (non-Javadoc)
2467
     *
2468
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2469
     */
2470
    @Override
2471
    public Set getMetadataChildren() {
2472
        return this.metadataChildren;
2473
    }
2474

    
2475
    /*
2476
     * (non-Javadoc)
2477
     *
2478
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2479
     */
2480
    @Override
2481
    public String getMetadataName() {
2482
        return this.provider.getProviderName();
2483
    }
2484

    
2485
    public FeatureTypeManager getFeatureTypeManager() {
2486
        return this.featureTypeManager;
2487
    }
2488

    
2489
    @Override
2490
    public long getFeatureCount() throws DataException {
2491
        if (featureCount == null) {
2492
            featureCount = this.provider.getFeatureCount();
2493
        }
2494
        if (this.isEditing()) {
2495
            if(this.isAppending()) {
2496
                try{
2497
                    throw new IllegalStateException();
2498
                } catch(IllegalStateException e) {
2499
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND",e);
2500
                }
2501
                return -1;
2502
            } else {
2503
                return featureCount
2504
                    + this.featureManager.getDeltaSize();
2505
            }
2506
        }
2507
        return featureCount;
2508
    }
2509

    
2510
    private Long getTemporalOID() {
2511
        return this.temporalOid++;
2512
    }
2513

    
2514
    @Override
2515
    public FeatureType getProviderFeatureType(String featureTypeId) {
2516
        if (featureTypeId == null) {
2517
            return this.defaultFeatureType;
2518
        }
2519
        FeatureType type;
2520
        Iterator iter = this.featureTypes.iterator();
2521
        while (iter.hasNext()) {
2522
            type = (FeatureType) iter.next();
2523
            if (type.getId().equals(featureTypeId)) {
2524
                return type;
2525
            }
2526
        }
2527
        return null;
2528
    }
2529

    
2530
    @Override
2531
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2532
        return ((DefaultFeature) feature).getData();
2533
    }
2534

    
2535
    @Override
2536
    public DataStore getStore() {
2537
        return this;
2538
    }
2539

    
2540
    @Override
2541
    public FeatureStore getFeatureStore() {
2542
        return this;
2543
    }
2544

    
2545
    @Override
2546
    public void createCache(String name, DynObject parameters)
2547
        throws DataException {
2548
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2549
        if (cache == null) {
2550
            throw new CreateException("FeaureCacheProvider", null);
2551
        }
2552
        cache.apply(this, provider);
2553
        provider = cache;
2554

    
2555
        featureCount = null;
2556
    }
2557

    
2558
    @Override
2559
    public FeatureCache getCache() {
2560
        return cache;
2561
    }
2562

    
2563
    @Override
2564
    public void clear() {
2565
        if (metadata != null) {
2566
            metadata.clear();
2567
        }
2568
    }
2569

    
2570
    @Override
2571
    public String getName() {
2572
        if( this.provider != null ) {
2573
            return this.provider.getName();
2574
        }
2575
        if( this.parameters instanceof HasAFile ) {
2576
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2577
        }
2578
        return "unknow";
2579
    }
2580

    
2581
    @Override
2582
    public String getFullName() {
2583
        try {
2584
            if( this.provider!=null ) {
2585
                return this.provider.getFullName();
2586
            }
2587
            if( this.parameters instanceof HasAFile ) {
2588
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2589
            }
2590
            return null;
2591
        } catch(Throwable th) {
2592
            return null;
2593
        }
2594
    }
2595

    
2596
    @Override
2597
    public String getProviderName() {
2598
        if( this.provider!=null ) {
2599
            return this.provider.getProviderName();
2600
        }
2601
        if( this.parameters != null ) {
2602
            return this.parameters.getDataStoreName();
2603
        }
2604
        return null;
2605

    
2606
    }
2607

    
2608
    @Override
2609
    public boolean isKnownEnvelope() {
2610
        return this.provider.isKnownEnvelope();
2611
    }
2612

    
2613
    @Override
2614
    public boolean hasRetrievedFeaturesLimit() {
2615
        return this.provider.hasRetrievedFeaturesLimit();
2616
    }
2617

    
2618
    @Override
2619
    public int getRetrievedFeaturesLimit() {
2620
        return this.provider.getRetrievedFeaturesLimit();
2621
    }
2622

    
2623
    @Override
2624
    public Interval getInterval() {
2625
        if( this.timeSupport!=null ) {
2626
            return this.timeSupport.getInterval();
2627
        }
2628
        return this.provider.getInterval();
2629
    }
2630

    
2631
    @Override
2632
    public Collection getTimes() {
2633
        if( this.timeSupport!=null ) {
2634
            return this.timeSupport.getTimes();
2635
        }
2636
        return this.provider.getTimes();
2637
    }
2638

    
2639
    @Override
2640
    public Collection getTimes(Interval interval) {
2641
        if( this.timeSupport!=null ) {
2642
            return this.timeSupport.getTimes(interval);
2643
        }
2644
        return this.provider.getTimes(interval);
2645
    }
2646

    
2647
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2648
        if( this.isEditing() ) {
2649
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2650
        }
2651
        if( !this.transforms.isEmpty() ) {
2652
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2653
        }
2654
        FeatureType ft = this.defaultFeatureType;
2655
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2656
        if( attr == null ) {
2657
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2658
        }
2659
        EditableFeatureType eft = ft.getEditable();
2660
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2661
        if( attr != null ) {
2662
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2663
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2664
            }
2665
            eft.remove(attr.getName());
2666
        }
2667
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2668
            timeSupport.getAttributeName(), 
2669
            timeSupport.getDataType()
2670
        );
2671
        attrTime.setIsTime(true);
2672
        attrTime.setFeatureAttributeEmulator(timeSupport);
2673
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2674
        this.defaultFeatureType = eft.getNotEditableCopy();
2675
        
2676
        this.timeSupport = timeSupport;
2677
    }
2678

    
2679
    @Override
2680
    @SuppressWarnings("CloneDoesntCallSuperClone")
2681
    public Object clone() throws CloneNotSupportedException {
2682

    
2683
        DataStoreParameters dsp = getParameters();
2684

    
2685
        DefaultFeatureStore cloned_store = null;
2686

    
2687
        try {
2688
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2689
                openStore(this.getProviderName(), dsp);
2690
            if (transforms != null) {
2691
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2692
                cloned_store.transforms.setStoreForClone(cloned_store);
2693
            }
2694
        } catch (Exception e) {
2695
            throw new CloneException(e);
2696
        }
2697
        return cloned_store;
2698

    
2699
    }
2700

    
2701
    @Override
2702
    public Feature getFeature(DynObject dynobject) {
2703
        if (dynobject instanceof DynObjectFeatureFacade){
2704
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2705
            return f;
2706
        }
2707
        return null;
2708
    }
2709

    
2710
    @Override
2711
    public Iterator iterator() {
2712
        try {
2713
            return this.getFeatureSet().fastIterator();
2714
        } catch (DataException ex) {
2715
            throw new RuntimeException(ex);
2716
        }
2717
    }
2718

    
2719
    @Override
2720
    public ExpressionBuilder createExpressionBuilder() {
2721
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2722
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2723
        }
2724
        return new SQLBuilderBase();
2725
    }
2726

    
2727
    @Override
2728
    public ExpressionBuilder createExpression() {
2729
        return createExpressionBuilder();
2730
    }
2731

    
2732
    public FeatureSet features() throws DataException {
2733
        // This is to avoid jython to create a property with this name
2734
        // to access method getFeatures.
2735
        return this.getFeatureSet();
2736
    }
2737

    
2738
    @Override
2739
    public DataStoreProviderFactory getProviderFactory() {
2740
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2741
        return factory;
2742
    }
2743

    
2744
    @Override
2745
    public void useCache(String providerName, DynObject parameters) throws DataException {
2746
        throw new UnsupportedOperationException();
2747
    }
2748

    
2749
    @Override
2750
    public boolean isBroken() {
2751
        return this.state.isBroken();
2752
    }
2753

    
2754
    @Override
2755
    public Throwable getBreakingsCause() {
2756
            return this.state.getBreakingsCause();
2757
    }
2758

    
2759
    @Override
2760
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2761
      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2762
      if( !factory.supportNumericOID() ) {
2763
          return null;
2764
      }
2765
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2766
      return wrappedIndex;
2767
  }
2768

    
2769
    @Override
2770
    public FeatureReference getFeatureReference(String code) {
2771
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2772
        return featureReference;
2773
    }
2774
}