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

History | View | Annotate | Download (94.6 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6 42293 jjdelcerro
 * 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 40435 jjdelcerro
 *
11 42293 jjdelcerro
 * 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 40435 jjdelcerro
 *
16 42293 jjdelcerro
 * 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 40435 jjdelcerro
 *
21 42293 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
24 42293 jjdelcerro
25 40435 jjdelcerro
package org.gvsig.fmap.dal.feature.impl;
26
27 43954 jjdelcerro
import java.io.File;
28 43840 jjdelcerro
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 43020 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
32 43152 fdiaz
33 40435 jjdelcerro
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 43954 jjdelcerro
import java.util.logging.Level;
44 43981 omartinez
import org.apache.commons.collections4.ListUtils;
45 43371 fdiaz
46 43215 jjdelcerro
import org.apache.commons.io.FilenameUtils;
47 43533 jjdelcerro
import org.apache.commons.lang3.StringUtils;
48 40435 jjdelcerro
import org.cresques.cts.IProjection;
49 43152 fdiaz
50 40435 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
51
import org.gvsig.fmap.dal.DataManager;
52
import org.gvsig.fmap.dal.DataQuery;
53
import org.gvsig.fmap.dal.DataServerExplorer;
54
import org.gvsig.fmap.dal.DataSet;
55
import org.gvsig.fmap.dal.DataStore;
56
import org.gvsig.fmap.dal.DataStoreNotification;
57
import org.gvsig.fmap.dal.DataStoreParameters;
58 43152 fdiaz
import org.gvsig.fmap.dal.DataStoreProviderFactory;
59 43521 jjdelcerro
import org.gvsig.fmap.dal.ExpressionBuilder;
60 40435 jjdelcerro
import org.gvsig.fmap.dal.exception.CloneException;
61
import org.gvsig.fmap.dal.exception.CloseException;
62
import org.gvsig.fmap.dal.exception.CreateException;
63
import org.gvsig.fmap.dal.exception.DataException;
64
import org.gvsig.fmap.dal.exception.InitializeException;
65
import org.gvsig.fmap.dal.exception.OpenException;
66
import org.gvsig.fmap.dal.exception.ReadException;
67
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
68 40597 jldominguez
import org.gvsig.fmap.dal.exception.WriteException;
69 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
70 43610 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
71 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
72
import org.gvsig.fmap.dal.feature.Feature;
73
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
74 43981 omartinez
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
75 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureCache;
76
import org.gvsig.fmap.dal.feature.FeatureIndex;
77
import org.gvsig.fmap.dal.feature.FeatureIndexes;
78
import org.gvsig.fmap.dal.feature.FeatureLocks;
79
import org.gvsig.fmap.dal.feature.FeatureQuery;
80
import org.gvsig.fmap.dal.feature.FeatureReference;
81
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
82 43642 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureRules;
83 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSelection;
84
import org.gvsig.fmap.dal.feature.FeatureSet;
85
import org.gvsig.fmap.dal.feature.FeatureStore;
86
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
87 43705 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
88 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
89
import org.gvsig.fmap.dal.feature.FeatureType;
90
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
91 43135 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreTimeSupport;
92 43215 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreTransform;
93 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
94
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
95
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
96
import org.gvsig.fmap.dal.feature.exception.DataExportException;
97
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
98
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
99
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
100
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
101
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
102
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
103
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
104
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
105 40597 jldominguez
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
106 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindFeatureTypeException;
107
import org.gvsig.fmap.dal.feature.exception.PersistenceStoreAlreadyLoadedException;
108
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
109
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
110
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
111
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
112
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
113
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
114
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
115
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
116
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
117
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
118
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
119 42775 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
120 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
121
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
122 42925 jjdelcerro
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
123 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
124
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
125
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
126
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
127
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
128 43020 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider_v2;
129 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.cache.FeatureCacheProvider;
130
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
131
import org.gvsig.fmap.dal.impl.DefaultDataManager;
132
import org.gvsig.fmap.dal.resource.Resource;
133 43020 jjdelcerro
import org.gvsig.fmap.dal.spi.DataStoreInitializer2;
134 40435 jjdelcerro
import org.gvsig.fmap.dal.spi.DataStoreProvider;
135 43020 jjdelcerro
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
136 43358 jjdelcerro
import org.gvsig.fmap.geom.SpatialIndex;
137 40435 jjdelcerro
import org.gvsig.fmap.geom.primitive.Envelope;
138
import org.gvsig.metadata.MetadataLocator;
139
import org.gvsig.metadata.MetadataManager;
140
import org.gvsig.metadata.exceptions.MetadataException;
141
import org.gvsig.timesupport.Interval;
142
import org.gvsig.tools.ToolsLocator;
143
import org.gvsig.tools.dispose.DisposableIterator;
144 43642 jjdelcerro
import org.gvsig.tools.dispose.DisposeUtils;
145 40435 jjdelcerro
import org.gvsig.tools.dispose.impl.AbstractDisposable;
146
import org.gvsig.tools.dynobject.DelegatedDynObject;
147
import org.gvsig.tools.dynobject.DynClass;
148
import org.gvsig.tools.dynobject.DynObject;
149
import org.gvsig.tools.dynobject.DynObjectManager;
150 43246 jjdelcerro
import org.gvsig.tools.dynobject.DynObject_v2;
151 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynStruct;
152
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
153
import org.gvsig.tools.dynobject.exception.DynMethodException;
154
import org.gvsig.tools.exception.BaseException;
155
import org.gvsig.tools.exception.NotYetImplemented;
156 41928 jjdelcerro
import org.gvsig.tools.identitymanagement.SimpleIdentityManager;
157 40435 jjdelcerro
import org.gvsig.tools.observer.Observable;
158
import org.gvsig.tools.observer.Observer;
159
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
160
import org.gvsig.tools.persistence.PersistenceManager;
161
import org.gvsig.tools.persistence.Persistent;
162
import org.gvsig.tools.persistence.PersistentState;
163
import org.gvsig.tools.persistence.exception.PersistenceException;
164
import org.gvsig.tools.undo.RedoException;
165
import org.gvsig.tools.undo.UndoException;
166
import org.gvsig.tools.undo.command.Command;
167 43215 jjdelcerro
import org.gvsig.tools.util.HasAFile;
168 40435 jjdelcerro
import org.gvsig.tools.visitor.Visitor;
169 43152 fdiaz
170 42533 dmartinezizquierdo
import org.slf4j.Logger;
171
import org.slf4j.LoggerFactory;
172 40435 jjdelcerro
173 41243 jjdelcerro
public class DefaultFeatureStore extends AbstractDisposable implements
174 43020 jjdelcerro
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
175 40435 jjdelcerro
176
    private static final Logger LOG = LoggerFactory
177 42293 jjdelcerro
        .getLogger(DefaultFeatureStore.class);
178 40435 jjdelcerro
179
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
180
181
    private DataStoreParameters parameters = null;
182
    private FeatureSelection selection;
183
    private FeatureLocks locks;
184
185 42293 jjdelcerro
    private DelegateWeakReferencingObservable delegateObservable =
186
        new DelegateWeakReferencingObservable(this);
187 40435 jjdelcerro
188
    private FeatureCommandsStack commands;
189 43841 jjdelcerro
190
    /*
191
    TODO: Sustituir estos tres manager por un EditingManager
192
    */
193 40435 jjdelcerro
    private FeatureTypeManager featureTypeManager;
194
    private FeatureManager featureManager;
195
    private SpatialManager spatialManager;
196
197
    private FeatureType defaultFeatureType = null;
198
    private List featureTypes = new ArrayList();
199
200
    private int mode = MODE_QUERY;
201
    private long versionOfUpdate = 0;
202
    private boolean hasStrongChanges = true;
203
    private boolean hasInserts = true;
204
205
    private DefaultDataManager dataManager = null;
206
207
    private FeatureStoreProvider provider = null;
208
209
    private DefaultFeatureIndexes indexes;
210
211
    private DefaultFeatureStoreTransforms transforms;
212
213
    DelegatedDynObject metadata;
214 41818 fdiaz
215 40435 jjdelcerro
    private Set metadataChildren;
216
217
    private Long featureCount = null;
218
219
    private long temporalOid = 0;
220
221
    private FeatureCacheProvider cache;
222
223 43215 jjdelcerro
    StateInformation state;
224 43270 fdiaz
225 43135 jjdelcerro
    FeatureStoreTimeSupport timeSupport;
226 43215 jjdelcerro
227
228
    private class StateInformation extends HashMap<Object, Object> {
229
230
        private static final long serialVersionUID = 4109026189635185666L;
231
232
        private boolean broken;
233
        private Throwable breakingsCause;
234 43270 fdiaz
235 43840 jjdelcerro
        @SuppressWarnings("OverridableMethodCallInConstructor")
236 43215 jjdelcerro
        public StateInformation() {
237
            this.clear();
238
        }
239 43270 fdiaz
240 43215 jjdelcerro
        @Override
241
        public void clear() {
242
            this.broken = false;
243
            this.breakingsCause = null;
244
            super.clear();
245
        }
246 43270 fdiaz
247 43215 jjdelcerro
        public boolean isBroken() {
248
            return this.broken;
249
        }
250 43270 fdiaz
251 43215 jjdelcerro
        public void broken() {
252
            this.broken = true;
253
        }
254 43270 fdiaz
255 43215 jjdelcerro
        public Throwable getBreakingsCause() {
256
            return this.breakingsCause;
257
        }
258 43270 fdiaz
259 43215 jjdelcerro
        public void setBreakingsCause(Throwable cause) {
260
            if( this.breakingsCause==null ) {
261
                this.breakingsCause = cause;
262
            }
263
            this.broken = true;
264 43270 fdiaz
        }
265 43215 jjdelcerro
    }
266
267
268 43270 fdiaz
269 40435 jjdelcerro
    /*
270
     * TODO:
271 41818 fdiaz
     *
272 40435 jjdelcerro
     * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
273
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
274
     * featureType al que se le han cambiado las reglas de validacion cuando
275
     * hasStrongChanges=false.
276
     */
277 42293 jjdelcerro
278 40435 jjdelcerro
    public DefaultFeatureStore() {
279 43215 jjdelcerro
        this.state = new StateInformation();
280 40435 jjdelcerro
    }
281
282 43020 jjdelcerro
    @Override
283
    public void intialize(DataManager dataManager,
284 42293 jjdelcerro
        DataStoreParameters parameters) throws InitializeException {
285 40435 jjdelcerro
286
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
287
288 43020 jjdelcerro
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
289 43152 fdiaz
            FeatureStore.METADATA_DEFINITION_NAME,
290 43020 jjdelcerro
            MetadataManager.METADATA_NAMESPACE
291
        );
292 40435 jjdelcerro
293
        this.dataManager = (DefaultDataManager) dataManager;
294
295
        this.parameters = parameters;
296
        this.transforms = new DefaultFeatureStoreTransforms(this);
297
        try {
298
            indexes = new DefaultFeatureIndexes(this);
299
        } catch (DataException e) {
300
            throw new InitializeException(e);
301
        }
302
303
    }
304
305 43020 jjdelcerro
    @Override
306
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
307 40435 jjdelcerro
        this.provider = (FeatureStoreProvider) provider;
308 43020 jjdelcerro
        this.delegate((DynObject) provider);
309 40435 jjdelcerro
        this.metadataChildren = new HashSet();
310
        this.metadataChildren.add(provider);
311 43958 jjdelcerro
        loadDALFile();
312 40435 jjdelcerro
    }
313
314 43215 jjdelcerro
    @Override
315 40435 jjdelcerro
    public DataStoreParameters getParameters() {
316
        return parameters;
317
    }
318
319
    public int getMode() {
320
        return this.mode;
321
    }
322
323 43215 jjdelcerro
    @Override
324 40435 jjdelcerro
    public DataManager getManager() {
325
        return this.dataManager;
326
    }
327
328 43215 jjdelcerro
    @Override
329 40435 jjdelcerro
    public Iterator getChildren() {
330
        return this.provider.getChilds();
331
    }
332
333 43215 jjdelcerro
    @Override
334 40435 jjdelcerro
    public FeatureStoreProvider getProvider() {
335
        return this.provider;
336
    }
337
338
    public FeatureManager getFeatureManager() {
339
        return this.featureManager;
340
    }
341
342 43215 jjdelcerro
    @Override
343 40435 jjdelcerro
    public void setFeatureTypes(List types, FeatureType defaultType) {
344
        this.featureTypes = types;
345
        this.defaultFeatureType = defaultType;
346
    }
347
348
    public void open() throws OpenException {
349 42049 jjdelcerro
        if (this.mode != MODE_QUERY) {
350
            // TODO: Se puede hacer un open estando en edicion ?
351
            try {
352
                throw new IllegalStateException();
353 42293 jjdelcerro
            } catch(Exception ex) {
354
                LOG.warn("Opening a store in editing/append mode ("+this.getFullName()+").",ex);
355 42049 jjdelcerro
            }
356
        }
357 40435 jjdelcerro
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
358
        this.provider.open();
359
        this.notifyChange(DataStoreNotification.AFTER_OPEN);
360
    }
361
362 43215 jjdelcerro
    @Override
363 40435 jjdelcerro
    public void refresh() throws OpenException, InitializeException {
364
        if (this.mode != MODE_QUERY) {
365
            throw new IllegalStateException();
366
        }
367
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
368 43215 jjdelcerro
        if( state.isBroken() ) {
369
            this.load(state);
370
        } else {
371
            this.featureCount = null;
372
            this.provider.refresh();
373
        }
374 40435 jjdelcerro
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
375
    }
