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

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