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

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