376
377
    public void close() throws CloseException {
378 42049 jjdelcerro
        if (this.mode != MODE_QUERY) {
379
            // TODO: Se puede hacer un close estando en edicion ?
380
            try {
381
                throw new IllegalStateException();
382 42293 jjdelcerro
            } catch(Exception ex) {
383
                LOG.warn("Clossing a store in editing/append mode ("+this.getFullName()+").",ex);
384 42049 jjdelcerro
            }
385
        }
386 40435 jjdelcerro
        this.notifyChange(DataStoreNotification.BEFORE_CLOSE);
387
        this.featureCount = null;
388
        this.provider.close();
389
        this.notifyChange(DataStoreNotification.AFTER_CLOSE);
390
    }
391
392 43215 jjdelcerro
    @Override
393 40435 jjdelcerro
    protected void doDispose() throws BaseException {
394 42049 jjdelcerro
        if (this.mode != MODE_QUERY) {
395
            // TODO: Se puede hacer un dispose estando en edicion ?
396
            try {
397
                throw new IllegalStateException();
398 42293 jjdelcerro
            } catch(Exception ex) {
399
                LOG.warn("Dispossing a store in editing/append mode ("+this.getFullName()+").",ex);
400 42049 jjdelcerro
            }
401
        }
402 40435 jjdelcerro
        this.notifyChange(DataStoreNotification.BEFORE_DISPOSE);
403
        this.disposeIndexes();
404 43377 jjdelcerro
        if( this.provider!=null ) {
405
            this.provider.dispose();
406
        }
407 40435 jjdelcerro
        if (this.selection != null) {
408
            this.selection.dispose();
409
            this.selection = null;
410
        }
411
        this.commands = null;
412
        this.featureCount = null;
413
        if (this.locks != null) {
414
            // this.locks.dispose();
415
            this.locks = null;
416
        }
417
418
        if (this.featureTypeManager != null) {
419
            this.featureTypeManager.dispose();
420
            this.featureTypeManager = null;
421
        }
422
423
        this.featureManager = null;
424
        this.spatialManager = null;
425
426
        this.parameters = null;
427
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
428
        if (delegateObservable != null) {
429
            this.delegateObservable.deleteObservers();
430
            this.delegateObservable = null;
431
        }
432
    }
433
434 43215 jjdelcerro
    @Override
435 40435 jjdelcerro
    public boolean allowWrite() {
436 41928 jjdelcerro
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
437 42293 jjdelcerro
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
438 41928 jjdelcerro
            return false;
439
        }
440 40435 jjdelcerro
        return this.provider.allowWrite();
441
    }
442
443 43215 jjdelcerro
    @Override
444 40435 jjdelcerro
    public boolean canWriteGeometry(int geometryType) throws DataException {
445
        return this.provider.canWriteGeometry(geometryType, 0);
446
    }
447
448 43215 jjdelcerro
    @Override
449 40435 jjdelcerro
    public DataServerExplorer getExplorer() throws ReadException,
450 42293 jjdelcerro
        ValidateDataParametersException {
451 43215 jjdelcerro
        if( this.state.isBroken() ) {
452
            try {
453
                return this.provider.getExplorer();
454
            } catch(Throwable th) {
455
                return null;
456
            }
457
        } else {
458
            return this.provider.getExplorer();
459
        }
460 40435 jjdelcerro
    }
461
462
    /*
463
     * public Metadata getMetadata() throws MetadataNotFoundException {
464
     * // TODO:
465
     * // Si el provider devuelbe null habria que ver de construir aqui
466
     * // los metadatos basicos, como el Envelope y el SRS.
467 41818 fdiaz
     *
468 40435 jjdelcerro
     * // TODO: Estando en edicion el Envelope deberia de
469
     * // actualizarse usando el spatialManager
470
     * return this.provider.getMetadata();
471
     * }
472
     */
473 42293 jjdelcerro
474 43215 jjdelcerro
    @Override
475 40435 jjdelcerro
    public Envelope getEnvelope() throws DataException {
476
        if (this.mode == MODE_FULLEDIT) {
477 42293 jjdelcerro
                // Just in case another thread tries to write in the store
478
                synchronized (this) {
479
                        return this.spatialManager.getEnvelope();
480
                        }
481 40435 jjdelcerro
        }
482 42293 jjdelcerro
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
483
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
484 40435 jjdelcerro
        }
485
        return this.provider.getEnvelope();
486
    }
487
488
    /**
489 43840 jjdelcerro
     * @throws org.gvsig.fmap.dal.exception.DataException
490 40435 jjdelcerro
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
491
     */
492 43215 jjdelcerro
    @Override
493 40435 jjdelcerro
    public IProjection getSRSDefaultGeometry() throws DataException {
494
        return this.getDefaultFeatureType().getDefaultSRS();
495
    }
496
497 43215 jjdelcerro
    @Override
498 40435 jjdelcerro
    public FeatureSelection createDefaultFeatureSelection()
499 42293 jjdelcerro
        throws DataException {
500 40435 jjdelcerro
        return new DefaultFeatureSelection(this);
501
    }
502
503 43215 jjdelcerro
    @Override
504 40435 jjdelcerro
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
505 42293 jjdelcerro
        throws DataException {
506 40435 jjdelcerro
        if (type.hasOID()) {
507
            return new DefaultFeatureProvider(type,
508 42293 jjdelcerro
                this.provider.createNewOID());
509 40435 jjdelcerro
        }
510
        return new DefaultFeatureProvider(type);
511
    }
512
513 43215 jjdelcerro
    @Override
514 40435 jjdelcerro
    public void saveToState(PersistentState state) throws PersistenceException {
515 40776 nbrodin
        /*if (this.mode != FeatureStore.MODE_QUERY) {
516 42293 jjdelcerro
            throw new PersistenceException(new IllegalStateException(
517
                this.getName()));
518
        }*/
519 40435 jjdelcerro
        state.set("dataStoreName", this.getName());
520
        state.set("parameters", this.parameters);
521
        state.set("selection", this.selection);
522
        state.set("transforms", this.transforms);
523
        // TODO locks persistence
524
        // state.set("locks", this.locks);
525
        // TODO indexes persistence
526
        // state.set("indexes", this.indexes);
527
        Map evaluatedAttr = new HashMap(1);
528
        Iterator iterType = featureTypes.iterator();
529
        Iterator iterAttr;
530
        FeatureType type;
531
        DefaultFeatureAttributeDescriptor attr;
532
        List attrs;
533
        while (iterType.hasNext()) {
534
            type = (FeatureType) iterType.next();
535
            attrs = new ArrayList();
536
            iterAttr = type.iterator();
537
            while (iterAttr.hasNext()) {
538
                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
539
                if ((attr.getEvaluator() != null)
540 42293 jjdelcerro
                    && (attr.getEvaluator() instanceof Persistent)) {
541 40435 jjdelcerro
                    attrs.add(attr);
542
                }
543
            }
544
            if (!attrs.isEmpty()) {
545
                evaluatedAttr.put(type.getId(), attrs);
546
            }
547
548
        }
549
550
        if (evaluatedAttr.isEmpty()) {
551
            evaluatedAttr = null;
552
        }
553
554
        state.set("evaluatedAttributes", evaluatedAttr);
555
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
556
557
    }
558 43270 fdiaz
559 43215 jjdelcerro
    @Override
560
    public void loadFromState(final PersistentState persistentState)
561 42293 jjdelcerro
        throws PersistenceException {
562 40435 jjdelcerro
        if (this.provider != null) {
563
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
564
        }
565
        if (this.getManager() == null) {
566
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
567
        }
568 43215 jjdelcerro
        state.clear();
569
        try {
570
            state.put("parameters", persistentState.get("parameters"));
571
        } catch(Throwable th) {
572
            state.setBreakingsCause(th);
573
        }
574
        try {
575
            state.put("selection", persistentState.get("selection"));
576
        } catch(Throwable th) {
577
            state.setBreakingsCause(th);
578
        }
579
        try {
580
            state.put("transforms",  persistentState.get("transforms"));
581
        } catch(Throwable th) {
582
            state.setBreakingsCause(th);
583
        }
584
        try {
585
            state.put("evaluatedAttributes",  persistentState.get("evaluatedAttributes"));
586
        } catch(Throwable th) {
587
            state.setBreakingsCause(th);
588
        }
589
        try {
590
            state.put("defaultFeatureTypeId", persistentState.getString("defaultFeatureTypeId"));
591
        } catch(Throwable th) {
592
            state.setBreakingsCause(th);
593
        }
594
        load(state);
595 43270 fdiaz
    }
596
597
    private void load(StateInformation state) {
598 43215 jjdelcerro
        this.featureTypes = new ArrayList();
599
        this.defaultFeatureType = null;
600
        this.featureCount = null;
601 40435 jjdelcerro
602 43215 jjdelcerro
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
603
        try {
604
            intialize(dataManager, params);
605
        } catch(Throwable th) {
606
            state.setBreakingsCause(th);
607
        }
608 40435 jjdelcerro
609
        try {
610 43215 jjdelcerro
            DataStoreProvider prov = dataManager.createProvider(
611
                getStoreProviderServices(),
612
                params
613 43020 jjdelcerro
            );
614 43215 jjdelcerro
            setProvider(prov);
615
        } catch(Throwable th) {
616
            state.setBreakingsCause(th);
617
        }
618 43152 fdiaz
619 43215 jjdelcerro
        try {
620
            selection = (FeatureSelection) state.get("selection");
621
        } catch(Throwable th) {
622
            state.setBreakingsCause(th);
623
        }
624
625
        try {
626
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
627
            this.transforms.setFeatureStore(this);
628
            for( FeatureStoreTransform transform : this.transforms ) {
629
                try {
630
                    transform.setUp();
631
                } catch(Throwable th) {
632
                    state.setBreakingsCause(th);
633
                }
634
            }
635
        } catch(Throwable th) {
636
            state.setBreakingsCause(th);
637
        }
638
639
        try {
640 40435 jjdelcerro
            Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
641
            if ((evaluatedAttributes != null) && !evaluatedAttributes.isEmpty()) {
642 43215 jjdelcerro
                    Iterator iterEntries = evaluatedAttributes.entrySet().iterator();
643
                    while (iterEntries.hasNext()) {
644
                            Entry entry = (Entry) iterEntries.next();
645
                            List attrs = (List) entry.getValue();
646
                            if (attrs.isEmpty()) {
647
                                    continue;
648
                            }
649
                            int fTypePos = -1;
650
                            DefaultFeatureType type = null;
651
                            for (int i = 0; i < featureTypes.size(); i++) {
652
                                    type = (DefaultFeatureType) featureTypes.get(i);
653
                                    if (type.getId().equals(entry.getKey())) {
654
                                            fTypePos = i;
655
                                            break;
656
                                    }
657
                            }
658
                            if (type == null) {
659
                                    throw new PersistenceCantFindFeatureTypeException(
660
                                            getName(), (String) entry.getKey());
661
                            }
662
                            DefaultEditableFeatureType eType = (DefaultEditableFeatureType) type.getEditable();
663
                            Iterator<FeatureAttributeDescriptor> iterAttr = attrs.iterator();
664
                            while (iterAttr.hasNext()) {
665
                                    FeatureAttributeDescriptor attr = iterAttr.next();
666
                                    eType.addLike(attr);
667
                            }
668
                            featureTypes.set(fTypePos, eType.getNotEditableCopy());
669
670 40435 jjdelcerro
                    }
671
672
            }
673 43215 jjdelcerro
        } catch(Throwable th) {
674
            state.setBreakingsCause(th);
675
        }
676 40435 jjdelcerro
677 43270 fdiaz
678 43215 jjdelcerro
        try {
679
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
680
            FeatureType ftype;
681 41818 fdiaz
682 43215 jjdelcerro
            if (defaultFeatureType == null ||
683
                    defaultFeatureType.getId() == null ||
684
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
685 40435 jjdelcerro
686 43215 jjdelcerro
                    ftype = getFeatureType(defaultFeatureTypeId);
687
                    if (ftype == null) {
688
                            /*
689
                             * Un error en el m?todo de PostgreSQL getName(), hace que
690
                             * el nombre del featureType sea valor retornado por el getProviderName()
691
                             * De momento se pone este parche para apa?arlo y poder mantener compatibilidad
692
                             * con proyectos antiguos (2.1 y 2.2)
693
                             */
694
                            ftype = getFeatureType(getName());
695
                            if(ftype == null ) {
696
                                    throw new RuntimeException("Can't locate feature type");
697
                            }
698
                    }
699
                    defaultFeatureType = ftype;
700 40435 jjdelcerro
            }
701 43215 jjdelcerro
        } catch(Throwable th) {
702
            state.setBreakingsCause(th);
703 40435 jjdelcerro
        }
704
705 43270 fdiaz
        LOG.info("load() broken:{}, {}, {}.",
706 43215 jjdelcerro
                new Object[] { state.isBroken(), this.getProviderName(), params }
707
        );
708 40435 jjdelcerro
    }
709
710 43215 jjdelcerro
        public DataStoreProviderServices getStoreProviderServices() {
711
                return this;
712
        }
