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

History | View | Annotate | Download (91.1 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
    }
310

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

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

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

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

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

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

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

    
345
    public void open() throws OpenException {
346
        if (this.mode != MODE_QUERY) {
347
            // TODO: Se puede hacer un open estando en edicion ?
348
            try {
349
                throw new IllegalStateException();
350
            } catch(Exception ex) {
351
                LOG.warn("Opening a store in editing/append mode ("+this.getFullName()+").",ex);
352
            }
353
        }
354
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
355
        this.provider.open();
356
        loadDALFile();
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
                        featureTypeManager.getFeatureTypesChanged());
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
    @SuppressWarnings("UseSpecificCatch")
1486
    private void saveDALFile() {       
1487
        try {
1488
            DataServerExplorer explorer = this.getExplorer();
1489
            File f = explorer.getResourcePath(this, "dal");
1490
            if( f == null ) {
1491
                return;
1492
            }
1493
            DALFile dalFile = DALFile.getDALFile();
1494
            dalFile.setStore(this);
1495
            if( !dalFile.isEmpty() ) {
1496
                dalFile.write(f);
1497
            }
1498
        } catch (Exception ex) {
1499
            LOG.warn("Can't save DAL File", ex);
1500
        }
1501
    }
1502
    
1503
    @SuppressWarnings("UseSpecificCatch")
1504
    private void loadDALFile() {
1505
        try {
1506
            DataServerExplorer explorer = this.getExplorer();
1507
            File f = explorer.getResourcePath(this, "dal");
1508
            if( f == null ) {
1509
                return;
1510
            }
1511
            DALFile dalFile = DALFile.getDALFile(f);
1512
            if( !dalFile.isEmpty() ) {
1513
                dalFile.updateStore(this);
1514
            }
1515
        } catch (Exception ex) {
1516
            LOG.warn("Can't load DAL File", ex);
1517
        }
1518
    }
1519
    
1520
    /**
1521
     * Save changes in the provider without leaving the edit mode.
1522
     * Do not call observers to communicate a change of ediding mode.
1523
     * The operation's history is eliminated to prevent inconsistencies
1524
     * in the data.
1525
     *
1526
     * @throws DataException
1527
     */
1528
    @Override
1529
    synchronized public void commitChanges() throws DataException {
1530
      LOG.debug("commitChanges of mode: {}", mode);
1531
      if( !canCommitChanges() ) {
1532
              throw new WriteNotAllowedException(getName());
1533
      }
1534
      try {
1535
        switch (mode) {
1536
        case MODE_QUERY:
1537
          throw new NeedEditingModeException(this.getName());
1538

    
1539
        case MODE_APPEND:
1540
          this.provider.endAppend();
1541
          exitEditingMode();
1542
          invalidateIndexes();
1543
          this.provider.beginAppend();
1544
          hasInserts = false;
1545
          break;
1546

    
1547
        case MODE_FULLEDIT:
1548
          if (hasStrongChanges && !this.allowWrite()) {
1549
            throw new WriteNotAllowedException(getName());
1550
          }
1551
          if (hasStrongChanges) {
1552
            validateFeatures(Feature.FINISH_EDITING);
1553
            provider.performChanges(featureManager.getDeleted(),
1554
              featureManager.getInserted(),
1555
              featureManager.getUpdated(),
1556
              featureTypeManager.getFeatureTypesChanged());
1557
          }
1558
          invalidateIndexes();
1559
          featureManager = new FeatureManager();
1560
          featureTypeManager = new FeatureTypeManager(this);
1561
          spatialManager = new SpatialManager(this, provider.getEnvelope());
1562

    
1563
          commands =
1564
            new DefaultFeatureCommandsStack(this, featureManager,
1565
              spatialManager, featureTypeManager);
1566
          featureCount = null;
1567
          hasStrongChanges = false;
1568
          hasInserts = false;
1569
          break;
1570
        }
1571
      } catch (Exception e) {
1572
        throw new FinishEditingException(e);
1573
      }
1574
    }
1575

    
1576
    @Override
1577
    synchronized public boolean canCommitChanges() throws DataException {
1578
        if ( !this.allowWrite()) {
1579
                return false;
1580
        }
1581
            switch (mode) {
1582
            default:
1583
        case MODE_QUERY:
1584
                return false;
1585

    
1586
        case MODE_APPEND:
1587
                return true;
1588

    
1589
        case MODE_FULLEDIT:
1590
            List types = this.getFeatureTypes();
1591
            for( int i=0; i<types.size(); i++ ) {
1592
                    Object type = types.get(i);
1593
                    if( type instanceof DefaultEditableFeatureType ) {
1594
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1595
                                    return false;
1596
                            }
1597
                    }
1598
            }
1599
            return true;
1600
            }
1601
    }
1602

    
1603
    @Override
1604
    public void beginEditingGroup(String description)
1605
        throws NeedEditingModeException {
1606
        checkInEditingMode();
1607
        commands.startComplex(description);
1608
    }
1609

    
1610
    @Override
