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

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