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

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