1611
    public void endEditingGroup() throws NeedEditingModeException {
1612
        checkInEditingMode();
1613
        commands.endComplex();
1614
    }
1615

    
1616
    @Override
1617
    public boolean isAppendModeSupported() {
1618
        return this.provider.supportsAppendMode();
1619
    }
1620

    
1621
    @Override
1622
    public void export(DataServerExplorer explorer, String provider,
1623
        NewFeatureStoreParameters params) throws DataException {
1624

    
1625
        if (this.getFeatureTypes().size() != 1) {
1626
            throw new NotYetImplemented(
1627
                "export whith more than one type not yet implemented");
1628
        }
1629
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1630
        FeatureStore target = null;
1631
        FeatureSet features = null;
1632
        DisposableIterator iterator = null;
1633
        try {
1634
            FeatureType type = this.getDefaultFeatureType();
1635
            if ((params.getDefaultFeatureType() == null)
1636
                || (params.getDefaultFeatureType().size() == 0)) {
1637
                params.setDefaultFeatureType(type.getEditable());
1638

    
1639
            }
1640
            explorer.add(provider, params, true);
1641

    
1642
            DataManager manager = DALLocator.getDataManager();
1643
            target = (FeatureStore) manager.openStore(provider, params);
1644
            FeatureType targetType = target.getDefaultFeatureType();
1645

    
1646
            target.edit(MODE_APPEND);
1647
            FeatureAttributeDescriptor[] pkattrs = type.getPrimaryKey();
1648
            if (featureSelection.getSize() > 0) {
1649
                features = this.getFeatureSelection();
1650
            } else {
1651
                if ((pkattrs != null) && (pkattrs.length > 0)) {
1652
                    FeatureQuery query = createFeatureQuery();
1653
                    for (FeatureAttributeDescriptor pkattr : pkattrs) {
1654
                        query.getOrder().add(pkattr.getName(), true);
1655
                    }
1656
                    features = this.getFeatureSet(query);
1657
                } else {
1658
                    features = this.getFeatureSet();
1659
                }
1660
            }
1661
            iterator = features.fastIterator();
1662
            while (iterator.hasNext()) {
1663
                DefaultFeature feature = (DefaultFeature) iterator.next();
1664
                target.insert(target.createNewFeature(targetType, feature));
1665
            }
1666
            target.finishEditing();
1667
            target.dispose();
1668
        } catch (Exception e) {
1669
            throw new DataExportException(e, params.toString());
1670
        } finally {
1671
            dispose(iterator);
1672
            dispose(features);
1673
            dispose(target);
1674
        }
1675
    }
1676

    
1677
    //
1678
    // ====================================================================
1679
    // Obtencion de datos
1680
    // getDataCollection, getFeatureCollection
1681
    //
1682

    
1683
    @Override
1684
    public DataSet getDataSet() throws DataException {
1685
        checkNotInAppendMode();
1686
        FeatureQuery query =
1687
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1688
        return new DefaultFeatureSet(this, query);
1689
    }
1690

    
1691
    @Override
1692
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1693
        checkNotInAppendMode();
1694
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1695
    }
1696

    
1697
    @Override
1698
    public void getDataSet(Observer observer) throws DataException {
1699
        checkNotInAppendMode();
1700
        this.getFeatureSet(null, observer);
1701
    }
1702

    
1703
    @Override
1704
    public void getDataSet(DataQuery dataQuery, Observer observer)
1705
        throws DataException {
1706
        checkNotInAppendMode();
1707
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1708
    }
1709

    
1710
    @Override
1711
    public FeatureSet getFeatureSet() throws DataException {
1712
        return this.getFeatureSet((FeatureQuery)null);
1713
    }
1714

    
1715
    @Override
1716
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1717
        throws DataException {
1718
        checkNotInAppendMode();
1719
        if( featureQuery==null ) {
1720
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1721
        }
1722
        return new DefaultFeatureSet(this, featureQuery);
1723
    }
1724

    
1725
    @Override
1726
    public FeatureSet getFeatureSet(String filter) throws DataException {
1727
        return this.getFeatureSet(filter, null, true);
1728
    }
1729

    
1730
    @Override
1731
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1732
        return this.getFeatureSet(filter, sortBy, true);
1733
    }
1734

    
1735
    @Override
1736
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1737
        FeatureQuery query = this.createFeatureQuery();
1738
        if( !StringUtils.isEmpty(filter) ) {
1739
            query.setFilter(filter);
1740
        }
1741
        if( !StringUtils.isEmpty(sortBy) ) {
1742
            query.getOrder().add(sortBy, asc);
1743
        }
1744
        return this.getFeatureSet(query);
1745
    }
1746
    
1747
    @Override
1748
    public List<Feature> getFeatures(String filter)  {
1749
        return this.getFeatures(filter, null, true);
1750
    }
1751

    
1752
    @Override
1753
    public List<Feature> getFeatures(String filter, String sortBy)  {
1754
        return this.getFeatures(filter, sortBy, true);
1755
    }
1756

    
1757
    @Override
1758
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1759
        FeatureQuery query = this.createFeatureQuery();
