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

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