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

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