713 43270 fdiaz
714 40435 jjdelcerro
    public static void registerPersistenceDefinition() {
715
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
716
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
717 42293 jjdelcerro
            DynStruct definition =
718
                manager.addDefinition(DefaultFeatureStore.class,
719
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
720
                        + " Persistent definition", null, null);
721 40435 jjdelcerro
            definition.addDynFieldString("dataStoreName").setMandatory(true)
722 42293 jjdelcerro
                .setPersistent(true);
723 40435 jjdelcerro
724
            definition.addDynFieldObject("parameters")
725 42293 jjdelcerro
                .setClassOfValue(DynObject.class).setMandatory(true)
726
                .setPersistent(true);
727 40435 jjdelcerro
728
            definition.addDynFieldObject("selection")
729 42293 jjdelcerro
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
730
                .setPersistent(true);
731 40435 jjdelcerro
732
            definition.addDynFieldObject("transforms")
733 42293 jjdelcerro
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
734
                .setMandatory(true).setPersistent(true);
735 40435 jjdelcerro
736
            definition.addDynFieldMap("evaluatedAttributes")
737 42293 jjdelcerro
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
738
                .setMandatory(false).setPersistent(true);
739 40435 jjdelcerro
740
            definition.addDynFieldString("defaultFeatureTypeId")
741 42293 jjdelcerro
                .setMandatory(true).setPersistent(true);
742 40435 jjdelcerro
        }
743
    }
744
745
    public static void registerMetadataDefinition() throws MetadataException {
746
        MetadataManager manager = MetadataLocator.getMetadataManager();
747 43020 jjdelcerro
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
748 42293 jjdelcerro
            DynStruct metadataDefinition =
749 43020 jjdelcerro
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
750 40435 jjdelcerro
            metadataDefinition.extend(manager
751 42293 jjdelcerro
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
752 40435 jjdelcerro
        }
753
    }
754
755
    //
756
    // ====================================================================
757
    // Gestion de la seleccion
758
    //
759 42293 jjdelcerro
760 43215 jjdelcerro
    @Override
761 40435 jjdelcerro
    public void setSelection(DataSet selection) throws DataException {
762
        this.setSelection((FeatureSet) selection);
763
    }
764
765 43215 jjdelcerro
    @Override
766 40435 jjdelcerro
    public DataSet createSelection() throws DataException {
767
        return createFeatureSelection();
768
    }
769
770 43215 jjdelcerro
    @Override
771 40435 jjdelcerro
    public DataSet getSelection() throws DataException {
772
        return this.getFeatureSelection();
773
    }
774
775 43215 jjdelcerro
    @Override
776 40435 jjdelcerro
    public void setSelection(FeatureSet selection) throws DataException {
777
        setSelection(selection, true);
778
    }
779
780
    public void setSelection(FeatureSet selection, boolean undoable)
781 42293 jjdelcerro
        throws DataException {
782 40435 jjdelcerro
        if (selection == null) {
783
            if (undoable) {
784
                throw new SelectionNotAllowedException(getName());
785
            }
786
787
        } else {
788
            if (selection.equals(this.selection)) {
789
                return;
790
            }
791
            if (!selection.isFromStore(this)) {
792
                throw new SelectionNotAllowedException(getName());
793
            }
794
        }
795
796
        if (this.selection != null) {
797
            this.selection.deleteObserver(this);
798
        }
799
        if (selection == null) {
800
            if (this.selection != null) {
801
                this.selection.dispose();
802
            }
803
            this.selection = null;
804
            return;
805
        }
806
        if (selection instanceof FeatureSelection) {
807
            if (undoable && isEditing()) {
808
                commands.selectionSet(this, this.selection,
809 42293 jjdelcerro
                    (FeatureSelection) selection);
810 40435 jjdelcerro
            }
811
            if (this.selection != null) {
812
                this.selection.dispose();
813
            }
814
            this.selection = (FeatureSelection) selection;
815
        } else {
816
            if (undoable && isEditing()) {
817
                commands.startComplex("_selectionSet");
818
            }
819
            if (selection instanceof DefaultFeatureSelection) {
820 42293 jjdelcerro
                DefaultFeatureSelection defSelection =
821
                    (DefaultFeatureSelection) selection;
822 40435 jjdelcerro
                defSelection.deselectAll(undoable);
823
                defSelection.select(selection, undoable);
824
            } else {
825
                this.selection.deselectAll();
826
                this.selection.select(selection);
827
            }
828
            if (undoable && isEditing()) {
829
                commands.endComplex();
830
            }
831
        }
832
        this.selection.addObserver(this);
833
834
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
835
    }
836
837 43215 jjdelcerro
    @Override
838 40435 jjdelcerro
    public FeatureSelection createFeatureSelection() throws DataException {
839
        return this.provider.createFeatureSelection();
840
    }
841
842 43215 jjdelcerro
    @Override
843 40435 jjdelcerro
    public FeatureSelection getFeatureSelection() throws DataException {
844
        if (selection == null) {
845
            this.selection = createFeatureSelection();
846
            this.selection.addObserver(this);
847
        }
848
        return selection;
849
    }
850
851
    //
852
    // ====================================================================
853
    // Gestion de notificaciones
854
    //
855 42293 jjdelcerro
856 43093 jjdelcerro
    @Override
857
    public void notifyChange(FeatureStoreNotification storeNotification) {
858
        try {
859
            delegateObservable.notifyObservers(storeNotification);
860
        } catch (Throwable ex) {
861
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
862
        }
863
    }
864
865
    @Override
866 40435 jjdelcerro
    public void notifyChange(String notification) {
867
        if (delegateObservable != null) {
868
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
869
        }
870
871
    }
872
873 43093 jjdelcerro
    @Override
874 40435 jjdelcerro
    public void notifyChange(String notification, FeatureProvider data) {
875 43093 jjdelcerro
        Feature f = null;
876 40435 jjdelcerro
        try {
877 43093 jjdelcerro
            f = createFeature(data);
878
        } catch (Throwable ex) {
879
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
880 40435 jjdelcerro
        }
881 43093 jjdelcerro
        notifyChange(notification, f);
882 40435 jjdelcerro
    }
883
884
    public void notifyChange(String notification, Feature feature) {
885
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
886 42293 jjdelcerro
            feature));
887 40435 jjdelcerro
    }
888
889
    public void notifyChange(String notification, Command command) {
890
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
891 42293 jjdelcerro
            command));
892 40435 jjdelcerro
    }
893
894
    public void notifyChange(String notification, EditableFeatureType type) {
895
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
896 42293 jjdelcerro
            type));
897 40435 jjdelcerro
    }
898
899 43093 jjdelcerro
    @Override
900 40435 jjdelcerro
    public void notifyChange(String notification, Resource resource) {
901
        notifyChange(new DefaultFeatureStoreNotification(this,
902 42293 jjdelcerro
            DataStoreNotification.RESOURCE_CHANGED));
903 40435 jjdelcerro
    }
904
905
    //
906
    // ====================================================================
907
    // Gestion de bloqueos
908
    //
909 42293 jjdelcerro
910 43215 jjdelcerro
    @Override
911 40435 jjdelcerro
    public boolean isLocksSupported() {
912
        return this.provider.isLocksSupported();
913
    }
914
915 43215 jjdelcerro
    @Override
916 40435 jjdelcerro
    public FeatureLocks getLocks() throws DataException {
917
        if (!this.provider.isLocksSupported()) {
918
            LOG.warn("Locks not supported");
919
            return null;
920
        }
921
        if (locks == null) {
922
            this.locks = this.provider.createFeatureLocks();
923
        }
924
        return locks;
925
    }
926
927
    //
928
    // ====================================================================
929
    // Interface Observable
930
    //
931 42293 jjdelcerro
932 43215 jjdelcerro
    @Override
933 40435 jjdelcerro
    public void disableNotifications() {
934
        this.delegateObservable.disableNotifications();
935
936
    }
937
938 43215 jjdelcerro
    @Override
939 40435 jjdelcerro
    public void enableNotifications() {
940
        this.delegateObservable.enableNotifications();
941
    }
942
943 43215 jjdelcerro
    @Override
944 40435 jjdelcerro
    public void beginComplexNotification() {
945
        this.delegateObservable.beginComplexNotification();
946
947
    }
948
949 43215 jjdelcerro
    @Override
950 40435 jjdelcerro
    public void endComplexNotification() {
951
        this.delegateObservable.endComplexNotification();
952
953
    }
954
955 43215 jjdelcerro
    @Override
956 40435 jjdelcerro
    public void addObserver(Observer observer) {
957
        if (delegateObservable != null) {
958
            this.delegateObservable.addObserver(observer);
959
        }
960
    }
961
962 43215 jjdelcerro
    @Override
963 40435 jjdelcerro
    public void deleteObserver(Observer observer) {
964
        if (delegateObservable != null) {
965
            this.delegateObservable.deleteObserver(observer);
966
        }
967
    }
968
969 43215 jjdelcerro
    @Override
970 40435 jjdelcerro
    public void deleteObservers() {
971
        this.delegateObservable.deleteObservers();
972
973
    }
974
975
    //
976
    // ====================================================================
977
    // Interface Observer
978
    //
979
    // Usado para observar:
980
    // - su seleccion
981
    // - sus bloqueos
982
    // - sus recursos
983
    //
984 42293 jjdelcerro
985 43215 jjdelcerro
    @Override
986 40435 jjdelcerro
    public void update(Observable observable, Object notification) {
987
        if (observable instanceof FeatureSet) {
988
            if (observable == this.selection) {
989
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
990 43270 fdiaz
            } else if (observable == this.locks) {
991
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
992
            }
993 40435 jjdelcerro
994 43270 fdiaz
        } else if (observable instanceof FeatureStoreProvider) {
995
            if (observable == this.provider) {
996 40435 jjdelcerro
997
            }
998 43270 fdiaz
        } else if (observable instanceof FeatureReferenceSelection) {
999
            if(notification instanceof String){
1000
                    this.notifyChange((String)notification);
1001
            }
1002
        }
1003 40435 jjdelcerro
    }
1004
1005
    //
1006
    // ====================================================================
1007
    // Edicion
1008
    //
1009 42293 jjdelcerro
1010 40435 jjdelcerro
    private void newVersionOfUpdate() {
1011
        this.versionOfUpdate++;
1012
    }
1013
1014
    private long currentVersionOfUpdate() {
1015
        return this.versionOfUpdate;
1016
    }
1017
1018
    private void checkInEditingMode() throws NeedEditingModeException {
1019
        if (mode != MODE_FULLEDIT) {
1020
            throw new NeedEditingModeException(this.getName());
1021
        }
1022
    }
1023
1024
    private void checkNotInAppendMode() throws IllegalStateException {
1025
        if (mode == MODE_APPEND) {
1026 42293 jjdelcerro
                        throw new IllegalStateException("Error: store "
1027
                                        + this.getFullName() + " is in append mode");
1028 40435 jjdelcerro
        }
1029
    }
1030
1031
    private void checkIsOwnFeature(Feature feature)
1032 42293 jjdelcerro
        throws IllegalFeatureException {
1033 40435 jjdelcerro
        if (((DefaultFeature) feature).getStore() != this) {
1034
            throw new IllegalFeatureException(this.getName());
1035
        }
1036
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1037
        // fixFeatureType((DefaultFeatureType) feature.getType());
1038
    }
1039
1040
    private void exitEditingMode() {
1041
        if (commands != null) {
1042
            commands.clear();
1043
            commands = null;
1044
        }
1045
1046
        if (featureTypeManager != null) {
1047
            featureTypeManager.dispose();
1048
            featureTypeManager = null;
1049
1050
        }
1051
1052
        // TODO implementar un dispose para estos dos
1053
        featureManager = null;
1054
        spatialManager = null;
1055
1056
        featureCount = null;
1057
1058
        mode = MODE_QUERY;
1059
        hasStrongChanges = true; // Lo deja a true por si las moscas
1060
        hasInserts = true;
1061
    }
1062
1063 43215 jjdelcerro
    @Override
1064 40435 jjdelcerro
    synchronized public void edit() throws DataException {
1065
        edit(MODE_FULLEDIT);
1066
    }
1067
1068 43215 jjdelcerro
    @Override
1069 40435 jjdelcerro
    synchronized public void edit(int mode) throws DataException {
1070 43215 jjdelcerro
        LOG.debug("Starting editing in mode: {}", mode);
1071 40435 jjdelcerro
        try {
1072
            if (this.mode != MODE_QUERY) {
1073
                throw new AlreadyEditingException(this.getName());
1074
            }
1075
            if (!this.provider.supportsAppendMode()) {
1076
                mode = MODE_FULLEDIT;
1077
            }
1078
            switch (mode) {
1079 42293 jjdelcerro
            case MODE_QUERY:
1080
                throw new IllegalStateException(this.getName());
1081
1082
            case MODE_FULLEDIT:
1083
                if (!this.transforms.isEmpty()) {
1084 40435 jjdelcerro
                    throw new IllegalStateException(this.getName());
1085 42293 jjdelcerro
                }
1086
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1087
                invalidateIndexes();
1088 43840 jjdelcerro
                featureManager = new FeatureManager();
1089
                featureTypeManager = new FeatureTypeManager(this);
1090
                spatialManager = new SpatialManager(this, provider.getEnvelope());
1091 40435 jjdelcerro
1092 43840 jjdelcerro
                commands = new DefaultFeatureCommandsStack(
1093
                        this, featureManager,
1094 42293 jjdelcerro
                        spatialManager, featureTypeManager);
1095
                this.mode = MODE_FULLEDIT;
1096
                hasStrongChanges = false;
1097
                hasInserts = false;
1098
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1099
                break;
1100
            case MODE_APPEND:
1101
                if (!this.transforms.isEmpty()) {
1102
                    throw new IllegalStateException(this.getName());
1103
                }
1104
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1105
                invalidateIndexes();
1106
                this.provider.beginAppend();
1107
                this.mode = MODE_APPEND;
1108
                hasInserts = false;
1109
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1110
                break;
1111 40435 jjdelcerro
            }
1112
        } catch (Exception e) {
1113
            throw new StoreEditException(e, this.getName());
1114
        }
1115
    }