1760
        if( !StringUtils.isEmpty(filter) ) {
1761
            query.setFilter(filter);
1762
        }
1763
        if( !StringUtils.isEmpty(sortBy) ) {
1764
            query.getOrder().add(sortBy, asc);
1765
        }
1766
        return this.getFeatures(query, 100);
1767
    }
1768
    
1769
    @Override
1770
    public List<Feature> getFeatures(FeatureQuery query)  {
1771
        return this.getFeatures(query, 100);
1772
    }
1773
    
1774
    @Override
1775
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1776
        try {
1777
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1778
            return pager.asList();
1779
        } catch (BaseException ex) {
1780
            throw new RuntimeException("Can't create the list of features.", ex);
1781
        }
1782
    }
1783

    
1784
    @Override
1785
    public List<Feature> getFeatures() {
1786
        return this.getFeatures(null, 500);
1787
    }
1788

    
1789
    @Override
1790
    public Feature findFirst(String filter) throws DataException {
1791
        return this.findFirst(filter, null, true);
1792
    }
1793

    
1794
    @Override
1795
    public Feature findFirst(String filter, String sortBy) throws DataException {
1796
        return this.findFirst(filter, sortBy, true);
1797
    }
1798

    
1799
    @Override
1800
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1801
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1802
        if( set==null || set.isEmpty() ) {
1803
            return null;
1804
        }
1805
        DisposableIterator it = set.iterator();
1806
        Feature f = (Feature) it.next();
1807
        it.dispose();
1808
        return f;
1809
    }
1810
    
1811
    @Override
1812
    public void accept(Visitor visitor) throws BaseException {
1813
        FeatureSet set = getFeatureSet();
1814
        try {
1815
            set.accept(visitor);
1816
        } finally {
1817
            set.dispose();
1818
        }
1819
    }
1820

    
1821
    @Override
1822
    public void accept(Visitor visitor, DataQuery dataQuery)
1823
        throws BaseException {
1824
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1825
        try {
1826
            set.accept(visitor);
1827
        } finally {
1828
            set.dispose();
1829
        }
1830
    }
1831

    
1832
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1833
        throws DataException {
1834
        DefaultFeatureType fType =
1835
            (DefaultFeatureType) this.getFeatureType(featureQuery
1836
                .getFeatureTypeId());
1837
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1838
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1839
        }
1840
        return fType;
1841
    }
1842

    
1843
    @Override
1844
    public void getFeatureSet(Observer observer) throws DataException {
1845
        checkNotInAppendMode();
1846
        this.getFeatureSet(null, observer);
1847
    }
1848

    
1849
    @Override
1850
    public void getFeatureSet(FeatureQuery query, Observer observer)
1851
        throws DataException {
1852
        class LoadInBackGround implements Runnable {
1853

    
1854
            private final FeatureStore store;
1855
            private final FeatureQuery query;
1856
            private final Observer observer;
1857

    
1858
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1859
                Observer observer) {
1860
                this.store = store;
1861
                this.query = query;
1862
                this.observer = observer;
1863
            }
1864

    
1865
            void notify(FeatureStoreNotification theNotification) {
1866
                observer.update(store, theNotification);
1867
            }
1868

    
1869
            @Override
1870
            public void run() {
1871
                FeatureSet set = null;
1872
                try {
1873
                    set = store.getFeatureSet(query);
1874
                    notify(new DefaultFeatureStoreNotification(store,
1875
                        FeatureStoreNotification.LOAD_FINISHED, set));
1876
                } catch (Exception e) {
1877
                    notify(new DefaultFeatureStoreNotification(store,
1878
                        FeatureStoreNotification.LOAD_FINISHED, e));
1879
                } finally {
1880
                    dispose(set);
1881
                }
1882
            }
1883
        }
1884

    
1885
        checkNotInAppendMode();
1886
        if (query == null) {
1887
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1888
        }
1889
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1890
        Thread thread = new Thread(task, "Load Feature Set in background");
1891
        thread.start();
1892
    }
1893

    
1894
    @Override
1895
    public Feature getFeatureByReference(FeatureReference reference)
1896
        throws DataException {
1897
        checkNotInAppendMode();
1898
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1899
        FeatureType featureType;
1900
        if (ref.getFeatureTypeId() == null) {
1901
            featureType = this.getDefaultFeatureType();
1902
        } else {
1903
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1904
        }
1905
        return this.getFeatureByReference(reference, featureType);
1906
    }
1907

    
1908
    @Override
