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

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