1116
1117
    private void invalidateIndexes() {
1118
        setIndexesValidStatus(false);
1119
    }
1120
1121
    private void setIndexesValidStatus(boolean valid) {
1122 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1123 40435 jjdelcerro
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
1124 43215 jjdelcerro
            ? Boolean.TRUE : Boolean.FALSE), theIndexes);
1125
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1126 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1127
            if (index instanceof FeatureIndexProviderServices) {
1128 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1129
                    (FeatureIndexProviderServices) index;
1130 40435 jjdelcerro
                indexServices.setValid(valid);
1131
            }
1132
        }
1133
    }
1134
1135
    private void updateIndexes() throws FeatureIndexException {
1136 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1137
        LOG.debug("Refilling indexes: {}", theIndexes);
1138
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1139 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1140
            if (index instanceof FeatureIndexProviderServices) {
1141 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1142
                    (FeatureIndexProviderServices) index;
1143 40435 jjdelcerro
                indexServices.fill(true, null);
1144
            }
1145
        }
1146
    }
1147
1148
    private void waitForIndexes() {
1149 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1150
        LOG.debug("Waiting for indexes to finish filling: {}", theIndexes);
1151
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1152 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1153
            if (index instanceof FeatureIndexProviderServices) {
1154 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1155
                    (FeatureIndexProviderServices) index;
1156 40435 jjdelcerro
                indexServices.waitForIndex();
1157
            }
1158
        }
1159
    }
1160
1161
    private void disposeIndexes() {
1162 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1163
        LOG.debug("Disposing indexes: {}", theIndexes);
1164 43377 jjdelcerro
        if( theIndexes==null ) {
1165
            return;
1166
        }
1167 43215 jjdelcerro
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1168 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1169
            if (index instanceof FeatureIndexProviderServices) {
1170 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1171
                    (FeatureIndexProviderServices) index;
1172 40435 jjdelcerro
                indexServices.dispose();
1173
            }
1174
        }
1175
    }
1176
1177 43215 jjdelcerro
    @Override
1178 40435 jjdelcerro
    public boolean isEditing() {
1179
        return mode == MODE_FULLEDIT;
1180
    }
1181
1182 43215 jjdelcerro
    @Override
1183 40435 jjdelcerro
    public boolean isAppending() {
1184
        return mode == MODE_APPEND;
1185
    }
1186
1187 43215 jjdelcerro
    @Override
1188 40435 jjdelcerro
    synchronized public void update(EditableFeatureType type)
1189 42293 jjdelcerro
        throws DataException {
1190 40435 jjdelcerro
        try {
1191
            if (type == null) {
1192
                throw new NullFeatureTypeException(getName());
1193
            }
1194 43981 omartinez
            boolean typehasStrongChanges = ((DefaultEditableFeatureType) type).hasStrongChanges();
1195
            if (typehasStrongChanges) {
1196
                checkInEditingMode();
1197
            }  else if(!this.isAppending()) {
1198
                throw new NeedEditingModeException(this.getName());
1199
            }
1200 40435 jjdelcerro
            // FIXME: Comprobar que es un featureType aceptable.
1201
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
1202
            newVersionOfUpdate();
1203 43981 omartinez
1204
            if (typehasStrongChanges) {
1205
                FeatureType oldt = type.getSource().getCopy();
1206
                FeatureType newt = type.getCopy();
1207
                commands.update(newt, oldt);
1208 40435 jjdelcerro
                hasStrongChanges = true;
1209 43981 omartinez
            } else {
1210
                boolean ok = this.featureTypes.remove(this.defaultFeatureType);
1211
                this.defaultFeatureType = type.getCopy();
1212
                if (ok) {
1213
                    this.featureTypes.add(this.defaultFeatureType);
1214
                }
1215 40435 jjdelcerro
            }
1216
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1217
        } catch (Exception e) {
1218
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1219
        }
1220
    }
1221
1222 43215 jjdelcerro
    @Override
1223 41818 fdiaz
    public void delete(Feature feature) throws DataException {
1224 40435 jjdelcerro
        this.commands.delete(feature);
1225
    }
1226 41818 fdiaz
1227 40435 jjdelcerro
    synchronized public void doDelete(Feature feature) throws DataException {
1228
        try {
1229
            checkInEditingMode();
1230
            checkIsOwnFeature(feature);
1231
            if (feature instanceof EditableFeature) {
1232
                throw new StoreDeleteEditableFeatureException(getName());
1233
            }
1234 41818 fdiaz
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1235
1236 40435 jjdelcerro
            //Update the featureManager and the spatialManager
1237
            featureManager.delete(feature.getReference());
1238
            spatialManager.deleteFeature(feature);
1239 41818 fdiaz
1240 40435 jjdelcerro
            newVersionOfUpdate();
1241
            hasStrongChanges = true;
1242
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1243
        } catch (Exception e) {
1244
            throw new StoreDeleteFeatureException(e, this.getName());
1245
        }
1246
    }
1247
1248
    private static EditableFeature lastChangedFeature = null;
1249
1250 43215 jjdelcerro
    @Override
1251 41818 fdiaz
    public synchronized void insert(EditableFeature feature)
1252 42293 jjdelcerro
        throws DataException {
1253 43215 jjdelcerro
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1254 40435 jjdelcerro
        try {
1255
            switch (mode) {
1256 42293 jjdelcerro
            case MODE_QUERY:
1257
                throw new NeedEditingModeException(this.getName());
1258 40435 jjdelcerro
1259 42293 jjdelcerro
            case MODE_APPEND:
1260
                checkIsOwnFeature(feature);
1261
                if (feature.getSource() != null) {
1262
                    throw new NoNewFeatureInsertException(this.getName());
1263
                }
1264
                this.featureCount = null;
1265
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1266
                feature.validate(Feature.UPDATE);
1267
                provider.append(((DefaultEditableFeature) feature).getData());
1268
                hasStrongChanges = true;
1269
                hasInserts = true;
1270
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1271
                break;
1272 40435 jjdelcerro
1273 42293 jjdelcerro
            case MODE_FULLEDIT:
1274
                if (feature.getSource() != null) {
1275
                    throw new NoNewFeatureInsertException(this.getName());
1276
                }
1277
                commands.insert(feature);
1278 40435 jjdelcerro
            }
1279
        } catch (Exception e) {
1280
            throw new StoreInsertFeatureException(e, this.getName());
1281
        }
1282
    }
1283 41818 fdiaz
1284 40435 jjdelcerro
    synchronized public void doInsert(EditableFeature feature)
1285 42293 jjdelcerro
        throws DataException {
1286 40435 jjdelcerro
        checkIsOwnFeature(feature);
1287 41818 fdiaz
1288 40435 jjdelcerro
        waitForIndexes();
1289
1290
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1291
        newVersionOfUpdate();
1292
        if ((lastChangedFeature == null)
1293 42293 jjdelcerro
            || (lastChangedFeature.getSource() != feature.getSource())) {
1294 40435 jjdelcerro
            lastChangedFeature = feature;
1295
            feature.validate(Feature.UPDATE);
1296
            lastChangedFeature = null;
1297
        }
1298
        //Update the featureManager and the spatialManager
1299
        ((DefaultEditableFeature) feature).setInserted(true);
1300
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1301 41818 fdiaz
1302 42293 jjdelcerro
1303 40435 jjdelcerro
        featureManager.add(newFeature);
1304
        spatialManager.insertFeature(newFeature);
1305 41818 fdiaz
1306 40435 jjdelcerro
        hasStrongChanges = true;
1307
        hasInserts = true;
1308 41818 fdiaz
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1309 40435 jjdelcerro
    }
1310 41818 fdiaz
1311 43215 jjdelcerro
    @Override
1312 40435 jjdelcerro
    public void update(EditableFeature feature)
1313 42293 jjdelcerro
    throws DataException {
1314 40435 jjdelcerro
        if ((feature).getSource() == null) {
1315
            insert(feature);
1316
            return;
1317
        }
1318
        commands.update(feature, feature.getSource());
1319
    }
1320
1321
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1322 42293 jjdelcerro
        throws DataException {
1323 41818 fdiaz
        try {
1324 40435 jjdelcerro
            checkInEditingMode();
1325
            checkIsOwnFeature(feature);
1326
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1327
            newVersionOfUpdate();
1328
            if ((lastChangedFeature == null)
1329 42293 jjdelcerro
                || (lastChangedFeature.getSource() != feature.getSource())) {
1330 40435 jjdelcerro
                lastChangedFeature = feature;
1331
                feature.validate(Feature.UPDATE);
1332
                lastChangedFeature = null;
1333
            }
1334 41818 fdiaz
1335 40435 jjdelcerro
            //Update the featureManager and the spatialManager
1336
            Feature newf = feature.getNotEditableCopy();
1337
            featureManager.update(newf, oldFeature);
1338
            spatialManager.updateFeature(newf, oldFeature);
1339 41818 fdiaz
1340 40435 jjdelcerro
            hasStrongChanges = true;
1341
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1342
        } catch (Exception e) {
1343
            throw new StoreUpdateFeatureException(e, this.getName());
1344
        }
1345
    }
1346
1347 43215 jjdelcerro
    @Override
1348 40435 jjdelcerro
    synchronized public void redo() throws RedoException {
1349
        Command redo = commands.getNextRedoCommand();
1350
        try {
1351
            checkInEditingMode();
1352
        } catch (NeedEditingModeException ex) {
1353
            throw new RedoException(redo, ex);
1354
        }
1355
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1356
        newVersionOfUpdate();
1357
        commands.redo();
1358
        hasStrongChanges = true;
1359
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1360
    }
1361
1362 43215 jjdelcerro
    @Override
1363 40435 jjdelcerro
    synchronized public void undo() throws UndoException {
1364
        Command undo = commands.getNextUndoCommand();
1365
        try {
1366
            checkInEditingMode();
1367
        } catch (NeedEditingModeException ex) {
1368
            throw new UndoException(undo, ex);
1369
        }
1370
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1371
        newVersionOfUpdate();
1372
        commands.undo();
1373
        hasStrongChanges = true;
1374
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1375
    }
1376
1377 43215 jjdelcerro
    @Override
1378 40435 jjdelcerro
    public List getRedoInfos() {
1379
        if (isEditing() && (commands != null)) {
1380
            return commands.getRedoInfos();
1381
        } else {
1382
            return null;
1383
        }
1384
    }
1385
1386 43215 jjdelcerro
    @Override
1387 40435 jjdelcerro
    public List getUndoInfos() {
1388
        if (isEditing() && (commands != null)) {
1389
            return commands.getUndoInfos();
1390
        } else {
1391
            return null;
1392
        }
1393
    }
1394
1395
    public synchronized FeatureCommandsStack getCommandsStack()
1396 42293 jjdelcerro
        throws DataException {
1397 40435 jjdelcerro
        checkInEditingMode();
1398
        return commands;
1399
    }
1400
1401 43215 jjdelcerro
    @Override
1402 40435 jjdelcerro
    synchronized public void cancelEditing() throws DataException {
1403 43642 jjdelcerro
        if( spatialManager!=null ) {
1404
            spatialManager.cancelModifies();
1405
        }
1406 40435 jjdelcerro
        try {
1407 43408 jjdelcerro
            switch (mode) {
1408
            case MODE_QUERY:
1409
                throw new NeedEditingModeException(this.getName());
1410 40435 jjdelcerro
1411 43408 jjdelcerro
            case MODE_APPEND:
1412
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1413
                provider.abortAppend();
1414
                exitEditingMode();
1415 40435 jjdelcerro
                ((FeatureSelection) this.getSelection()).deselectAll();
1416 43408 jjdelcerro
                updateIndexes();
1417
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1418
1419
            case MODE_FULLEDIT:
1420
                boolean clearSelection = this.hasStrongChanges;
1421
                if (this.selection instanceof FeatureReferenceSelection) {
1422
                    clearSelection = this.hasInserts;
1423
                }
1424
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1425
                exitEditingMode();
1426
                if (clearSelection) {
1427
                    ((FeatureSelection) this.getSelection()).deselectAll();
1428
                }
1429
                updateIndexes();
1430
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1431 40435 jjdelcerro
            }
1432
        } catch (Exception e) {
1433
            throw new StoreCancelEditingException(e, this.getName());
1434
        }
1435
    }
1436
1437 43215 jjdelcerro
    @Override