1909
    public Feature getFeatureByReference(FeatureReference reference,
1910
        FeatureType featureType) throws DataException {
1911
        checkNotInAppendMode();
1912
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1913
        if (this.mode == MODE_FULLEDIT) {
1914
            Feature f = featureManager.get(reference, this, featureType);
1915
            if (f != null) {
1916
                return f;
1917
            }
1918
        }
1919

    
1920
        FeatureType sourceFeatureType = featureType;
1921
        if (!this.transforms.isEmpty()) {
1922
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1923
        }
1924
        // TODO comprobar que el id es de este store
1925

    
1926
        DefaultFeature feature =
1927
            new DefaultFeature(this,
1928
                this.provider.getFeatureProviderByReference(
1929
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1930

    
1931
        if (!this.transforms.isEmpty()) {
1932
            return this.transforms.applyTransform(feature, featureType);
1933
        }
1934
        return feature;
1935
    }
1936

    
1937
    //
1938
    // ====================================================================
1939
    // Gestion de features
1940
    //
1941

    
1942
    private FeatureType fixFeatureType(DefaultFeatureType type)
1943
        throws DataException {
1944
        FeatureType original = this.getDefaultFeatureType();
1945

    
1946
        if ((type == null) || type.equals(original)) {
1947
            return original;
1948
        } else {
1949
            if (!type.isSubtypeOf(original)) {
1950
                Iterator iter = this.getFeatureTypes().iterator();
1951
                FeatureType tmpType;
1952
                boolean found = false;
1953
                while (iter.hasNext()) {
1954
                    tmpType = (FeatureType) iter.next();
1955
                    if (type.equals(tmpType)) {
1956
                        return type;
1957

    
1958
                    } else
1959
                        if (type.isSubtypeOf(tmpType)) {
1960
                            found = true;
1961
                            original = tmpType;
1962
                            break;
1963
                        }
1964

    
1965
                }
1966
                if (!found) {
1967
                    throw new IllegalFeatureTypeException(getName());
1968
                }
1969
            }
1970
        }
1971

    
1972
        // Checks that type has all fields of pk
1973
        // else add the missing attributes at the end.
1974
        if (!original.hasOID()) {
1975
            // Gets original pk attributes
1976
            DefaultEditableFeatureType edOriginal =
1977
                (DefaultEditableFeatureType) original.getEditable();
1978
            FeatureAttributeDescriptor orgAttr;
1979
            Iterator edOriginalIter = edOriginal.iterator();
1980
            while (edOriginalIter.hasNext()) {
1981
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1982
                if (!orgAttr.isPrimaryKey()) {
1983
                    edOriginalIter.remove();
1984
                }
1985
            }
1986

    
1987
            // Checks if all pk attributes are in type
1988
            Iterator typeIterator;
1989
            edOriginalIter = edOriginal.iterator();
1990
            FeatureAttributeDescriptor attr;
1991
            while (edOriginalIter.hasNext()) {
1992
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1993
                typeIterator = type.iterator();
1994
                while (typeIterator.hasNext()) {
1995
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1996
                    if (attr.getName().equals(orgAttr.getName())) {
1997
                        edOriginalIter.remove();
1998
                        break;
1999
                    }
2000
                }
2001
            }
2002

    
2003
            // add missing pk attributes if any
2004
            if (edOriginal.size() > 0) {
2005
                boolean isEditable = type instanceof DefaultEditableFeatureType;
2006
                DefaultEditableFeatureType edType =
2007
                    (DefaultEditableFeatureType) original.getEditable();
2008
                edType.clear();
2009
                edType.addAll(type);
2010
                edType.addAll(edOriginal);
2011
                if (!isEditable) {
2012
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
2013
                }
2014
            }
2015

    
2016
        }
2017

    
2018
        return type;
2019
    }
2020

    
2021
    @Override
2022
    public void validateFeatures(int mode) throws DataException {
2023
        FeatureSet collection = null;
2024
        DisposableIterator iter = null;
2025
        try {
2026
            FeatureRules rules = this.getDefaultFeatureType().getRules();
2027
            if( rules==null || rules.isEmpty() ) {
2028
                return;
2029
            }
2030
            checkNotInAppendMode();
2031
            collection = this.getFeatureSet();
2032
            iter = collection.fastIterator();
2033
            long previousVersionOfUpdate = currentVersionOfUpdate();
2034
            while (iter.hasNext()) {
2035
                ((DefaultFeature) iter.next()).validate(mode);
2036
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
2037
                    throw new ConcurrentDataModificationException(getName());
2038
                }
2039
            }
2040
        } catch (Exception e) {
2041
            throw new ValidateFeaturesException(e, getName());
2042
        } finally {
2043
            DisposeUtils.disposeQuietly(iter);
2044
            DisposeUtils.disposeQuietly(collection);
2045
        }
2046
    }
2047

    
2048
    @Override
2049
    public FeatureType getDefaultFeatureType() throws DataException {
2050
        try {
2051

    
2052
            if (isEditing()) {
2053
                FeatureType auxFeatureType =
2054
                    featureTypeManager.getType(defaultFeatureType.getId());
2055
                if (auxFeatureType != null) {
2056
                    return avoidEditable(auxFeatureType);
2057
                }
2058
            }
2059
            FeatureType type = this.transforms.getDefaultFeatureType();
2060
            if (type != null) {
2061
                return avoidEditable(type);
2062
            }
2063

    
2064
            return avoidEditable(defaultFeatureType);
2065

    
2066
        } catch (Exception e) {
2067
            throw new GetFeatureTypeException(e, getName());
2068
        }
2069
    }
2070

    
2071
    private FeatureType avoidEditable(FeatureType ft) {
2072
        if (ft instanceof EditableFeatureType) {
2073
            return ((EditableFeatureType) ft).getNotEditableCopy();
2074
        } else {
2075
            return ft;
2076
        }
2077
    }
2078

    
2079
    @Override
2080
    public FeatureType getFeatureType(String featureTypeId)
2081
        throws DataException {
2082
        if (featureTypeId == null) {
2083
            return this.getDefaultFeatureType();
2084
        }
2085
        try {
2086
            if (isEditing()) {
2087
                FeatureType auxFeatureType =
2088
                    featureTypeManager.getType(featureTypeId);
2089
                if (auxFeatureType != null) {
2090
                    return auxFeatureType;
2091
                }
2092
            }
2093
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2094
            if (type != null) {
2095
                return type;
2096
            }
2097
            Iterator iter = this.featureTypes.iterator();
2098
            while (iter.hasNext()) {
2099
                type = (FeatureType) iter.next();
2100
                if (type.getId().equals(featureTypeId)) {
2101
                    return type;
2102
                }
2103
            }
2104
            return null;
2105
        } catch (Exception e) {
2106
            throw new GetFeatureTypeException(e, getName());
2107
        }
2108
    }
2109

    
2110
    public FeatureType getProviderDefaultFeatureType() {
2111
        return defaultFeatureType;
2112
    }
2113

    
2114
    @Override
2115
    public List getFeatureTypes() throws DataException {
2116
        try {
2117
            List types;
2118
            if (isEditing()) {
2119
                types = new ArrayList();
2120
                Iterator it = featureTypes.iterator();
2121
                while (it.hasNext()) {
2122
                    FeatureType type = (FeatureType) it.next();
2123
                    FeatureType typeaux =
2124
                        featureTypeManager.getType(type.getId());
2125
                    if (typeaux != null) {
2126
                        types.add(typeaux);
2127
                    } else {
2128
                        types.add(type);
2129
                    }
2130
                }
2131
                it = featureTypeManager.newsIterator();
2132
                while (it.hasNext()) {
2133
                    FeatureType type = (FeatureType) it.next();
2134
                    types.add(type);
2135
                }
2136
            } else {
2137
                types = this.transforms.getFeatureTypes();
2138
                if (types == null) {
2139
                    types = featureTypes;
2140
                }
2141
            }
2142
            return Collections.unmodifiableList(types);
2143
        } catch (Exception e) {
2144
            throw new GetFeatureTypeException(e, getName());
2145
        }
2146
    }
2147

    
2148
    public List getProviderFeatureTypes() throws DataException {
2149
        return Collections.unmodifiableList(this.featureTypes);
2150
    }
2151

    
2152
    @Override
2153
    public Feature createFeature(FeatureProvider data) throws DataException {
2154
        DefaultFeature feature = new DefaultFeature(this, data);
2155
        return feature;
2156
    }
2157

    
2158
    public Feature createFeature(FeatureProvider data, FeatureType type)
2159
        throws DataException {
2160
        // FIXME: falta por implementar
2161
        // Comprobar si es un subtipo del feature de data
2162
        // y construir un feature usando el subtipo.
2163
        // Probablemente requiera generar una copia del data.
2164
        throw new NotYetImplemented();
2165
    }
2166

    
2167
    @Override
2168
    public EditableFeature createNewFeature(FeatureType type,
2169
        Feature defaultValues) throws DataException {
2170
        try {
2171
            FeatureProvider data = createNewFeatureProvider(type);
2172
            DefaultEditableFeature feature =
2173
                new DefaultEditableFeature(this, data);
2174
            feature.initializeValues(defaultValues);
2175
            data.setNew(true);
2176

    
2177
            return feature;
2178
        } catch (Exception e) {
2179
            throw new CreateFeatureException(e, getName());
2180
        }
2181
    }
2182

    
2183
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2184
        throws DataException {
2185
        type = this.fixFeatureType((DefaultFeatureType) type);
2186
        FeatureProvider data = this.provider.createFeatureProvider(type);
2187
        data.setNew(true);
2188
        if (type.hasOID() && (data.getOID() == null)) {
2189
            data.setOID(this.provider.createNewOID());
2190
        } else {
2191
            data.setOID(this.getTemporalOID());
2192
        }
2193
        return data;
2194

    
2195
    }
2196

    
2197
    @Override
2198
    public EditableFeature createNewFeature(FeatureType type,
2199
        boolean defaultValues) throws DataException {
2200
        try {
2201
            FeatureProvider data = createNewFeatureProvider(type);
2202
            DefaultEditableFeature feature =
2203
                new DefaultEditableFeature(this, data);
2204
            if (defaultValues) {
2205
                feature.initializeValues();
2206
            }
2207
            return feature;
2208
        } catch (Exception e) {
2209
            throw new CreateFeatureException(e, getName());
2210
        }
2211
    }
2212

    
2213
    @Override
2214
    public EditableFeature createNewFeature(boolean defaultValues)
2215
        throws DataException {
2216
        return this.createNewFeature(this.getDefaultFeatureType(),
2217
            defaultValues);
2218
    }
2219

    
2220
    @Override
2221
    public EditableFeature createNewFeature() throws DataException {
2222
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2223
    }
2224

    
2225
    @Override
2226
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2227
        FeatureType ft = this.getDefaultFeatureType();
2228
        EditableFeature f = this.createNewFeature(ft, false);
2229
                for( FeatureAttributeDescriptor desc : ft ) {
2230
                        try {
2231
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2232
                        } catch(Throwable th) {
2233
                                // Ignore
2234
                        }
2235
                }
2236
        return f;
2237
    }
