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

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