1438 40435 jjdelcerro
    synchronized public void finishEditing() throws DataException {
1439 43215 jjdelcerro
        LOG.debug("finish editing of mode: {}", mode);
1440 40435 jjdelcerro
        try {
1441 41818 fdiaz
1442 40435 jjdelcerro
            /*
1443
             * Selection needs to be cleared when editing stops
1444
             * to prevent conflicts with selection remaining from
1445
             * editing mode.
1446
             */
1447 42639 dmartinezizquierdo
//            ((FeatureSelection) this.getSelection()).deselectAll();
1448 43981 omartinez
            Map<String,List<FeatureAttributeDescriptor>> computedFields = this.getComputedFields();
1449 40435 jjdelcerro
            switch (mode) {
1450 42293 jjdelcerro
            case MODE_QUERY:
1451
                throw new NeedEditingModeException(this.getName());
1452 40435 jjdelcerro
1453 42293 jjdelcerro
            case MODE_APPEND:
1454 43377 jjdelcerro
                if( selection!=null ) {
1455
                    selection = null;
1456
                }
1457 42293 jjdelcerro
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1458
                provider.endAppend();
1459
                exitEditingMode();
1460 43981 omartinez
                this.updateComputedFields(computedFields);
1461
                saveDALFile();
1462 42293 jjdelcerro
                updateIndexes();
1463
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1464
                break;
1465 40435 jjdelcerro
1466 42293 jjdelcerro
            case MODE_FULLEDIT:
1467
                if (hasStrongChanges && !this.allowWrite()) {
1468
                    throw new WriteNotAllowedException(getName());
1469
                }
1470 43377 jjdelcerro
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1471
                    selection = null;
1472
                }
1473 42293 jjdelcerro
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1474
                if (hasStrongChanges) {
1475
                    validateFeatures(Feature.FINISH_EDITING);
1476 41818 fdiaz
1477 42293 jjdelcerro
                    /*
1478
                     * This will throw a PerformEditingExceptionif the provider
1479
                     * does not accept the changes (for example, an invalid field name)
1480
                     */
1481
                    provider.performChanges(featureManager.getDeleted(),
1482
                        featureManager.getInserted(),
1483
                        featureManager.getUpdated(),
1484 43967 jjdelcerro
                        removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1485 43981 omartinez
1486 43954 jjdelcerro
                }
1487 43981 omartinez
                exitEditingMode();
1488
                this.updateComputedFields(computedFields);
1489 43954 jjdelcerro
                saveDALFile();
1490 42293 jjdelcerro
                updateIndexes();
1491
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1492
                break;
1493 40435 jjdelcerro
            }
1494 40597 jldominguez
        } catch (PerformEditingException pee) {
1495 41437 jjdelcerro
            throw new WriteException(provider.getSourceId().toString(), pee);
1496 40435 jjdelcerro
        } catch (Exception e) {
1497
            throw new FinishEditingException(e);
1498
        }
1499
    }
1500 43981 omartinez
    private Map<String,List<FeatureAttributeDescriptor>> getComputedFields() throws DataException {
1501
        Map<String,List<FeatureAttributeDescriptor>> r = new HashMap<>();
1502
1503
        List<FeatureType> theTypes = new ArrayList<>();
1504
        theTypes.addAll(this.getFeatureTypes());
1505
        theTypes.add(this.getDefaultFeatureType());
1506
        for( int n=0; n<theTypes.size(); n++ ) {
1507
            FeatureType type = theTypes.get(n);
1508
                for (FeatureAttributeDescriptor attrdesc : type) {
1509
                    FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
1510
                    if( emulator!= null) {
1511
                        List<FeatureAttributeDescriptor> l = r.get(type.getId());
1512
                        if (l==null) {
1513
                            l = new ArrayList<>();
1514
                            r.put(type.getId(), l);
1515
                        }
1516
                        l.add(attrdesc);
1517
                    }
1518
            }
1519
        }
1520
        return r;
1521
    }
1522
    private void updateComputedFields(Map<String,List<FeatureAttributeDescriptor>> computedFields) throws DataException {
1523
1524
        List<FeatureType> theTypes = new ArrayList<>();
1525
        theTypes.addAll(this.getFeatureTypes());
1526
        theTypes.add(this.getDefaultFeatureType());
1527
        for( int n=0; n<theTypes.size(); n++ ) {
1528
            DefaultFeatureType type = (DefaultFeatureType) theTypes.get(n);
1529
            List<FeatureAttributeDescriptor> x = computedFields.get(type.getId());
1530
            if(x!=null && !x.isEmpty()) {
1531
                for (FeatureAttributeDescriptor attrdesc : x) {
1532
                    if (type.get(attrdesc.getName())==null) {
1533
                        type.add(attrdesc);
1534
                    }
1535
                }
1536
            }
1537
        }
1538
1539
    }
1540 43967 jjdelcerro
    private List<FeatureStoreProvider.FeatureTypeChanged> removeCalculatedAttributes(List<FeatureStoreProvider.FeatureTypeChanged> ftypes) {
1541
        // FIXME: Falta por implementar
1542 43978 omartinez
//        for (FeatureStoreProvider.FeatureTypeChanged ftype : ftypes) {
1543
//            EditableFeatureType target = (EditableFeatureType) ftype.getTarget();
1544
//            for (FeatureAttributeDescriptor attributeDescriptor : ftype.getSource().getAttributeDescriptors()) {
1545
//                if (attributeDescriptor.isComputed()) {
1546
//                    target.remove(attributeDescriptor.getName());
1547
//                }
1548
//            }
1549
//        }
1550 43967 jjdelcerro
        return ftypes;
1551
    }
1552
1553 40435 jjdelcerro
1554 43954 jjdelcerro
    @SuppressWarnings("UseSpecificCatch")
1555
    private void saveDALFile() {
1556
        try {
1557
            DataServerExplorer explorer = this.getExplorer();
1558 43956 jjdelcerro
            if( explorer == null ) {
1559
                return;
1560
            }
1561 43954 jjdelcerro
            File f = explorer.getResourcePath(this, "dal");
1562
            if( f == null ) {
1563
                return;
1564
            }
1565
            DALFile dalFile = DALFile.getDALFile();
1566
            dalFile.setStore(this);
1567
            if( !dalFile.isEmpty() ) {
1568
                dalFile.write(f);
1569
            }
1570
        } catch (Exception ex) {
1571
            LOG.warn("Can't save DAL File", ex);
1572
        }
1573
    }
1574
1575
    @SuppressWarnings("UseSpecificCatch")
1576
    private void loadDALFile() {
1577
        try {
1578
            DataServerExplorer explorer = this.getExplorer();
1579 43956 jjdelcerro
            if( explorer == null ) {
1580
                return;
1581
            }
1582 43954 jjdelcerro
            File f = explorer.getResourcePath(this, "dal");
1583 43958 jjdelcerro
            if( f == null || !f.exists() ) {
1584 43954 jjdelcerro
                return;
1585
            }
1586
            DALFile dalFile = DALFile.getDALFile(f);
1587
            if( !dalFile.isEmpty() ) {
1588
                dalFile.updateStore(this);
1589
            }
1590
        } catch (Exception ex) {
1591
            LOG.warn("Can't load DAL File", ex);
1592
        }
1593
    }
1594
1595 40435 jjdelcerro
    /**
1596 42293 jjdelcerro
     * Save changes in the provider without leaving the edit mode.
1597
     * Do not call observers to communicate a change of ediding mode.
1598
     * The operation's history is eliminated to prevent inconsistencies
1599
     * in the data.
1600 40435 jjdelcerro
     *
1601
     * @throws DataException
1602
     */
1603 43215 jjdelcerro
    @Override
1604 40435 jjdelcerro
    synchronized public void commitChanges() throws DataException {
1605 43215 jjdelcerro
      LOG.debug("commitChanges of mode: {}", mode);
1606 42293 jjdelcerro
      if( !canCommitChanges() ) {
1607
              throw new WriteNotAllowedException(getName());
1608
      }
1609
      try {
1610
        switch (mode) {
1611
        case MODE_QUERY:
1612
          throw new NeedEditingModeException(this.getName());
1613 40435 jjdelcerro
1614 42293 jjdelcerro
        case MODE_APPEND:
1615
          this.provider.endAppend();
1616
          exitEditingMode();
1617
          invalidateIndexes();
1618
          this.provider.beginAppend();
1619
          hasInserts = false;
1620
          break;
1621 40435 jjdelcerro
1622 42293 jjdelcerro
        case MODE_FULLEDIT:
1623
          if (hasStrongChanges && !this.allowWrite()) {
1624
            throw new WriteNotAllowedException(getName());
1625
          }
1626
          if (hasStrongChanges) {
1627
            validateFeatures(Feature.FINISH_EDITING);
1628
            provider.performChanges(featureManager.getDeleted(),
1629
              featureManager.getInserted(),
1630
              featureManager.getUpdated(),
1631 43967 jjdelcerro
              removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1632 42293 jjdelcerro
          }
1633
          invalidateIndexes();
1634 43840 jjdelcerro
          featureManager = new FeatureManager();
1635
          featureTypeManager = new FeatureTypeManager(this);
1636
          spatialManager = new SpatialManager(this, provider.getEnvelope());
1637 40435 jjdelcerro
1638 42293 jjdelcerro
          commands =
1639
            new DefaultFeatureCommandsStack(this, featureManager,
1640
              spatialManager, featureTypeManager);
1641
          featureCount = null;
1642
          hasStrongChanges = false;
1643
          hasInserts = false;
1644
          break;
1645 40435 jjdelcerro
        }
1646 42293 jjdelcerro
      } catch (Exception e) {
1647
        throw new FinishEditingException(e);
1648
      }
1649 40435 jjdelcerro
    }
1650
1651 43215 jjdelcerro
    @Override
1652 40435 jjdelcerro
    synchronized public boolean canCommitChanges() throws DataException {
1653 42293 jjdelcerro
        if ( !this.allowWrite()) {
1654
                return false;
1655 40435 jjdelcerro
        }
1656 42293 jjdelcerro
            switch (mode) {
1657
            default:
1658
        case MODE_QUERY:
1659
                return false;
1660 41818 fdiaz
1661 42293 jjdelcerro
        case MODE_APPEND:
1662
                return true;
1663 41818 fdiaz
1664 42293 jjdelcerro
        case MODE_FULLEDIT:
1665
            List types = this.getFeatureTypes();
1666
            for( int i=0; i<types.size(); i++ ) {
1667
                    Object type = types.get(i);
1668
                    if( type instanceof DefaultEditableFeatureType ) {
1669
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1670
                                    return false;
1671
                            }
1672
                    }
1673
            }
1674
            return true;
1675
            }
1676 40435 jjdelcerro
    }
1677 41818 fdiaz
1678 43215 jjdelcerro
    @Override
1679 40435 jjdelcerro
    public void beginEditingGroup(String description)
1680 42293 jjdelcerro
        throws NeedEditingModeException {
1681 40435 jjdelcerro
        checkInEditingMode();
1682
        commands.startComplex(description);
1683
    }
1684
1685 43215 jjdelcerro
    @Override
1686 40435 jjdelcerro
    public void endEditingGroup() throws NeedEditingModeException {
1687
        checkInEditingMode();
1688
        commands.endComplex();
1689
    }
1690
1691 43215 jjdelcerro
    @Override
1692 40435 jjdelcerro
    public boolean isAppendModeSupported() {
1693
        return this.provider.supportsAppendMode();
1694
    }
1695
1696 43215 jjdelcerro
    @Override
1697 40435 jjdelcerro
    public void export(DataServerExplorer explorer, String provider,
1698 42293 jjdelcerro
        NewFeatureStoreParameters params) throws DataException {
1699 40435 jjdelcerro
1700
        if (this.getFeatureTypes().size() != 1) {
1701
            throw new NotYetImplemented(
1702 42293 jjdelcerro
                "export whith more than one type not yet implemented");
1703 40435 jjdelcerro
        }
1704
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1705
        FeatureStore target = null;
1706
        FeatureSet features = null;
1707
        DisposableIterator iterator = null;
1708
        try {
1709
            FeatureType type = this.getDefaultFeatureType();
1710
            if ((params.getDefaultFeatureType() == null)
1711 42293 jjdelcerro
                || (params.getDefaultFeatureType().size() == 0)) {
1712 40435 jjdelcerro
                params.setDefaultFeatureType(type.getEditable());
1713
1714
            }
1715
            explorer.add(provider, params, true);
1716
1717
            DataManager manager = DALLocator.getDataManager();
1718
            target = (FeatureStore) manager.openStore(provider, params);
1719
            FeatureType targetType = target.getDefaultFeatureType();
1720
1721
            target.edit(MODE_APPEND);
1722 43840 jjdelcerro
            FeatureAttributeDescriptor[] pkattrs = type.getPrimaryKey();
1723 40435 jjdelcerro
            if (featureSelection.getSize() > 0) {
1724
                features = this.getFeatureSelection();
1725
            } else {
1726 43840 jjdelcerro
                if ((pkattrs != null) && (pkattrs.length > 0)) {
1727 40435 jjdelcerro
                    FeatureQuery query = createFeatureQuery();
1728 43840 jjdelcerro
                    for (FeatureAttributeDescriptor pkattr : pkattrs) {
1729
                        query.getOrder().add(pkattr.getName(), true);
1730 40435 jjdelcerro
                    }
1731
                    features = this.getFeatureSet(query);
1732
                } else {
1733
                    features = this.getFeatureSet();
1734
                }
1735
            }
1736
            iterator = features.fastIterator();
1737
            while (iterator.hasNext()) {
1738
                DefaultFeature feature = (DefaultFeature) iterator.next();
1739
                target.insert(target.createNewFeature(targetType, feature));
1740
            }
1741
            target.finishEditing();
1742
            target.dispose();
1743
        } catch (Exception e) {
1744
            throw new DataExportException(e, params.toString());
1745
        } finally {
1746
            dispose(iterator);
1747
            dispose(features);
1748
            dispose(target);
1749
        }
1750
    }
1751
1752
    //
1753
    // ====================================================================
1754
    // Obtencion de datos
1755
    // getDataCollection, getFeatureCollection
1756
    //
1757 42293 jjdelcerro
1758 43215 jjdelcerro
    @Override
1759 40435 jjdelcerro
    public DataSet getDataSet() throws DataException {
1760
        checkNotInAppendMode();
1761 42293 jjdelcerro
        FeatureQuery query =
1762
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1763 40435 jjdelcerro
        return new DefaultFeatureSet(this, query);
1764
    }