2238

    
2239
    @Override
2240
    public EditableFeatureType createFeatureType() {
2241
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2242
        return ftype;
2243
    }
2244

    
2245
    @Override
2246
    public EditableFeatureType createFeatureType(String id) {
2247
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2248
        return ftype;
2249
    }
2250

    
2251
    //
2252
    // ====================================================================
2253
    // Index related methods
2254
    //
2255

    
2256
    @Override
2257
    public FeatureIndexes getIndexes() {
2258
        return this.indexes;
2259
    }
2260

    
2261
    @Override
2262
    public FeatureIndex createIndex(FeatureType featureType,
2263
        String attributeName, String indexName) throws DataException {
2264
        return createIndex(null, featureType, attributeName, indexName);
2265
    }
2266

    
2267
    @Override
2268
    public FeatureIndex createIndex(String indexTypeName,
2269
        FeatureType featureType, String attributeName, String indexName)
2270
        throws DataException {
2271

    
2272
        return createIndex(indexTypeName, featureType, attributeName,
2273
            indexName, false, null);
2274
    }
2275

    
2276
    @Override
2277
    public FeatureIndex createIndex(FeatureType featureType,
2278
        String attributeName, String indexName, Observer observer)
2279
        throws DataException {
2280
        return createIndex(null, featureType, attributeName, indexName,
2281
            observer);
2282
    }
