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

History | View | Annotate | Download (141 KB)

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