1765
1766 43215 jjdelcerro
    @Override
1767 40435 jjdelcerro
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1768
        checkNotInAppendMode();
1769
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1770
    }
1771
1772 43215 jjdelcerro
    @Override
1773 40435 jjdelcerro
    public void getDataSet(Observer observer) throws DataException {
1774
        checkNotInAppendMode();
1775
        this.getFeatureSet(null, observer);
1776
    }
1777
1778 43215 jjdelcerro
    @Override
1779 40435 jjdelcerro
    public void getDataSet(DataQuery dataQuery, Observer observer)
1780 42293 jjdelcerro
        throws DataException {
1781 40435 jjdelcerro
        checkNotInAppendMode();
1782
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1783
    }
1784
1785 42799 jjdelcerro
    @Override
1786 40435 jjdelcerro
    public FeatureSet getFeatureSet() throws DataException {
1787 42799 jjdelcerro
        return this.getFeatureSet((FeatureQuery)null);
1788 40435 jjdelcerro
    }
1789
1790 42799 jjdelcerro
    @Override
1791 40435 jjdelcerro
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1792 42293 jjdelcerro
        throws DataException {
1793 40435 jjdelcerro
        checkNotInAppendMode();
1794 42799 jjdelcerro
        if( featureQuery==null ) {
1795
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1796
        }
1797 40435 jjdelcerro
        return new DefaultFeatureSet(this, featureQuery);
1798
    }
1799
1800 42925 jjdelcerro
    @Override
1801 43533 jjdelcerro
    public FeatureSet getFeatureSet(String filter) throws DataException {
1802
        return this.getFeatureSet(filter, null, true);
1803
    }
1804
1805
    @Override
1806
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1807
        return this.getFeatureSet(filter, sortBy, true);
1808
    }
1809
1810
    @Override
1811
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1812
        FeatureQuery query = this.createFeatureQuery();
1813
        if( !StringUtils.isEmpty(filter) ) {
1814
            query.setFilter(filter);
1815
        }
1816
        if( !StringUtils.isEmpty(sortBy) ) {
1817
            query.getOrder().add(sortBy, asc);
1818
        }
1819
        return this.getFeatureSet(query);
1820
    }
1821 43628 jjdelcerro
1822
    @Override
1823
    public List<Feature> getFeatures(String filter)  {
1824
        return this.getFeatures(filter, null, true);
1825
    }
1826 43533 jjdelcerro
1827
    @Override
1828 43628 jjdelcerro
    public List<Feature> getFeatures(String filter, String sortBy)  {
1829
        return this.getFeatures(filter, sortBy, true);
1830
    }
1831
1832
    @Override
1833
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1834
        FeatureQuery query = this.createFeatureQuery();
1835
        if( !StringUtils.isEmpty(filter) ) {
1836
            query.setFilter(filter);
1837
        }
1838
        if( !StringUtils.isEmpty(sortBy) ) {
1839
            query.getOrder().add(sortBy, asc);
1840
        }
1841
        return this.getFeatures(query, 100);
1842
    }
1843
1844
    @Override
1845 43550 jjdelcerro
    public List<Feature> getFeatures(FeatureQuery query)  {
1846
        return this.getFeatures(query, 100);
1847
    }
1848
1849
    @Override
1850 42925 jjdelcerro
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1851
        try {
1852
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1853
            return pager.asList();
1854
        } catch (BaseException ex) {
1855
            throw new RuntimeException("Can't create the list of features.", ex);
1856
        }
1857
    }
1858 43020 jjdelcerro
1859
    @Override
1860
    public List<Feature> getFeatures() {
1861
        return this.getFeatures(null, 500);
1862
    }
1863 43152 fdiaz
1864 43215 jjdelcerro
    @Override
1865 43628 jjdelcerro
    public Feature findFirst(String filter) throws DataException {
1866
        return this.findFirst(filter, null, true);
1867
    }
1868
1869
    @Override
1870
    public Feature findFirst(String filter, String sortBy) throws DataException {
1871
        return this.findFirst(filter, sortBy, true);
1872
    }
1873
1874
    @Override
1875
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1876
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1877
        if( set==null || set.isEmpty() ) {
1878
            return null;
1879
        }
1880
        DisposableIterator it = set.iterator();
1881
        Feature f = (Feature) it.next();
1882
        it.dispose();
1883
        return f;
1884
    }
1885
1886
    @Override
1887 40435 jjdelcerro
    public void accept(Visitor visitor) throws BaseException {
1888
        FeatureSet set = getFeatureSet();
1889
        try {
1890
            set.accept(visitor);
1891
        } finally {
1892
            set.dispose();
1893
        }
1894
    }
1895
1896 43215 jjdelcerro
    @Override
1897 40435 jjdelcerro
    public void accept(Visitor visitor, DataQuery dataQuery)
1898 42293 jjdelcerro
        throws BaseException {
1899 40435 jjdelcerro
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1900
        try {
1901
            set.accept(visitor);
1902
        } finally {
1903
            set.dispose();
1904
        }
1905
    }
1906
1907
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1908 42293 jjdelcerro
        throws DataException {
1909
        DefaultFeatureType fType =
1910
            (DefaultFeatureType) this.getFeatureType(featureQuery
1911
                .getFeatureTypeId());
1912
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1913
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1914 40435 jjdelcerro
        }
1915
        return fType;
1916
    }
1917
1918 43215 jjdelcerro
    @Override
1919 40435 jjdelcerro
    public void getFeatureSet(Observer observer) throws DataException {
1920
        checkNotInAppendMode();
1921
        this.getFeatureSet(null, observer);
1922
    }
1923
1924 43215 jjdelcerro
    @Override
1925 40435 jjdelcerro
    public void getFeatureSet(FeatureQuery query, Observer observer)
1926 42293 jjdelcerro
        throws DataException {
1927 40435 jjdelcerro
        class LoadInBackGround implements Runnable {
1928
1929 43215 jjdelcerro
            private final FeatureStore store;
1930
            private final FeatureQuery query;
1931
            private final Observer observer;
1932 40435 jjdelcerro
1933
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1934 42293 jjdelcerro
                Observer observer) {
1935 40435 jjdelcerro
                this.store = store;
1936
                this.query = query;
1937
                this.observer = observer;
1938
            }
1939
1940
            void notify(FeatureStoreNotification theNotification) {
1941
                observer.update(store, theNotification);
1942
            }
1943
1944 43215 jjdelcerro
            @Override
1945 40435 jjdelcerro
            public void run() {
1946
                FeatureSet set = null;
1947
                try {
1948
                    set = store.getFeatureSet(query);
1949
                    notify(new DefaultFeatureStoreNotification(store,
1950 42293 jjdelcerro
                        FeatureStoreNotification.LOAD_FINISHED, set));
1951 40435 jjdelcerro
                } catch (Exception e) {
1952
                    notify(new DefaultFeatureStoreNotification(store,
1953 42293 jjdelcerro
                        FeatureStoreNotification.LOAD_FINISHED, e));
1954 40435 jjdelcerro
                } finally {
1955
                    dispose(set);
1956
                }
1957
            }
1958
        }
1959
1960
        checkNotInAppendMode();
1961
        if (query == null) {
1962
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1963
        }
1964
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1965
        Thread thread = new Thread(task, "Load Feature Set in background");
1966
        thread.start();
1967
    }
1968
1969 43215 jjdelcerro
    @Override
1970 40435 jjdelcerro
    public Feature getFeatureByReference(FeatureReference reference)
1971 42293 jjdelcerro
        throws DataException {
1972 40435 jjdelcerro
        checkNotInAppendMode();
1973
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1974
        FeatureType featureType;
1975
        if (ref.getFeatureTypeId() == null) {
1976
            featureType = this.getDefaultFeatureType();
1977
        } else {
1978
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1979
        }
1980
        return this.getFeatureByReference(reference, featureType);
1981
    }
1982
1983 43215 jjdelcerro
    @Override