2283

    
2284
    @Override
2285
    public FeatureIndex createIndex(String indexTypeName,
2286
        FeatureType featureType, String attributeName, String indexName,
2287
        final Observer observer) throws DataException {
2288

    
2289
        return createIndex(indexTypeName, featureType, attributeName,
2290
            indexName, true, observer);
2291
    }
2292

    
2293
    private FeatureIndex createIndex(String indexTypeName,
2294
        FeatureType featureType, String attributeName, String indexName,
2295
        boolean background, final Observer observer) throws DataException {
2296

    
2297
        checkNotInAppendMode();
2298
        FeatureIndexProviderServices index;
2299
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2300
                featureType, indexName,
2301
                featureType.getAttributeDescriptor(attributeName));
2302

    
2303
        try {
2304
            index.fill(background, observer);
2305
        } catch (FeatureIndexException e) {
2306
            throw new InitializeException(index.getName(), e);
2307
        }
2308

    
2309
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2310
        return index;
2311
    }
2312

    
2313
    //
2314
    // ====================================================================
2315
    // Transforms related methods
2316
    //
2317

    
2318
    @Override
2319
    public FeatureStoreTransforms getTransforms() {
2320
        return this.transforms;
2321
    }
2322

    
2323
    @Override
2324
    public FeatureQuery createFeatureQuery() {
2325
        return new DefaultFeatureQuery();
2326
    }
2327

    
2328
    @Override
2329
    public DataQuery createQuery() {
2330
        return createFeatureQuery();
2331
    }
2332

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

    
2338
    @Override
2339
    public boolean canRedo() {
2340
        return commands.canRedo();
2341
    }
2342

    
2343
    @Override
2344
    public boolean canUndo() {
2345
        return commands.canUndo();
2346
    }
2347

    
2348
    @Override
2349
    public void redo(int num) throws RedoException {
2350
        for (int i = 0; i < num; i++) {
2351
            redo();
2352
        }
2353
    }
2354

    
2355
    @Override
2356
    public void undo(int num) throws UndoException {
2357
        for (int i = 0; i < num; i++) {
2358
            undo();
2359
        }
2360
    }
2361

    
2362
    //
2363
    // ====================================================================
2364
    // Metadata related methods
2365
    //
2366

    
2367
    @Override
2368
    public Object getMetadataID() {
2369
        return this.provider.getSourceId();
2370
    }
2371

    
2372
    @Override
2373
    public void delegate(DynObject dynObject) {
2374
        this.metadata.delegate(dynObject);
2375
    }
2376

    
2377
    @Override
2378
    public DynClass getDynClass() {
2379
        return this.metadata.getDynClass();
2380
    }
2381

    
2382
    @Override
2383
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2384
                if( this.transforms.hasDynValue(name) ) {
2385
                        return this.transforms.getDynValue(name);
2386
                }
2387
                if (this.metadata.hasDynValue(name)) {
2388
                        return this.metadata.getDynValue(name);
2389
                }
2390
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2391
                        return this.provider.getProviderName();
2392
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2393
                        return this.provider.getSourceId();