1984 40435 jjdelcerro
    public Feature getFeatureByReference(FeatureReference reference,
1985 42293 jjdelcerro
        FeatureType featureType) throws DataException {
1986 40435 jjdelcerro
        checkNotInAppendMode();
1987
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1988
        if (this.mode == MODE_FULLEDIT) {
1989
            Feature f = featureManager.get(reference, this, featureType);
1990
            if (f != null) {
1991
                return f;
1992
            }
1993
        }
1994 41818 fdiaz
1995 42092 fdiaz
        FeatureType sourceFeatureType = featureType;
1996
        if (!this.transforms.isEmpty()) {
1997
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1998
        }
1999
        // TODO comprobar que el id es de este store
2000 41818 fdiaz
2001 42293 jjdelcerro
        DefaultFeature feature =
2002
            new DefaultFeature(this,
2003
                this.provider.getFeatureProviderByReference(
2004
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
2005 40435 jjdelcerro
2006
        if (!this.transforms.isEmpty()) {
2007
            return this.transforms.applyTransform(feature, featureType);
2008
        }
2009
        return feature;
2010
    }
2011
2012
    //
2013
    // ====================================================================
2014
    // Gestion de features
2015
    //
2016 42293 jjdelcerro
2017 40435 jjdelcerro
    private FeatureType fixFeatureType(DefaultFeatureType type)
2018 42293 jjdelcerro
        throws DataException {
2019 40435 jjdelcerro
        FeatureType original = this.getDefaultFeatureType();
2020
2021
        if ((type == null) || type.equals(original)) {
2022
            return original;
2023
        } else {
2024
            if (!type.isSubtypeOf(original)) {
2025
                Iterator iter = this.getFeatureTypes().iterator();
2026
                FeatureType tmpType;
2027
                boolean found = false;
2028
                while (iter.hasNext()) {
2029
                    tmpType = (FeatureType) iter.next();
2030
                    if (type.equals(tmpType)) {
2031
                        return type;
2032
2033 42293 jjdelcerro
                    } else
2034
                        if (type.isSubtypeOf(tmpType)) {
2035
                            found = true;
2036
                            original = tmpType;
2037
                            break;
2038
                        }
2039 40435 jjdelcerro
2040
                }
2041
                if (!found) {
2042
                    throw new IllegalFeatureTypeException(getName());
2043
                }
2044
            }
2045
        }
2046
2047
        // Checks that type has all fields of pk
2048
        // else add the missing attributes at the end.
2049
        if (!original.hasOID()) {
2050
            // Gets original pk attributes
2051 42293 jjdelcerro
            DefaultEditableFeatureType edOriginal =
2052
                (DefaultEditableFeatureType) original.getEditable();
2053 40435 jjdelcerro
            FeatureAttributeDescriptor orgAttr;
2054
            Iterator edOriginalIter = edOriginal.iterator();
2055
            while (edOriginalIter.hasNext()) {
2056
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2057
                if (!orgAttr.isPrimaryKey()) {
2058
                    edOriginalIter.remove();
2059
                }
2060
            }
2061
2062
            // Checks if all pk attributes are in type
2063
            Iterator typeIterator;
2064
            edOriginalIter = edOriginal.iterator();
2065
            FeatureAttributeDescriptor attr;
2066
            while (edOriginalIter.hasNext()) {
2067
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2068
                typeIterator = type.iterator();
2069
                while (typeIterator.hasNext()) {
2070
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
2071
                    if (attr.getName().equals(orgAttr.getName())) {
2072
                        edOriginalIter.remove();
2073
                        break;
2074
                    }
2075
                }
2076
            }
2077
2078
            // add missing pk attributes if any
2079
            if (edOriginal.size() > 0) {
2080
                boolean isEditable = type instanceof DefaultEditableFeatureType;
2081 42293 jjdelcerro
                DefaultEditableFeatureType edType =
2082
                    (DefaultEditableFeatureType) original.getEditable();
2083 40435 jjdelcerro
                edType.clear();
2084
                edType.addAll(type);
2085
                edType.addAll(edOriginal);
2086
                if (!isEditable) {
2087
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
2088
                }
2089
            }
2090
2091
        }
2092
2093
        return type;
2094
    }
2095
2096 43215 jjdelcerro
    @Override
2097 40435 jjdelcerro
    public void validateFeatures(int mode) throws DataException {
2098
        FeatureSet collection = null;
2099
        DisposableIterator iter = null;
2100
        try {
2101 43642 jjdelcerro
            FeatureRules rules = this.getDefaultFeatureType().getRules();
2102
            if( rules==null || rules.isEmpty() ) {
2103
                return;
2104
            }
2105 40435 jjdelcerro
            checkNotInAppendMode();
2106
            collection = this.getFeatureSet();
2107
            iter = collection.fastIterator();
2108
            long previousVersionOfUpdate = currentVersionOfUpdate();
2109
            while (iter.hasNext()) {
2110
                ((DefaultFeature) iter.next()).validate(mode);
2111
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
2112
                    throw new ConcurrentDataModificationException(getName());
2113
                }
2114
            }
2115
        } catch (Exception e) {
2116
            throw new ValidateFeaturesException(e, getName());
2117
        } finally {
2118 43642 jjdelcerro
            DisposeUtils.disposeQuietly(iter);
2119
            DisposeUtils.disposeQuietly(collection);
2120 40435 jjdelcerro
        }
2121
    }
2122
2123 43215 jjdelcerro
    @Override
2124 40435 jjdelcerro
    public FeatureType getDefaultFeatureType() throws DataException {
2125
        try {
2126 41818 fdiaz
2127 40435 jjdelcerro
            if (isEditing()) {
2128 42293 jjdelcerro
                FeatureType auxFeatureType =
2129
                    featureTypeManager.getType(defaultFeatureType.getId());
2130 40435 jjdelcerro
                if (auxFeatureType != null) {
2131
                    return avoidEditable(auxFeatureType);
2132
                }
2133
            }
2134
            FeatureType type = this.transforms.getDefaultFeatureType();
2135
            if (type != null) {
2136
                return avoidEditable(type);
2137
            }
2138 41818 fdiaz
2139 40435 jjdelcerro
            return avoidEditable(defaultFeatureType);
2140 41818 fdiaz
2141 40435 jjdelcerro
        } catch (Exception e) {
2142
            throw new GetFeatureTypeException(e, getName());
2143
        }
2144
    }
2145 41818 fdiaz
2146 40435 jjdelcerro
    private FeatureType avoidEditable(FeatureType ft) {
2147
        if (ft instanceof EditableFeatureType) {
2148
            return ((EditableFeatureType) ft).getNotEditableCopy();
2149
        } else {
2150
            return ft;
2151
        }
2152
    }
2153
2154 43215 jjdelcerro
    @Override
2155 40435 jjdelcerro
    public FeatureType getFeatureType(String featureTypeId)
2156 42293 jjdelcerro
        throws DataException {
2157 40435 jjdelcerro
        if (featureTypeId == null) {
2158
            return this.getDefaultFeatureType();
2159
        }
2160
        try {
2161
            if (isEditing()) {
2162 42293 jjdelcerro
                FeatureType auxFeatureType =
2163
                    featureTypeManager.getType(featureTypeId);
2164 40435 jjdelcerro
                if (auxFeatureType != null) {
2165
                    return auxFeatureType;
2166
                }
2167
            }
2168
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2169
            if (type != null) {
2170
                return type;
2171
            }
2172
            Iterator iter = this.featureTypes.iterator();
2173
            while (iter.hasNext()) {
2174
                type = (FeatureType) iter.next();
2175
                if (type.getId().equals(featureTypeId)) {
2176
                    return type;
2177
                }
2178
            }
2179
            return null;
2180
        } catch (Exception e) {
2181
            throw new GetFeatureTypeException(e, getName());
2182
        }
2183
    }
2184
2185
    public FeatureType getProviderDefaultFeatureType() {
2186
        return defaultFeatureType;
2187
    }
2188
2189 43215 jjdelcerro
    @Override
2190 40435 jjdelcerro
    public List getFeatureTypes() throws DataException {
2191
        try {
2192
            List types;
2193
            if (isEditing()) {
2194
                types = new ArrayList();
2195
                Iterator it = featureTypes.iterator();
2196
                while (it.hasNext()) {
2197
                    FeatureType type = (FeatureType) it.next();
2198 42293 jjdelcerro
                    FeatureType typeaux =
2199
                        featureTypeManager.getType(type.getId());
2200 40435 jjdelcerro
                    if (typeaux != null) {
2201
                        types.add(typeaux);
2202
                    } else {
2203
                        types.add(type);
2204
                    }
2205
                }
2206
                it = featureTypeManager.newsIterator();
2207
                while (it.hasNext()) {
2208
                    FeatureType type = (FeatureType) it.next();
2209
                    types.add(type);
2210
                }
2211
            } else {
2212
                types = this.transforms.getFeatureTypes();
2213
                if (types == null) {
2214
                    types = featureTypes;
2215
                }
2216
            }
2217
            return Collections.unmodifiableList(types);
2218
        } catch (Exception e) {
2219
            throw new GetFeatureTypeException(e, getName());
2220
        }
2221
    }
2222
2223
    public List getProviderFeatureTypes() throws DataException {
2224
        return Collections.unmodifiableList(this.featureTypes);
2225
    }
2226
2227 43215 jjdelcerro
    @Override
2228 40435 jjdelcerro
    public Feature createFeature(FeatureProvider data) throws DataException {
2229
        DefaultFeature feature = new DefaultFeature(this, data);
2230
        return feature;
2231
    }
2232
2233
    public Feature createFeature(FeatureProvider data, FeatureType type)
2234 42293 jjdelcerro
        throws DataException {
2235 40435 jjdelcerro
        // FIXME: falta por implementar
2236
        // Comprobar si es un subtipo del feature de data
2237
        // y construir un feature usando el subtipo.
2238
        // Probablemente requiera generar una copia del data.
2239
        throw new NotYetImplemented();
2240
    }
2241
2242 43215 jjdelcerro
    @Override
2243 40435 jjdelcerro
    public EditableFeature createNewFeature(FeatureType type,
2244 42293 jjdelcerro
        Feature defaultValues) throws DataException {
2245 40435 jjdelcerro
        try {
2246
            FeatureProvider data = createNewFeatureProvider(type);
2247 42293 jjdelcerro
            DefaultEditableFeature feature =
2248
                new DefaultEditableFeature(this, data);
2249 40435 jjdelcerro
            feature.initializeValues(defaultValues);
2250
            data.setNew(true);
2251 41818 fdiaz
2252 40435 jjdelcerro
            return feature;
2253
        } catch (Exception e) {
2254
            throw new CreateFeatureException(e, getName());
2255
        }
2256
    }
2257
2258
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2259 42293 jjdelcerro
        throws DataException {
2260 40435 jjdelcerro
        type = this.fixFeatureType((DefaultFeatureType) type);
2261
        FeatureProvider data = this.provider.createFeatureProvider(type);
2262
        data.setNew(true);
2263
        if (type.hasOID() && (data.getOID() == null)) {
2264
            data.setOID(this.provider.createNewOID());
2265
        } else {
2266
            data.setOID(this.getTemporalOID());
2267
        }
2268
        return data;
2269
2270
    }
2271
2272 43215 jjdelcerro
    @Override
2273 40435 jjdelcerro
    public EditableFeature createNewFeature(FeatureType type,
2274 42293 jjdelcerro
        boolean defaultValues) throws DataException {
2275 40435 jjdelcerro
        try {
2276
            FeatureProvider data = createNewFeatureProvider(type);
2277 42293 jjdelcerro
            DefaultEditableFeature feature =
2278
                new DefaultEditableFeature(this, data);
2279 40435 jjdelcerro
            if (defaultValues) {
2280
                feature.initializeValues();
2281
            }
2282
            return feature;
2283
        } catch (Exception e) {
2284
            throw new CreateFeatureException(e, getName());
2285
        }
2286
    }
2287
2288 43215 jjdelcerro
    @Override
2289 40435 jjdelcerro
    public EditableFeature createNewFeature(boolean defaultValues)
2290 42293 jjdelcerro
        throws DataException {
2291 40435 jjdelcerro
        return this.createNewFeature(this.getDefaultFeatureType(),
2292 42293 jjdelcerro
            defaultValues);
2293 40435 jjdelcerro
    }
2294
2295 43215 jjdelcerro
    @Override
2296 40435 jjdelcerro
    public EditableFeature createNewFeature() throws DataException {
2297
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2298
    }
2299
2300 43215 jjdelcerro
    @Override
2301 42293 jjdelcerro
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2302
        FeatureType ft = this.getDefaultFeatureType();
2303
        EditableFeature f = this.createNewFeature(ft, false);
2304 43215 jjdelcerro
                for( FeatureAttributeDescriptor desc : ft ) {
2305
                        try {
2306
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2307
                        } catch(Throwable th) {
2308
                                // Ignore
2309
                        }
2310
                }
2311 42293 jjdelcerro
        return f;
2312
    }
2313
2314 43215 jjdelcerro
    @Override
2315 40435 jjdelcerro
    public EditableFeatureType createFeatureType() {
2316 43739 jjdelcerro
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2317 40435 jjdelcerro
        return ftype;
2318
    }
2319
2320 43215 jjdelcerro
    @Override
2321 40435 jjdelcerro
    public EditableFeatureType createFeatureType(String id) {
2322 43739 jjdelcerro
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2323 40435 jjdelcerro
        return ftype;
2324
    }
2325
2326
    //
2327
    // ====================================================================
2328
    // Index related methods
2329
    //
2330 42293 jjdelcerro
2331 43215 jjdelcerro
    @Override
2332 40435 jjdelcerro
    public FeatureIndexes getIndexes() {
2333
        return this.indexes;
2334
    }
2335
2336 43215 jjdelcerro
    @Override
2337 40435 jjdelcerro
    public FeatureIndex createIndex(FeatureType featureType,
2338 42293 jjdelcerro
        String attributeName, String indexName) throws DataException {
2339 40435 jjdelcerro
        return createIndex(null, featureType, attributeName, indexName);
2340
    }
2341
2342 43215 jjdelcerro
    @Override
2343 40435 jjdelcerro
    public FeatureIndex createIndex(String indexTypeName,
2344 42293 jjdelcerro
        FeatureType featureType, String attributeName, String indexName)
2345
        throws DataException {
2346 40435 jjdelcerro
2347
        return createIndex(indexTypeName, featureType, attributeName,
2348 42293 jjdelcerro
            indexName, false, null);
2349 40435 jjdelcerro
    }
2350
2351 43215 jjdelcerro
    @Override
2352 40435 jjdelcerro
    public FeatureIndex createIndex(FeatureType featureType,
2353 42293 jjdelcerro
        String attributeName, String indexName, Observer observer)
2354
        throws DataException {
2355 40435 jjdelcerro
        return createIndex(null, featureType, attributeName, indexName,
2356 42293 jjdelcerro
            observer);
2357 40435 jjdelcerro
    }
2358
2359 43215 jjdelcerro
    @Override
2360 40435 jjdelcerro
    public FeatureIndex createIndex(String indexTypeName,
2361 42293 jjdelcerro
        FeatureType featureType, String attributeName, String indexName,
2362
        final Observer observer) throws DataException {
2363 40435 jjdelcerro
2364
        return createIndex(indexTypeName, featureType, attributeName,
2365 42293 jjdelcerro
            indexName, true, observer);
2366 40435 jjdelcerro
    }
2367
2368
    private FeatureIndex createIndex(String indexTypeName,
2369 42293 jjdelcerro
        FeatureType featureType, String attributeName, String indexName,
2370
        boolean background, final Observer observer) throws DataException {
2371 40435 jjdelcerro
2372
        checkNotInAppendMode();
2373 43215 jjdelcerro
        FeatureIndexProviderServices index;
2374
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2375 42293 jjdelcerro
                featureType, indexName,
2376
                featureType.getAttributeDescriptor(attributeName));
2377 40435 jjdelcerro
2378
        try {
2379
            index.fill(background, observer);
2380
        } catch (FeatureIndexException e) {
2381
            throw new InitializeException(index.getName(), e);
2382
        }
2383
2384
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2385
        return index;
2386
    }
2387
2388
    //
2389
    // ====================================================================
2390
    // Transforms related methods
2391
    //
2392 42293 jjdelcerro
2393 43215 jjdelcerro
    @Override
2394 40435 jjdelcerro
    public FeatureStoreTransforms getTransforms() {
2395
        return this.transforms;
2396
    }
2397
2398 43215 jjdelcerro
    @Override
2399 40435 jjdelcerro
    public FeatureQuery createFeatureQuery() {
2400
        return new DefaultFeatureQuery();
2401
    }
2402
2403 43215 jjdelcerro
    @Override
2404 40435 jjdelcerro
    public DataQuery createQuery() {
2405
        return createFeatureQuery();
2406
    }
2407
2408
    //
2409
    // ====================================================================
2410
    // UndoRedo related methods
2411
    //
2412 42293 jjdelcerro
2413 43215 jjdelcerro
    @Override
2414 40435 jjdelcerro
    public boolean canRedo() {
2415
        return commands.canRedo();
2416
    }
2417
2418 43215 jjdelcerro
    @Override
2419 40435 jjdelcerro
    public boolean canUndo() {
2420
        return commands.canUndo();
2421
    }
2422
2423 43215 jjdelcerro
    @Override
2424 40435 jjdelcerro
    public void redo(int num) throws RedoException {
2425
        for (int i = 0; i < num; i++) {
2426
            redo();
2427
        }
2428
    }
2429
2430 43215 jjdelcerro
    @Override
2431 40435 jjdelcerro
    public void undo(int num) throws UndoException {
2432
        for (int i = 0; i < num; i++) {
2433
            undo();
2434
        }
2435
    }
2436
2437
    //
2438
    // ====================================================================
2439
    // Metadata related methods
2440
    //
2441 42293 jjdelcerro
2442 43215 jjdelcerro
    @Override
2443 40435 jjdelcerro
    public Object getMetadataID() {
2444
        return this.provider.getSourceId();
2445
    }
2446
2447 43215 jjdelcerro
    @Override
2448 40435 jjdelcerro
    public void delegate(DynObject dynObject) {
2449
        this.metadata.delegate(dynObject);
2450
    }
2451
2452 43215 jjdelcerro
    @Override
2453 40435 jjdelcerro
    public DynClass getDynClass() {
2454
        return this.metadata.getDynClass();
2455
    }
2456
2457 43215 jjdelcerro
    @Override
2458 42293 jjdelcerro
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2459
                if( this.transforms.hasDynValue(name) ) {
2460
                        return this.transforms.getDynValue(name);
2461
                }
2462
                if (this.metadata.hasDynValue(name)) {
2463
                        return this.metadata.getDynValue(name);
2464
                }
2465
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2466
                        return this.provider.getProviderName();
2467
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2468
                        return this.provider.getSourceId();
2469
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2470
                        try {
2471
                                return this.getDefaultFeatureType();
2472
                        } catch (DataException e) {
2473
                                return null;
2474
                        }
2475
                }
2476
                return this.metadata.getDynValue(name);
2477
        }
2478 40435 jjdelcerro
2479 43215 jjdelcerro
    @Override
2480 40435 jjdelcerro
    public boolean hasDynValue(String name) {
2481 42293 jjdelcerro
                if( this.transforms.hasDynValue(name) ) {
2482
                        return true;
2483
                }
2484 40435 jjdelcerro
        return this.metadata.hasDynValue(name);
2485
    }
2486 43270 fdiaz
2487 43215 jjdelcerro
    @Override
2488 43246 jjdelcerro
    public boolean hasDynMethod(String name) {
2489
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2490
    }
2491 43270 fdiaz
2492 43246 jjdelcerro
    @Override
2493 40435 jjdelcerro
    public void implement(DynClass dynClass) {
2494
        this.metadata.implement(dynClass);
2495
    }
2496
2497 43215 jjdelcerro
    @Override
2498 42775 jjdelcerro
    public Object invokeDynMethod(String name, Object[] args)
2499 42293 jjdelcerro
        throws DynMethodException {
2500 42775 jjdelcerro
        return this.metadata.invokeDynMethod(this, name, args);
2501 40435 jjdelcerro
    }
2502
2503 43215 jjdelcerro
    @Override
2504 42775 jjdelcerro
    public Object invokeDynMethod(int code, Object[] args)
2505 42293 jjdelcerro
        throws DynMethodException {
2506 42775 jjdelcerro
        return this.metadata.invokeDynMethod(this, code, args);
2507 40435 jjdelcerro
    }
2508
2509 43215 jjdelcerro
    @Override
2510 40435 jjdelcerro
    public void setDynValue(String name, Object value)
2511 42293 jjdelcerro
        throws DynFieldNotFoundException {
2512
                if( this.transforms.hasDynValue(name) ) {
2513
                        this.transforms.setDynValue(name, value);
2514
                        return;
2515
                }
2516 40435 jjdelcerro
        this.metadata.setDynValue(name, value);
2517
2518
    }
2519
2520
    /*
2521
     * (non-Javadoc)
2522 41818 fdiaz
     *
2523 40435 jjdelcerro
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2524
     */
2525 43215 jjdelcerro
    @Override
2526 40435 jjdelcerro
    public Set getMetadataChildren() {
2527
        return this.metadataChildren;
2528
    }
2529
2530
    /*
2531
     * (non-Javadoc)
2532 41818 fdiaz
     *
2533 40435 jjdelcerro
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2534
     */
2535 43215 jjdelcerro
    @Override
2536 40435 jjdelcerro
    public String getMetadataName() {
2537
        return this.provider.getProviderName();
2538
    }
2539
2540
    public FeatureTypeManager getFeatureTypeManager() {
2541
        return this.featureTypeManager;
2542
    }
2543
2544 43215 jjdelcerro
    @Override
2545 40435 jjdelcerro
    public long getFeatureCount() throws DataException {
2546
        if (featureCount == null) {
2547 43215 jjdelcerro
            featureCount = this.provider.getFeatureCount();
2548 40435 jjdelcerro
        }
2549 42556 dmartinezizquierdo
        if (this.isEditing()) {
2550
            if(this.isAppending()) {
2551
                try{
2552
                    throw new IllegalStateException();
2553
                } catch(IllegalStateException e) {
2554 43840 jjdelcerro
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND",e);
2555 42556 dmartinezizquierdo
                }
2556
                return -1;
2557
            } else {
2558 43215 jjdelcerro
                return featureCount
2559 42556 dmartinezizquierdo
                    + this.featureManager.getDeltaSize();
2560
            }
2561 40435 jjdelcerro
        }
2562 43215 jjdelcerro
        return featureCount;
2563 40435 jjdelcerro
    }
2564
2565
    private Long getTemporalOID() {
2566 43215 jjdelcerro
        return this.temporalOid++;
2567 40435 jjdelcerro
    }
2568
2569 43215 jjdelcerro
    @Override
2570 40435 jjdelcerro
    public FeatureType getProviderFeatureType(String featureTypeId) {
2571
        if (featureTypeId == null) {
2572
            return this.defaultFeatureType;
2573
        }
2574
        FeatureType type;
2575
        Iterator iter = this.featureTypes.iterator();
2576
        while (iter.hasNext()) {
2577
            type = (FeatureType) iter.next();
2578
            if (type.getId().equals(featureTypeId)) {
2579
                return type;
2580
            }
2581
        }
2582
        return null;
2583
    }
2584
2585 43215 jjdelcerro
    @Override
2586 40435 jjdelcerro
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2587
        return ((DefaultFeature) feature).getData();
2588
    }
2589
2590 43215 jjdelcerro
    @Override
2591 40435 jjdelcerro
    public DataStore getStore() {
2592
        return this;
2593
    }
2594
2595 43215 jjdelcerro
    @Override
2596 40435 jjdelcerro
    public FeatureStore getFeatureStore() {
2597
        return this;
2598
    }
2599
2600 43215 jjdelcerro
    @Override
2601 43056 jjdelcerro
    public void createCache(String name, DynObject parameters)
2602
        throws DataException {
2603
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2604
        if (cache == null) {
2605
            throw new CreateException("FeaureCacheProvider", null);
2606
        }
2607
        cache.apply(this, provider);
2608
        provider = cache;
2609 40435 jjdelcerro
2610 43056 jjdelcerro
        featureCount = null;
2611
    }
2612
2613 43215 jjdelcerro
    @Override
2614 43056 jjdelcerro
    public FeatureCache getCache() {
2615
        return cache;
2616
    }
2617
2618 43215 jjdelcerro
    @Override
2619 40435 jjdelcerro
    public void clear() {
2620
        if (metadata != null) {
2621
            metadata.clear();
2622
        }
2623
    }
2624
2625 43215 jjdelcerro
    @Override
2626 40435 jjdelcerro
    public String getName() {
2627 43215 jjdelcerro
        if( this.provider != null ) {
2628
            return this.provider.getName();
2629
        }
2630
        if( this.parameters instanceof HasAFile ) {
2631
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2632
        }
2633
        return "unknow";
2634 40435 jjdelcerro
    }
2635
2636 43215 jjdelcerro
    @Override
2637 40435 jjdelcerro
    public String getFullName() {
2638 42049 jjdelcerro
        try {
2639 43215 jjdelcerro
            if( this.provider!=null ) {
2640
                return this.provider.getFullName();
2641
            }
2642
            if( this.parameters instanceof HasAFile ) {
2643
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2644
            }
2645
            return null;
2646 42293 jjdelcerro
        } catch(Throwable th) {
2647 42049 jjdelcerro
            return null;
2648
        }
2649 40435 jjdelcerro
    }
2650
2651 43215 jjdelcerro
    @Override
2652 40435 jjdelcerro
    public String getProviderName() {
2653 43215 jjdelcerro
        if( this.provider!=null ) {
2654
            return this.provider.getProviderName();
2655
        }
2656
        if( this.parameters != null ) {
2657
            return this.parameters.getDataStoreName();
2658
        }
2659
        return null;
2660 43270 fdiaz
2661 40435 jjdelcerro
    }
2662
2663 43215 jjdelcerro
    @Override
2664 40435 jjdelcerro
    public boolean isKnownEnvelope() {
2665
        return this.provider.isKnownEnvelope();
2666
    }
2667
2668 43215 jjdelcerro
    @Override
2669 40435 jjdelcerro
    public boolean hasRetrievedFeaturesLimit() {
2670
        return this.provider.hasRetrievedFeaturesLimit();
2671
    }
2672
2673 43215 jjdelcerro
    @Override
2674 40435 jjdelcerro
    public int getRetrievedFeaturesLimit() {
2675
        return this.provider.getRetrievedFeaturesLimit();
2676
    }
2677
2678 43215 jjdelcerro
    @Override
2679 41818 fdiaz
    public Interval getInterval() {
2680 43135 jjdelcerro
        if( this.timeSupport!=null ) {
2681
            return this.timeSupport.getInterval();
2682
        }
2683 40435 jjdelcerro
        return this.provider.getInterval();
2684
    }
2685
2686 43215 jjdelcerro
    @Override
2687 41818 fdiaz
    public Collection getTimes() {
2688 43135 jjdelcerro
        if( this.timeSupport!=null ) {
2689
            return this.timeSupport.getTimes();
2690
        }
2691 40435 jjdelcerro
        return this.provider.getTimes();
2692
    }
2693
2694 43215 jjdelcerro
    @Override
2695 41818 fdiaz
    public Collection getTimes(Interval interval) {
2696 43135 jjdelcerro
        if( this.timeSupport!=null ) {
2697
            return this.timeSupport.getTimes(interval);
2698
        }
2699 40435 jjdelcerro
        return this.provider.getTimes(interval);
2700
    }
2701 41818 fdiaz
2702 43135 jjdelcerro
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2703 43610 jjdelcerro
        if( this.isEditing() ) {
2704
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2705 43135 jjdelcerro
        }
2706 43610 jjdelcerro
        if( !this.transforms.isEmpty() ) {
2707
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2708 43135 jjdelcerro
        }
2709 43610 jjdelcerro
        FeatureType ft = this.defaultFeatureType;
2710
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2711
        if( attr == null ) {
2712 43135 jjdelcerro
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2713
        }
2714 43610 jjdelcerro
        EditableFeatureType eft = ft.getEditable();
2715
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2716
        if( attr != null ) {
2717
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2718
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2719
            }
2720
            eft.remove(attr.getName());
2721
        }
2722
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2723
            timeSupport.getAttributeName(),
2724
            timeSupport.getDataType()
2725
        );
2726
        attrTime.setIsTime(true);
2727
        attrTime.setFeatureAttributeEmulator(timeSupport);
2728
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2729
        this.defaultFeatureType = eft.getNotEditableCopy();
2730
2731 43135 jjdelcerro
        this.timeSupport = timeSupport;
2732
    }
2733 43152 fdiaz
2734 43215 jjdelcerro
    @Override
2735 43840 jjdelcerro
    @SuppressWarnings("CloneDoesntCallSuperClone")
2736 40435 jjdelcerro
    public Object clone() throws CloneNotSupportedException {
2737 41818 fdiaz
2738 40435 jjdelcerro
        DataStoreParameters dsp = getParameters();
2739 41818 fdiaz
2740 40435 jjdelcerro
        DefaultFeatureStore cloned_store = null;
2741 41818 fdiaz
2742 40435 jjdelcerro
        try {
2743
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2744 42293 jjdelcerro
                openStore(this.getProviderName(), dsp);
2745 40435 jjdelcerro
            if (transforms != null) {
2746
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2747 41093 jldominguez
                cloned_store.transforms.setStoreForClone(cloned_store);
2748 40435 jjdelcerro
            }
2749
        } catch (Exception e) {
2750
            throw new CloneException(e);
2751 41818 fdiaz
        }
2752 40435 jjdelcerro
        return cloned_store;
2753 41818 fdiaz
2754 40435 jjdelcerro
    }
2755 41818 fdiaz
2756 43215 jjdelcerro
    @Override
2757 41818 fdiaz
    public Feature getFeature(DynObject dynobject) {
2758 42293 jjdelcerro
        if (dynobject instanceof DynObjectFeatureFacade){
2759
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2760 41818 fdiaz
            return f;
2761
        }
2762
        return null;
2763
    }
2764 42533 dmartinezizquierdo
2765 43215 jjdelcerro
    @Override
2766 42293 jjdelcerro
    public Iterator iterator() {
2767
        try {
2768
            return this.getFeatureSet().fastIterator();
2769
        } catch (DataException ex) {
2770
            throw new RuntimeException(ex);
2771
        }
2772
    }
2773 43020 jjdelcerro
2774
    @Override
2775 43521 jjdelcerro
    public ExpressionBuilder createExpressionBuilder() {
2776 43020 jjdelcerro
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2777 43088 jjdelcerro
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2778 43020 jjdelcerro
        }
2779
        return new SQLBuilderBase();
2780
    }
2781 43062 jjdelcerro
2782 43521 jjdelcerro
    @Override
2783
    public ExpressionBuilder createExpression() {
2784
        return createExpressionBuilder();
2785
    }
2786 43152 fdiaz
2787 43062 jjdelcerro
    public FeatureSet features() throws DataException {
2788
        // This is to avoid jython to create a property with this name
2789
        // to access method getFeatures.
2790
        return this.getFeatureSet();
2791
    }
2792 43152 fdiaz
2793
    @Override
2794 43190 jjdelcerro
    public DataStoreProviderFactory getProviderFactory() {
2795 43152 fdiaz
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2796
        return factory;
2797
    }
2798
2799
    @Override
2800
    public void useCache(String providerName, DynObject parameters) throws DataException {
2801
        throw new UnsupportedOperationException();
2802
    }
2803 43270 fdiaz
2804 43215 jjdelcerro
    @Override
2805
    public boolean isBroken() {
2806
        return this.state.isBroken();
2807
    }
2808
2809
    @Override
2810
    public Throwable getBreakingsCause() {
2811
            return this.state.getBreakingsCause();
2812
    }
2813 43371 fdiaz
2814
    @Override
2815
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2816 43705 jjdelcerro
      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2817
      if( !factory.supportNumericOID() ) {
2818
          return null;
2819
      }
2820 43371 fdiaz
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2821
      return wrappedIndex;
2822
  }
2823 43824 jjdelcerro
2824
    @Override
2825
    public FeatureReference getFeatureReference(String code) {
2826
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2827
        return featureReference;
2828
    }
2829 42293 jjdelcerro
}