2394
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2395
                        try {
2396
                                return this.getDefaultFeatureType();
2397
                        } catch (DataException e) {
2398
                                return null;
2399
                        }
2400
                }
2401
                return this.metadata.getDynValue(name);
2402
        }
2403

    
2404
    @Override
2405
    public boolean hasDynValue(String name) {
2406
                if( this.transforms.hasDynValue(name) ) {
2407
                        return true;
2408
                }
2409
        return this.metadata.hasDynValue(name);
2410
    }
2411

    
2412
    @Override
2413
    public boolean hasDynMethod(String name) {
2414
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2415
    }
2416

    
2417
    @Override
2418
    public void implement(DynClass dynClass) {
2419
        this.metadata.implement(dynClass);
2420
    }
2421

    
2422
    @Override
2423
    public Object invokeDynMethod(String name, Object[] args)
2424
        throws DynMethodException {
2425
        return this.metadata.invokeDynMethod(this, name, args);
2426
    }
2427

    
2428
    @Override
2429
    public Object invokeDynMethod(int code, Object[] args)
2430
        throws DynMethodException {
2431
        return this.metadata.invokeDynMethod(this, code, args);
2432
    }
2433

    
2434
    @Override
2435
    public void setDynValue(String name, Object value)
2436
        throws DynFieldNotFoundException {
2437
                if( this.transforms.hasDynValue(name) ) {
2438
                        this.transforms.setDynValue(name, value);
2439
                        return;
2440
                }
2441
        this.metadata.setDynValue(name, value);
2442

    
2443
    }
2444

    
2445
    /*
2446
     * (non-Javadoc)
2447
     *
2448
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2449
     */
2450
    @Override
2451
    public Set getMetadataChildren() {
2452
        return this.metadataChildren;
2453
    }
2454

    
2455
    /*
2456
     * (non-Javadoc)
2457
     *
2458
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2459
     */
2460
    @Override
2461
    public String getMetadataName() {
2462
        return this.provider.getProviderName();
2463
    }
2464

    
2465
    public FeatureTypeManager getFeatureTypeManager() {
2466
        return this.featureTypeManager;
2467
    }
2468

    
2469
    @Override
2470
    public long getFeatureCount() throws DataException {
2471
        if (featureCount == null) {
2472
            featureCount = this.provider.getFeatureCount();
2473
        }
2474
        if (this.isEditing()) {
2475
            if(this.isAppending()) {
2476
                try{
2477
                    throw new IllegalStateException();
2478
                } catch(IllegalStateException e) {
2479
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND",e);
2480
                }
2481
                return -1;
2482
            } else {
2483
                return featureCount
2484
                    + this.featureManager.getDeltaSize();
2485
            }
2486
        }
2487
        return featureCount;
2488
    }
2489

    
2490
    private Long getTemporalOID() {
2491
        return this.temporalOid++;
2492
    }
2493

    
2494
    @Override
2495
    public FeatureType getProviderFeatureType(String featureTypeId) {
2496
        if (featureTypeId == null) {
2497
            return this.defaultFeatureType;
2498
        }
2499
        FeatureType type;
2500
        Iterator iter = this.featureTypes.iterator();
2501
        while (iter.hasNext()) {
2502
            type = (FeatureType) iter.next();
2503
            if (type.getId().equals(featureTypeId)) {
2504
                return type;
2505
            }
2506
        }
2507
        return null;
2508
    }
2509

    
2510
    @Override
2511
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2512
        return ((DefaultFeature) feature).getData();
2513
    }
2514

    
2515
    @Override
2516
    public DataStore getStore() {
2517
        return this;
2518
    }
2519

    
2520
    @Override
2521
    public FeatureStore getFeatureStore() {
2522
        return this;
2523
    }
2524

    
2525
    @Override
2526
    public void createCache(String name, DynObject parameters)
2527
        throws DataException {
2528
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2529
        if (cache == null) {
2530
            throw new CreateException("FeaureCacheProvider", null);
2531
        }
2532
        cache.apply(this, provider);
2533
        provider = cache;
2534

    
2535
        featureCount = null;
2536
    }
2537

    
2538
    @Override
2539
    public FeatureCache getCache() {
2540
        return cache;
2541
    }
2542

    
2543
    @Override
2544
    public void clear() {
2545
        if (metadata != null) {
2546
            metadata.clear();
2547
        }
2548
    }
2549

    
2550
    @Override
2551
    public String getName() {
2552
        if( this.provider != null ) {
2553
            return this.provider.getName();
2554
        }
2555
        if( this.parameters instanceof HasAFile ) {
2556
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2557
        }
2558
        return "unknow";
2559
    }
2560

    
2561
    @Override
2562
    public String getFullName() {
2563
        try {
2564
            if( this.provider!=null ) {
2565
                return this.provider.getFullName();
2566
            }
2567
            if( this.parameters instanceof HasAFile ) {
2568
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2569
            }
2570
            return null;
2571
        } catch(Throwable th) {
2572
            return null;
2573
        }
2574
    }
2575

    
2576
    @Override
2577
    public String getProviderName() {
2578
        if( this.provider!=null ) {
2579
            return this.provider.getProviderName();
2580
        }
2581
        if( this.parameters != null ) {
2582
            return this.parameters.getDataStoreName();
2583
        }
2584
        return null;
2585

    
2586
    }
2587

    
2588
    @Override
2589
    public boolean isKnownEnvelope() {
2590
        return this.provider.isKnownEnvelope();
2591
    }
2592

    
2593
    @Override
2594
    public boolean hasRetrievedFeaturesLimit() {
2595
        return this.provider.hasRetrievedFeaturesLimit();
2596
    }
2597

    
2598
    @Override
2599
    public int getRetrievedFeaturesLimit() {
2600
        return this.provider.getRetrievedFeaturesLimit();
2601
    }
2602

    
2603
    @Override
2604
    public Interval getInterval() {
2605
        if( this.timeSupport!=null ) {
2606
            return this.timeSupport.getInterval();
2607
        }
2608
        return this.provider.getInterval();
2609
    }
2610

    
2611
    @Override
2612
    public Collection getTimes() {
2613
        if( this.timeSupport!=null ) {
2614
            return this.timeSupport.getTimes();
2615
        }
2616
        return this.provider.getTimes();
2617
    }
2618

    
2619
    @Override
2620
    public Collection getTimes(Interval interval) {
2621
        if( this.timeSupport!=null ) {
2622
            return this.timeSupport.getTimes(interval);
2623
        }
2624
        return this.provider.getTimes(interval);
2625
    }
2626

    
2627
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2628
        if( this.isEditing() ) {
2629
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2630
        }
2631
        if( !this.transforms.isEmpty() ) {
2632
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2633
        }
2634
        FeatureType ft = this.defaultFeatureType;
2635
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2636
        if( attr == null ) {
2637
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2638
        }
2639
        EditableFeatureType eft = ft.getEditable();
2640
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2641
        if( attr != null ) {
2642
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2643
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2644
            }
2645
            eft.remove(attr.getName());
2646
        }
2647
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2648
            timeSupport.getAttributeName(), 
2649
            timeSupport.getDataType()
2650
        );
2651
        attrTime.setIsTime(true);
2652
        attrTime.setFeatureAttributeEmulator(timeSupport);
2653
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2654
        this.defaultFeatureType = eft.getNotEditableCopy();
2655
        
2656
        this.timeSupport = timeSupport;
2657
    }
2658

    
2659
    @Override
2660
    @SuppressWarnings("CloneDoesntCallSuperClone")
2661
    public Object clone() throws CloneNotSupportedException {
2662

    
2663
        DataStoreParameters dsp = getParameters();
2664

    
2665
        DefaultFeatureStore cloned_store = null;
2666

    
2667
        try {
2668
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2669
                openStore(this.getProviderName(), dsp);
2670
            if (transforms != null) {
2671
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2672
                cloned_store.transforms.setStoreForClone(cloned_store);
2673
            }
2674
        } catch (Exception e) {
2675
            throw new CloneException(e);
2676
        }
2677
        return cloned_store;
2678

    
2679
    }
2680

    
2681
    @Override
2682
    public Feature getFeature(DynObject dynobject) {
2683
        if (dynobject instanceof DynObjectFeatureFacade){
2684
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2685
            return f;
2686
        }
2687
        return null;
2688
    }
2689

    
2690
    @Override
2691
    public Iterator iterator() {
2692
        try {
2693
            return this.getFeatureSet().fastIterator();
2694
        } catch (DataException ex) {
2695
            throw new RuntimeException(ex);
2696
        }
2697
    }
2698

    
2699
    @Override
2700
    public ExpressionBuilder createExpressionBuilder() {
2701
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2702
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2703
        }
2704
        return new SQLBuilderBase();
2705
    }
2706

    
2707
    @Override
2708
    public ExpressionBuilder createExpression() {
2709
        return createExpressionBuilder();
2710
    }
2711

    
2712
    public FeatureSet features() throws DataException {
2713
        // This is to avoid jython to create a property with this name
2714
        // to access method getFeatures.
2715
        return this.getFeatureSet();
2716
    }
2717

    
2718
    @Override
2719
    public DataStoreProviderFactory getProviderFactory() {
2720
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2721
        return factory;
2722
    }
2723

    
2724
    @Override
2725
    public void useCache(String providerName, DynObject parameters) throws DataException {
2726
        throw new UnsupportedOperationException();
2727
    }
2728

    
2729
    @Override
2730
    public boolean isBroken() {
2731
        return this.state.isBroken();
2732
    }
2733

    
2734
    @Override
2735
    public Throwable getBreakingsCause() {
2736
            return this.state.getBreakingsCause();
2737
    }
2738

    
2739
    @Override
2740
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2741
      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2742
      if( !factory.supportNumericOID() ) {
2743
          return null;
2744
      }
2745
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2746
      return wrappedIndex;
2747
  }
2748

    
2749
    @Override
2750
    public FeatureReference getFeatureReference(String code) {
2751
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2752
        return featureReference;
2753
    }
2754
}