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

History | View | Annotate | Download (103 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 42293 jjdelcerro
25 40435 jjdelcerro
package org.gvsig.fmap.dal.feature.impl;
26
27 43840 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.editing.memory.SpatialManager;
28
import org.gvsig.fmap.dal.feature.impl.editing.memory.FeatureTypeManager;
29
import org.gvsig.fmap.dal.feature.impl.editing.memory.FeatureManager;
30 43152 fdiaz
31 40435 jjdelcerro
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.Collections;
34
import java.util.HashMap;
35
import java.util.HashSet;
36
import java.util.Iterator;
37
import java.util.List;
38
import java.util.Map;
39
import java.util.Map.Entry;
40
import java.util.Set;
41 43371 fdiaz
42 43215 jjdelcerro
import org.apache.commons.io.FilenameUtils;
43 44190 jjdelcerro
import org.apache.commons.io.IOUtils;
44 43533 jjdelcerro
import org.apache.commons.lang3.StringUtils;
45 44190 jjdelcerro
import org.apache.commons.lang3.mutable.MutableObject;
46 40435 jjdelcerro
import org.cresques.cts.IProjection;
47 44023 jjdelcerro
import org.gvsig.expressionevaluator.Expression;
48 44042 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder;
49
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
50 43152 fdiaz
51 40435 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
52
import org.gvsig.fmap.dal.DataManager;
53
import org.gvsig.fmap.dal.DataQuery;
54
import org.gvsig.fmap.dal.DataServerExplorer;
55 44160 jjdelcerro
import org.gvsig.fmap.dal.DataServerExplorer.DataResource;
56 40435 jjdelcerro
import org.gvsig.fmap.dal.DataSet;
57
import org.gvsig.fmap.dal.DataStore;
58
import org.gvsig.fmap.dal.DataStoreNotification;
59
import org.gvsig.fmap.dal.DataStoreParameters;
60 43152 fdiaz
import org.gvsig.fmap.dal.DataStoreProviderFactory;
61 44259 jjdelcerro
import org.gvsig.fmap.dal.StoresRepository;
62 40435 jjdelcerro
import org.gvsig.fmap.dal.exception.CloneException;
63
import org.gvsig.fmap.dal.exception.CloseException;
64
import org.gvsig.fmap.dal.exception.CreateException;
65
import org.gvsig.fmap.dal.exception.DataException;
66
import org.gvsig.fmap.dal.exception.InitializeException;
67
import org.gvsig.fmap.dal.exception.OpenException;
68
import org.gvsig.fmap.dal.exception.ReadException;
69
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
70 40597 jldominguez
import org.gvsig.fmap.dal.exception.WriteException;
71 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
72 43610 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
73 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
74
import org.gvsig.fmap.dal.feature.Feature;
75
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
76 43981 omartinez
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
77 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureCache;
78
import org.gvsig.fmap.dal.feature.FeatureIndex;
79
import org.gvsig.fmap.dal.feature.FeatureIndexes;
80
import org.gvsig.fmap.dal.feature.FeatureLocks;
81
import org.gvsig.fmap.dal.feature.FeatureQuery;
82
import org.gvsig.fmap.dal.feature.FeatureReference;
83
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
84 43642 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureRules;
85 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSelection;
86
import org.gvsig.fmap.dal.feature.FeatureSet;
87
import org.gvsig.fmap.dal.feature.FeatureStore;
88
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
89 43705 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
90 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
91
import org.gvsig.fmap.dal.feature.FeatureType;
92
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
93 43135 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreTimeSupport;
94 43215 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreTransform;
95 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
96
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
97
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
98
import org.gvsig.fmap.dal.feature.exception.DataExportException;
99
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
100
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
101
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
102
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
103
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
104
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
105
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
106
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
107 40597 jldominguez
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
108 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindFeatureTypeException;
109
import org.gvsig.fmap.dal.feature.exception.PersistenceStoreAlreadyLoadedException;
110
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
111
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
112
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
113
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
114
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
115
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
116
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
117
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
118
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
119
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
120
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
121 42775 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
122 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
123
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
124 42925 jjdelcerro
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
125 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
126
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
127
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
128
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
129
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
130
import org.gvsig.fmap.dal.feature.spi.cache.FeatureCacheProvider;
131
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
132 44251 jjdelcerro
import org.gvsig.fmap.dal.impl.DALResourcesStorage;
133 40435 jjdelcerro
import org.gvsig.fmap.dal.impl.DefaultDataManager;
134
import org.gvsig.fmap.dal.resource.Resource;
135 43020 jjdelcerro
import org.gvsig.fmap.dal.spi.DataStoreInitializer2;
136 40435 jjdelcerro
import org.gvsig.fmap.dal.spi.DataStoreProvider;
137 43020 jjdelcerro
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
138 44190 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
139 43358 jjdelcerro
import org.gvsig.fmap.geom.SpatialIndex;
140 40435 jjdelcerro
import org.gvsig.fmap.geom.primitive.Envelope;
141
import org.gvsig.metadata.MetadataLocator;
142
import org.gvsig.metadata.MetadataManager;
143
import org.gvsig.metadata.exceptions.MetadataException;
144
import org.gvsig.timesupport.Interval;
145
import org.gvsig.tools.ToolsLocator;
146
import org.gvsig.tools.dispose.DisposableIterator;
147 43642 jjdelcerro
import org.gvsig.tools.dispose.DisposeUtils;
148 40435 jjdelcerro
import org.gvsig.tools.dispose.impl.AbstractDisposable;
149
import org.gvsig.tools.dynobject.DelegatedDynObject;
150
import org.gvsig.tools.dynobject.DynClass;
151
import org.gvsig.tools.dynobject.DynObject;
152
import org.gvsig.tools.dynobject.DynObjectManager;
153 43246 jjdelcerro
import org.gvsig.tools.dynobject.DynObject_v2;
154 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynStruct;
155
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
156
import org.gvsig.tools.dynobject.exception.DynMethodException;
157
import org.gvsig.tools.exception.BaseException;
158
import org.gvsig.tools.exception.NotYetImplemented;
159 41928 jjdelcerro
import org.gvsig.tools.identitymanagement.SimpleIdentityManager;
160 40435 jjdelcerro
import org.gvsig.tools.observer.Observable;
161
import org.gvsig.tools.observer.Observer;
162
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
163
import org.gvsig.tools.persistence.PersistenceManager;
164
import org.gvsig.tools.persistence.Persistent;
165
import org.gvsig.tools.persistence.PersistentState;
166
import org.gvsig.tools.persistence.exception.PersistenceException;
167
import org.gvsig.tools.undo.RedoException;
168
import org.gvsig.tools.undo.UndoException;
169
import org.gvsig.tools.undo.command.Command;
170 43215 jjdelcerro
import org.gvsig.tools.util.HasAFile;
171 44251 jjdelcerro
import org.gvsig.tools.util.ResourcesStorage;
172 44259 jjdelcerro
import org.gvsig.tools.util.UnmodifiableBasicMap;
173
import org.gvsig.tools.util.UnmodifiableBasicSet;
174
import org.gvsig.tools.util.UnmodifiableBasicSetChained;
175 44190 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
176 40435 jjdelcerro
import org.gvsig.tools.visitor.Visitor;
177 43152 fdiaz
178 42533 dmartinezizquierdo
import org.slf4j.Logger;
179
import org.slf4j.LoggerFactory;
180 40435 jjdelcerro
181 44190 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
182 41243 jjdelcerro
public class DefaultFeatureStore extends AbstractDisposable implements
183 43020 jjdelcerro
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
184 40435 jjdelcerro
185
    private static final Logger LOG = LoggerFactory
186 42293 jjdelcerro
        .getLogger(DefaultFeatureStore.class);
187 40435 jjdelcerro
188
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
189
190
    private DataStoreParameters parameters = null;
191
    private FeatureSelection selection;
192
    private FeatureLocks locks;
193
194 42293 jjdelcerro
    private DelegateWeakReferencingObservable delegateObservable =
195
        new DelegateWeakReferencingObservable(this);
196 40435 jjdelcerro
197
    private FeatureCommandsStack commands;
198 43841 jjdelcerro
199
    /*
200
    TODO: Sustituir estos tres manager por un EditingManager
201
    */
202 40435 jjdelcerro
    private FeatureTypeManager featureTypeManager;
203
    private FeatureManager featureManager;
204
    private SpatialManager spatialManager;
205
206
    private FeatureType defaultFeatureType = null;
207
    private List featureTypes = new ArrayList();
208
209
    private int mode = MODE_QUERY;
210
    private long versionOfUpdate = 0;
211
    private boolean hasStrongChanges = true;
212
    private boolean hasInserts = true;
213
214
    private DefaultDataManager dataManager = null;
215
216
    private FeatureStoreProvider provider = null;
217
218
    private DefaultFeatureIndexes indexes;
219
220
    private DefaultFeatureStoreTransforms transforms;
221
222
    DelegatedDynObject metadata;
223 41818 fdiaz
224 40435 jjdelcerro
    private Set metadataChildren;
225
226
    private Long featureCount = null;
227
228
    private long temporalOid = 0;
229
230
    private FeatureCacheProvider cache;
231
232 43215 jjdelcerro
    StateInformation state;
233 43270 fdiaz
234 43135 jjdelcerro
    FeatureStoreTimeSupport timeSupport;
235 43215 jjdelcerro
236
237
    private class StateInformation extends HashMap<Object, Object> {
238
239
        private static final long serialVersionUID = 4109026189635185666L;
240
241
        private boolean broken;
242
        private Throwable breakingsCause;
243 43270 fdiaz
244 43840 jjdelcerro
        @SuppressWarnings("OverridableMethodCallInConstructor")
245 43215 jjdelcerro
        public StateInformation() {
246
            this.clear();
247
        }
248 43270 fdiaz
249 43215 jjdelcerro
        @Override
250
        public void clear() {
251
            this.broken = false;
252
            this.breakingsCause = null;
253
            super.clear();
254
        }
255 43270 fdiaz
256 43215 jjdelcerro
        public boolean isBroken() {
257
            return this.broken;
258
        }
259 43270 fdiaz
260 43215 jjdelcerro
        public void broken() {
261
            this.broken = true;
262
        }
263 43270 fdiaz
264 43215 jjdelcerro
        public Throwable getBreakingsCause() {
265
            return this.breakingsCause;
266
        }
267 43270 fdiaz
268 43215 jjdelcerro
        public void setBreakingsCause(Throwable cause) {
269
            if( this.breakingsCause==null ) {
270
                this.breakingsCause = cause;
271
            }
272
            this.broken = true;
273 43270 fdiaz
        }
274 43215 jjdelcerro
    }
275
276
277 43270 fdiaz
278 40435 jjdelcerro
    /*
279
     * TODO:
280 41818 fdiaz
     *
281 40435 jjdelcerro
     * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
282
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
283
     * featureType al que se le han cambiado las reglas de validacion cuando
284
     * hasStrongChanges=false.
285
     */
286 42293 jjdelcerro
287 40435 jjdelcerro
    public DefaultFeatureStore() {
288 43215 jjdelcerro
        this.state = new StateInformation();
289 40435 jjdelcerro
    }
290
291 43020 jjdelcerro
    @Override
292
    public void intialize(DataManager dataManager,
293 42293 jjdelcerro
        DataStoreParameters parameters) throws InitializeException {
294 40435 jjdelcerro
295
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
296
297 43020 jjdelcerro
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
298 43152 fdiaz
            FeatureStore.METADATA_DEFINITION_NAME,
299 43020 jjdelcerro
            MetadataManager.METADATA_NAMESPACE
300
        );
301 40435 jjdelcerro
302
        this.dataManager = (DefaultDataManager) dataManager;
303
304
        this.parameters = parameters;
305
        this.transforms = new DefaultFeatureStoreTransforms(this);
306
        try {
307
            indexes = new DefaultFeatureIndexes(this);
308
        } catch (DataException e) {
309
            throw new InitializeException(e);
310
        }
311
312
    }
313
314 43020 jjdelcerro
    @Override
315
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
316 40435 jjdelcerro
        this.provider = (FeatureStoreProvider) provider;
317 43020 jjdelcerro
        this.delegate((DynObject) provider);
318 40435 jjdelcerro
        this.metadataChildren = new HashSet();
319
        this.metadataChildren.add(provider);
320 43958 jjdelcerro
        loadDALFile();
321 40435 jjdelcerro
    }
322
323 43215 jjdelcerro
    @Override
324 40435 jjdelcerro
    public DataStoreParameters getParameters() {
325
        return parameters;
326
    }
327
328
    public int getMode() {
329
        return this.mode;
330
    }
331
332 43215 jjdelcerro
    @Override
333 40435 jjdelcerro
    public DataManager getManager() {
334
        return this.dataManager;
335
    }
336
337 43215 jjdelcerro
    @Override
338 44259 jjdelcerro
    public UnmodifiableBasicMap<String,DataStore> getChildren() {
339 44251 jjdelcerro
        return this.provider.getChildren();
340 40435 jjdelcerro
    }
341
342 43215 jjdelcerro
    @Override
343 40435 jjdelcerro
    public FeatureStoreProvider getProvider() {
344
        return this.provider;
345
    }
346
347
    public FeatureManager getFeatureManager() {
348
        return this.featureManager;
349
    }
350
351 43215 jjdelcerro
    @Override
352 40435 jjdelcerro
    public void setFeatureTypes(List types, FeatureType defaultType) {
353
        this.featureTypes = types;
354
        this.defaultFeatureType = defaultType;
355
    }
356
357
    public void open() throws OpenException {
358 42049 jjdelcerro
        if (this.mode != MODE_QUERY) {
359
            // TODO: Se puede hacer un open estando en edicion ?
360
            try {
361
                throw new IllegalStateException();
362 42293 jjdelcerro
            } catch(Exception ex) {
363
                LOG.warn("Opening a store in editing/append mode ("+this.getFullName()+").",ex);
364 42049 jjdelcerro
            }
365
        }
366 40435 jjdelcerro
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
367
        this.provider.open();
368
        this.notifyChange(DataStoreNotification.AFTER_OPEN);
369
    }
370
371 43215 jjdelcerro
    @Override
372 40435 jjdelcerro
    public void refresh() throws OpenException, InitializeException {
373
        if (this.mode != MODE_QUERY) {
374
            throw new IllegalStateException();
375
        }
376
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
377 43215 jjdelcerro
        if( state.isBroken() ) {
378
            this.load(state);
379
        } else {
380
            this.featureCount = null;
381
            this.provider.refresh();
382
        }
383 40435 jjdelcerro
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
384
    }
385
386
    public void close() throws CloseException {
387 42049 jjdelcerro
        if (this.mode != MODE_QUERY) {
388
            // TODO: Se puede hacer un close estando en edicion ?
389
            try {
390
                throw new IllegalStateException();
391 42293 jjdelcerro
            } catch(Exception ex) {
392
                LOG.warn("Clossing a store in editing/append mode ("+this.getFullName()+").",ex);
393 42049 jjdelcerro
            }
394
        }
395 40435 jjdelcerro
        this.notifyChange(DataStoreNotification.BEFORE_CLOSE);
396
        this.featureCount = null;
397
        this.provider.close();
398
        this.notifyChange(DataStoreNotification.AFTER_CLOSE);
399
    }
400
401 43215 jjdelcerro
    @Override
402 40435 jjdelcerro
    protected void doDispose() throws BaseException {
403 42049 jjdelcerro
        if (this.mode != MODE_QUERY) {
404
            // TODO: Se puede hacer un dispose estando en edicion ?
405
            try {
406
                throw new IllegalStateException();
407 42293 jjdelcerro
            } catch(Exception ex) {
408
                LOG.warn("Dispossing a store in editing/append mode ("+this.getFullName()+").",ex);
409 42049 jjdelcerro
            }
410
        }
411 40435 jjdelcerro
        this.notifyChange(DataStoreNotification.BEFORE_DISPOSE);
412
        this.disposeIndexes();
413 43377 jjdelcerro
        if( this.provider!=null ) {
414
            this.provider.dispose();
415
        }
416 40435 jjdelcerro
        if (this.selection != null) {
417
            this.selection.dispose();
418
            this.selection = null;
419
        }
420
        this.commands = null;
421
        this.featureCount = null;
422
        if (this.locks != null) {
423
            // this.locks.dispose();
424
            this.locks = null;
425
        }
426
427
        if (this.featureTypeManager != null) {
428
            this.featureTypeManager.dispose();
429
            this.featureTypeManager = null;
430
        }
431
432
        this.featureManager = null;
433
        this.spatialManager = null;
434
435
        this.parameters = null;
436
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
437
        if (delegateObservable != null) {
438
            this.delegateObservable.deleteObservers();
439
            this.delegateObservable = null;
440
        }
441
    }
442
443 43215 jjdelcerro
    @Override
444 40435 jjdelcerro
    public boolean allowWrite() {
445 41928 jjdelcerro
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
446 42293 jjdelcerro
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
447 41928 jjdelcerro
            return false;
448
        }
449 40435 jjdelcerro
        return this.provider.allowWrite();
450
    }
451
452 43215 jjdelcerro
    @Override
453 40435 jjdelcerro
    public boolean canWriteGeometry(int geometryType) throws DataException {
454
        return this.provider.canWriteGeometry(geometryType, 0);
455
    }
456
457 43215 jjdelcerro
    @Override
458 40435 jjdelcerro
    public DataServerExplorer getExplorer() throws ReadException,
459 42293 jjdelcerro
        ValidateDataParametersException {
460 43215 jjdelcerro
        if( this.state.isBroken() ) {
461
            try {
462
                return this.provider.getExplorer();
463
            } catch(Throwable th) {
464
                return null;
465
            }
466
        } else {
467
            return this.provider.getExplorer();
468
        }
469 40435 jjdelcerro
    }
470
471
    /*
472
     * public Metadata getMetadata() throws MetadataNotFoundException {
473
     * // TODO:
474
     * // Si el provider devuelbe null habria que ver de construir aqui
475
     * // los metadatos basicos, como el Envelope y el SRS.
476 41818 fdiaz
     *
477 40435 jjdelcerro
     * // TODO: Estando en edicion el Envelope deberia de
478
     * // actualizarse usando el spatialManager
479
     * return this.provider.getMetadata();
480
     * }
481
     */
482 42293 jjdelcerro
483 43215 jjdelcerro
    @Override
484 40435 jjdelcerro
    public Envelope getEnvelope() throws DataException {
485
        if (this.mode == MODE_FULLEDIT) {
486 42293 jjdelcerro
                // Just in case another thread tries to write in the store
487
                synchronized (this) {
488
                        return this.spatialManager.getEnvelope();
489
                        }
490 40435 jjdelcerro
        }
491 42293 jjdelcerro
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
492
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
493 40435 jjdelcerro
        }
494 44190 jjdelcerro
        Envelope envelope = this.provider.getEnvelope();
495
        if( envelope!=null ) {
496
            return envelope;
497
        }
498
        FeatureAttributeDescriptor attrdesc = this.getDefaultFeatureType().getDefaultGeometryAttribute();
499
        if( attrdesc == null || !attrdesc.isComputed() ) {
500
            return null;
501
        }
502
        final int index = attrdesc.getIndex();
503
        final MutableObject<Envelope> envelopeValue = new MutableObject<>();
504
        try {
505
            this.accept(new Visitor() {
506
                @Override
507
                public void visit(Object obj) throws VisitCanceledException, BaseException {
508
                    Feature f = (Feature) obj;
509
                    Geometry g =  (Geometry) f.get(index);
510
                    if( g == null ) {
511
                        return;
512
                    }
513
                    if( envelopeValue.getValue()==null ) {
514
                        envelopeValue.setValue(g.getEnvelope());
515
                    } else {
516
                        envelopeValue.getValue().add(g);
517
                    }
518
                }
519
            });
520
        } catch (Throwable th) {
521
            LOG.warn("Can't calculate envelope", th);
522
            return null;
523
        }
524
        return envelopeValue.getValue();
525 40435 jjdelcerro
    }
526
527
    /**
528 43840 jjdelcerro
     * @throws org.gvsig.fmap.dal.exception.DataException
529 40435 jjdelcerro
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
530
     */
531 43215 jjdelcerro
    @Override
532 40435 jjdelcerro
    public IProjection getSRSDefaultGeometry() throws DataException {
533
        return this.getDefaultFeatureType().getDefaultSRS();
534
    }
535
536 43215 jjdelcerro
    @Override
537 40435 jjdelcerro
    public FeatureSelection createDefaultFeatureSelection()
538 42293 jjdelcerro
        throws DataException {
539 40435 jjdelcerro
        return new DefaultFeatureSelection(this);
540
    }
541
542 43215 jjdelcerro
    @Override
543 40435 jjdelcerro
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
544 42293 jjdelcerro
        throws DataException {
545 40435 jjdelcerro
        if (type.hasOID()) {
546
            return new DefaultFeatureProvider(type,
547 42293 jjdelcerro
                this.provider.createNewOID());
548 40435 jjdelcerro
        }
549
        return new DefaultFeatureProvider(type);
550
    }
551
552 43215 jjdelcerro
    @Override
553 40435 jjdelcerro
    public void saveToState(PersistentState state) throws PersistenceException {
554 40776 nbrodin
        /*if (this.mode != FeatureStore.MODE_QUERY) {
555 42293 jjdelcerro
            throw new PersistenceException(new IllegalStateException(
556
                this.getName()));
557
        }*/
558 40435 jjdelcerro
        state.set("dataStoreName", this.getName());
559
        state.set("parameters", this.parameters);
560
        state.set("selection", this.selection);
561
        state.set("transforms", this.transforms);
562
        // TODO locks persistence
563
        // state.set("locks", this.locks);
564
        // TODO indexes persistence
565
        // state.set("indexes", this.indexes);
566
        Map evaluatedAttr = new HashMap(1);
567
        Iterator iterType = featureTypes.iterator();
568
        Iterator iterAttr;
569
        FeatureType type;
570
        DefaultFeatureAttributeDescriptor attr;
571
        List attrs;
572
        while (iterType.hasNext()) {
573
            type = (FeatureType) iterType.next();
574
            attrs = new ArrayList();
575
            iterAttr = type.iterator();
576
            while (iterAttr.hasNext()) {
577
                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
578
                if ((attr.getEvaluator() != null)
579 42293 jjdelcerro
                    && (attr.getEvaluator() instanceof Persistent)) {
580 40435 jjdelcerro
                    attrs.add(attr);
581
                }
582
            }
583
            if (!attrs.isEmpty()) {
584
                evaluatedAttr.put(type.getId(), attrs);
585
            }
586
587
        }
588
589
        if (evaluatedAttr.isEmpty()) {
590
            evaluatedAttr = null;
591
        }
592
593
        state.set("evaluatedAttributes", evaluatedAttr);
594
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
595
596
    }
597 43270 fdiaz
598 43215 jjdelcerro
    @Override
599
    public void loadFromState(final PersistentState persistentState)
600 42293 jjdelcerro
        throws PersistenceException {
601 40435 jjdelcerro
        if (this.provider != null) {
602
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
603
        }
604
        if (this.getManager() == null) {
605
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
606
        }
607 43215 jjdelcerro
        state.clear();
608
        try {
609
            state.put("parameters", persistentState.get("parameters"));
610
        } catch(Throwable th) {
611
            state.setBreakingsCause(th);
612
        }
613
        try {
614
            state.put("selection", persistentState.get("selection"));
615
        } catch(Throwable th) {
616
            state.setBreakingsCause(th);
617
        }
618
        try {
619
            state.put("transforms",  persistentState.get("transforms"));
620
        } catch(Throwable th) {
621
            state.setBreakingsCause(th);
622
        }
623
        try {
624
            state.put("evaluatedAttributes",  persistentState.get("evaluatedAttributes"));
625
        } catch(Throwable th) {
626
            state.setBreakingsCause(th);
627
        }
628
        try {
629
            state.put("defaultFeatureTypeId", persistentState.getString("defaultFeatureTypeId"));
630
        } catch(Throwable th) {
631
            state.setBreakingsCause(th);
632
        }
633
        load(state);
634 43270 fdiaz
    }
635
636
    private void load(StateInformation state) {
637 43215 jjdelcerro
        this.featureTypes = new ArrayList();
638
        this.defaultFeatureType = null;
639
        this.featureCount = null;
640 40435 jjdelcerro
641 43215 jjdelcerro
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
642
        try {
643
            intialize(dataManager, params);
644
        } catch(Throwable th) {
645
            state.setBreakingsCause(th);
646
        }
647 40435 jjdelcerro
648
        try {
649 43215 jjdelcerro
            DataStoreProvider prov = dataManager.createProvider(
650
                getStoreProviderServices(),
651
                params
652 43020 jjdelcerro
            );
653 43215 jjdelcerro
            setProvider(prov);
654
        } catch(Throwable th) {
655 44191 jjdelcerro
            LOG.warn("Can't load store from state.", th);
656 43215 jjdelcerro
            state.setBreakingsCause(th);
657
        }
658
        try {
659
            selection = (FeatureSelection) state.get("selection");
660
        } catch(Throwable th) {
661
            state.setBreakingsCause(th);
662
        }
663
664
        try {
665
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
666
            this.transforms.setFeatureStore(this);
667
            for( FeatureStoreTransform transform : this.transforms ) {
668
                try {
669
                    transform.setUp();
670
                } catch(Throwable th) {
671
                    state.setBreakingsCause(th);
672
                }
673
            }
674
        } catch(Throwable th) {
675
            state.setBreakingsCause(th);
676
        }
677
678
        try {
679 40435 jjdelcerro
            Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
680
            if ((evaluatedAttributes != null) && !evaluatedAttributes.isEmpty()) {
681 43215 jjdelcerro
                    Iterator iterEntries = evaluatedAttributes.entrySet().iterator();
682
                    while (iterEntries.hasNext()) {
683
                            Entry entry = (Entry) iterEntries.next();
684
                            List attrs = (List) entry.getValue();
685
                            if (attrs.isEmpty()) {
686
                                    continue;
687
                            }
688
                            int fTypePos = -1;
689
                            DefaultFeatureType type = null;
690
                            for (int i = 0; i < featureTypes.size(); i++) {
691
                                    type = (DefaultFeatureType) featureTypes.get(i);
692
                                    if (type.getId().equals(entry.getKey())) {
693
                                            fTypePos = i;
694
                                            break;
695
                                    }
696
                            }
697
                            if (type == null) {
698
                                    throw new PersistenceCantFindFeatureTypeException(
699
                                            getName(), (String) entry.getKey());
700
                            }
701
                            DefaultEditableFeatureType eType = (DefaultEditableFeatureType) type.getEditable();
702
                            Iterator<FeatureAttributeDescriptor> iterAttr = attrs.iterator();
703
                            while (iterAttr.hasNext()) {
704
                                    FeatureAttributeDescriptor attr = iterAttr.next();
705
                                    eType.addLike(attr);
706
                            }
707
                            featureTypes.set(fTypePos, eType.getNotEditableCopy());
708
709 40435 jjdelcerro
                    }
710
711
            }
712 43215 jjdelcerro
        } catch(Throwable th) {
713
            state.setBreakingsCause(th);
714
        }
715 40435 jjdelcerro
716 43270 fdiaz
717 43215 jjdelcerro
        try {
718
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
719
            FeatureType ftype;
720 41818 fdiaz
721 43215 jjdelcerro
            if (defaultFeatureType == null ||
722
                    defaultFeatureType.getId() == null ||
723
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
724 40435 jjdelcerro
725 43215 jjdelcerro
                    ftype = getFeatureType(defaultFeatureTypeId);
726
                    if (ftype == null) {
727
                            /*
728
                             * Un error en el m?todo de PostgreSQL getName(), hace que
729
                             * el nombre del featureType sea valor retornado por el getProviderName()
730
                             * De momento se pone este parche para apa?arlo y poder mantener compatibilidad
731
                             * con proyectos antiguos (2.1 y 2.2)
732
                             */
733
                            ftype = getFeatureType(getName());
734
                            if(ftype == null ) {
735
                                    throw new RuntimeException("Can't locate feature type");
736
                            }
737
                    }
738
                    defaultFeatureType = ftype;
739 40435 jjdelcerro
            }
740 43215 jjdelcerro
        } catch(Throwable th) {
741
            state.setBreakingsCause(th);
742 40435 jjdelcerro
        }
743
744 43270 fdiaz
        LOG.info("load() broken:{}, {}, {}.",
745 43215 jjdelcerro
                new Object[] { state.isBroken(), this.getProviderName(), params }
746
        );
747 40435 jjdelcerro
    }
748
749 43215 jjdelcerro
        public DataStoreProviderServices getStoreProviderServices() {
750
                return this;
751
        }
752 43270 fdiaz
753 40435 jjdelcerro
    public static void registerPersistenceDefinition() {
754
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
755
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
756 42293 jjdelcerro
            DynStruct definition =
757
                manager.addDefinition(DefaultFeatureStore.class,
758
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
759
                        + " Persistent definition", null, null);
760 40435 jjdelcerro
            definition.addDynFieldString("dataStoreName").setMandatory(true)
761 42293 jjdelcerro
                .setPersistent(true);
762 40435 jjdelcerro
763
            definition.addDynFieldObject("parameters")
764 42293 jjdelcerro
                .setClassOfValue(DynObject.class).setMandatory(true)
765
                .setPersistent(true);
766 40435 jjdelcerro
767
            definition.addDynFieldObject("selection")
768 42293 jjdelcerro
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
769
                .setPersistent(true);
770 40435 jjdelcerro
771
            definition.addDynFieldObject("transforms")
772 42293 jjdelcerro
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
773
                .setMandatory(true).setPersistent(true);
774 40435 jjdelcerro
775
            definition.addDynFieldMap("evaluatedAttributes")
776 42293 jjdelcerro
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
777
                .setMandatory(false).setPersistent(true);
778 40435 jjdelcerro
779
            definition.addDynFieldString("defaultFeatureTypeId")
780 42293 jjdelcerro
                .setMandatory(true).setPersistent(true);
781 40435 jjdelcerro
        }
782
    }
783
784
    public static void registerMetadataDefinition() throws MetadataException {
785
        MetadataManager manager = MetadataLocator.getMetadataManager();
786 43020 jjdelcerro
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
787 42293 jjdelcerro
            DynStruct metadataDefinition =
788 43020 jjdelcerro
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
789 40435 jjdelcerro
            metadataDefinition.extend(manager
790 42293 jjdelcerro
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
791 40435 jjdelcerro
        }
792
    }
793
794
    //
795
    // ====================================================================
796
    // Gestion de la seleccion
797
    //
798 42293 jjdelcerro
799 43215 jjdelcerro
    @Override
800 40435 jjdelcerro
    public void setSelection(DataSet selection) throws DataException {
801
        this.setSelection((FeatureSet) selection);
802
    }
803
804 43215 jjdelcerro
    @Override
805 40435 jjdelcerro
    public DataSet createSelection() throws DataException {
806
        return createFeatureSelection();
807
    }
808
809 43215 jjdelcerro
    @Override
810 40435 jjdelcerro
    public DataSet getSelection() throws DataException {
811
        return this.getFeatureSelection();
812
    }
813
814 43215 jjdelcerro
    @Override
815 40435 jjdelcerro
    public void setSelection(FeatureSet selection) throws DataException {
816
        setSelection(selection, true);
817
    }
818
819
    public void setSelection(FeatureSet selection, boolean undoable)
820 42293 jjdelcerro
        throws DataException {
821 40435 jjdelcerro
        if (selection == null) {
822
            if (undoable) {
823
                throw new SelectionNotAllowedException(getName());
824
            }
825
826
        } else {
827
            if (selection.equals(this.selection)) {
828
                return;
829
            }
830
            if (!selection.isFromStore(this)) {
831
                throw new SelectionNotAllowedException(getName());
832
            }
833
        }
834
835
        if (this.selection != null) {
836
            this.selection.deleteObserver(this);
837
        }
838
        if (selection == null) {
839
            if (this.selection != null) {
840
                this.selection.dispose();
841
            }
842
            this.selection = null;
843
            return;
844
        }
845
        if (selection instanceof FeatureSelection) {
846
            if (undoable && isEditing()) {
847
                commands.selectionSet(this, this.selection,
848 42293 jjdelcerro
                    (FeatureSelection) selection);
849 40435 jjdelcerro
            }
850
            if (this.selection != null) {
851
                this.selection.dispose();
852
            }
853
            this.selection = (FeatureSelection) selection;
854
        } else {
855
            if (undoable && isEditing()) {
856
                commands.startComplex("_selectionSet");
857
            }
858
            if (selection instanceof DefaultFeatureSelection) {
859 42293 jjdelcerro
                DefaultFeatureSelection defSelection =
860
                    (DefaultFeatureSelection) selection;
861 40435 jjdelcerro
                defSelection.deselectAll(undoable);
862
                defSelection.select(selection, undoable);
863
            } else {
864
                this.selection.deselectAll();
865
                this.selection.select(selection);
866
            }
867
            if (undoable && isEditing()) {
868
                commands.endComplex();
869
            }
870
        }
871
        this.selection.addObserver(this);
872
873
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
874
    }
875
876 43215 jjdelcerro
    @Override
877 40435 jjdelcerro
    public FeatureSelection createFeatureSelection() throws DataException {
878
        return this.provider.createFeatureSelection();
879
    }
880
881 43215 jjdelcerro
    @Override
882 40435 jjdelcerro
    public FeatureSelection getFeatureSelection() throws DataException {
883
        if (selection == null) {
884
            this.selection = createFeatureSelection();
885
            this.selection.addObserver(this);
886
        }
887
        return selection;
888
    }
889
890
    //
891
    // ====================================================================
892
    // Gestion de notificaciones
893
    //
894 42293 jjdelcerro
895 43093 jjdelcerro
    @Override
896
    public void notifyChange(FeatureStoreNotification storeNotification) {
897
        try {
898
            delegateObservable.notifyObservers(storeNotification);
899
        } catch (Throwable ex) {
900
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
901
        }
902
    }
903
904
    @Override
905 40435 jjdelcerro
    public void notifyChange(String notification) {
906
        if (delegateObservable != null) {
907
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
908
        }
909
910
    }
911
912 43093 jjdelcerro
    @Override
913 40435 jjdelcerro
    public void notifyChange(String notification, FeatureProvider data) {
914 43093 jjdelcerro
        Feature f = null;
915 40435 jjdelcerro
        try {
916 43093 jjdelcerro
            f = createFeature(data);
917
        } catch (Throwable ex) {
918
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
919 40435 jjdelcerro
        }
920 43093 jjdelcerro
        notifyChange(notification, f);
921 40435 jjdelcerro
    }
922
923
    public void notifyChange(String notification, Feature feature) {
924
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
925 42293 jjdelcerro
            feature));
926 40435 jjdelcerro
    }
927
928
    public void notifyChange(String notification, Command command) {
929
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
930 42293 jjdelcerro
            command));
931 40435 jjdelcerro
    }
932
933
    public void notifyChange(String notification, EditableFeatureType type) {
934
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
935 42293 jjdelcerro
            type));
936 40435 jjdelcerro
    }
937
938 43093 jjdelcerro
    @Override
939 40435 jjdelcerro
    public void notifyChange(String notification, Resource resource) {
940
        notifyChange(new DefaultFeatureStoreNotification(this,
941 42293 jjdelcerro
            DataStoreNotification.RESOURCE_CHANGED));
942 40435 jjdelcerro
    }
943
944
    //
945
    // ====================================================================
946
    // Gestion de bloqueos
947
    //
948 42293 jjdelcerro
949 43215 jjdelcerro
    @Override
950 40435 jjdelcerro
    public boolean isLocksSupported() {
951
        return this.provider.isLocksSupported();
952
    }
953
954 43215 jjdelcerro
    @Override
955 40435 jjdelcerro
    public FeatureLocks getLocks() throws DataException {
956
        if (!this.provider.isLocksSupported()) {
957
            LOG.warn("Locks not supported");
958
            return null;
959
        }
960
        if (locks == null) {
961
            this.locks = this.provider.createFeatureLocks();
962
        }
963
        return locks;
964
    }
965
966
    //
967
    // ====================================================================
968
    // Interface Observable
969
    //
970 42293 jjdelcerro
971 43215 jjdelcerro
    @Override
972 40435 jjdelcerro
    public void disableNotifications() {
973
        this.delegateObservable.disableNotifications();
974
975
    }
976
977 43215 jjdelcerro
    @Override
978 40435 jjdelcerro
    public void enableNotifications() {
979
        this.delegateObservable.enableNotifications();
980
    }
981
982 43215 jjdelcerro
    @Override
983 40435 jjdelcerro
    public void beginComplexNotification() {
984
        this.delegateObservable.beginComplexNotification();
985
986
    }
987
988 43215 jjdelcerro
    @Override
989 40435 jjdelcerro
    public void endComplexNotification() {
990
        this.delegateObservable.endComplexNotification();
991
992
    }
993
994 43215 jjdelcerro
    @Override
995 40435 jjdelcerro
    public void addObserver(Observer observer) {
996
        if (delegateObservable != null) {
997
            this.delegateObservable.addObserver(observer);
998
        }
999
    }
1000
1001 43215 jjdelcerro
    @Override
1002 40435 jjdelcerro
    public void deleteObserver(Observer observer) {
1003
        if (delegateObservable != null) {
1004
            this.delegateObservable.deleteObserver(observer);
1005
        }
1006
    }
1007
1008 43215 jjdelcerro
    @Override
1009 40435 jjdelcerro
    public void deleteObservers() {
1010
        this.delegateObservable.deleteObservers();
1011
1012
    }
1013
1014
    //
1015
    // ====================================================================
1016
    // Interface Observer
1017
    //
1018
    // Usado para observar:
1019
    // - su seleccion
1020
    // - sus bloqueos
1021
    // - sus recursos
1022
    //
1023 42293 jjdelcerro
1024 43215 jjdelcerro
    @Override
1025 40435 jjdelcerro
    public void update(Observable observable, Object notification) {
1026
        if (observable instanceof FeatureSet) {
1027
            if (observable == this.selection) {
1028
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
1029 43270 fdiaz
            } else if (observable == this.locks) {
1030
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
1031
            }
1032 40435 jjdelcerro
1033 43270 fdiaz
        } else if (observable instanceof FeatureStoreProvider) {
1034
            if (observable == this.provider) {
1035 40435 jjdelcerro
1036
            }
1037 43270 fdiaz
        } else if (observable instanceof FeatureReferenceSelection) {
1038
            if(notification instanceof String){
1039
                    this.notifyChange((String)notification);
1040
            }
1041
        }
1042 40435 jjdelcerro
    }
1043
1044
    //
1045
    // ====================================================================
1046
    // Edicion
1047
    //
1048 42293 jjdelcerro
1049 40435 jjdelcerro
    private void newVersionOfUpdate() {
1050
        this.versionOfUpdate++;
1051
    }
1052
1053
    private long currentVersionOfUpdate() {
1054
        return this.versionOfUpdate;
1055
    }
1056
1057
    private void checkInEditingMode() throws NeedEditingModeException {
1058
        if (mode != MODE_FULLEDIT) {
1059
            throw new NeedEditingModeException(this.getName());
1060
        }
1061
    }
1062
1063
    private void checkNotInAppendMode() throws IllegalStateException {
1064
        if (mode == MODE_APPEND) {
1065 42293 jjdelcerro
                        throw new IllegalStateException("Error: store "
1066
                                        + this.getFullName() + " is in append mode");
1067 40435 jjdelcerro
        }
1068
    }
1069
1070
    private void checkIsOwnFeature(Feature feature)
1071 42293 jjdelcerro
        throws IllegalFeatureException {
1072 40435 jjdelcerro
        if (((DefaultFeature) feature).getStore() != this) {
1073
            throw new IllegalFeatureException(this.getName());
1074
        }
1075
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1076
        // fixFeatureType((DefaultFeatureType) feature.getType());
1077
    }
1078
1079
    private void exitEditingMode() {
1080
        if (commands != null) {
1081
            commands.clear();
1082
            commands = null;
1083
        }
1084
1085
        if (featureTypeManager != null) {
1086
            featureTypeManager.dispose();
1087
            featureTypeManager = null;
1088
1089
        }
1090
1091
        // TODO implementar un dispose para estos dos
1092
        featureManager = null;
1093
        spatialManager = null;
1094
1095
        featureCount = null;
1096
1097
        mode = MODE_QUERY;
1098
        hasStrongChanges = true; // Lo deja a true por si las moscas
1099
        hasInserts = true;
1100
    }
1101
1102 43215 jjdelcerro
    @Override
1103 40435 jjdelcerro
    synchronized public void edit() throws DataException {
1104
        edit(MODE_FULLEDIT);
1105
    }
1106
1107 43215 jjdelcerro
    @Override
1108 40435 jjdelcerro
    synchronized public void edit(int mode) throws DataException {
1109 43215 jjdelcerro
        LOG.debug("Starting editing in mode: {}", mode);
1110 40435 jjdelcerro
        try {
1111
            if (this.mode != MODE_QUERY) {
1112
                throw new AlreadyEditingException(this.getName());
1113
            }
1114
            if (!this.provider.supportsAppendMode()) {
1115
                mode = MODE_FULLEDIT;
1116
            }
1117
            switch (mode) {
1118 42293 jjdelcerro
            case MODE_QUERY:
1119
                throw new IllegalStateException(this.getName());
1120
1121
            case MODE_FULLEDIT:
1122
                if (!this.transforms.isEmpty()) {
1123 40435 jjdelcerro
                    throw new IllegalStateException(this.getName());
1124 42293 jjdelcerro
                }
1125
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1126
                invalidateIndexes();
1127 43840 jjdelcerro
                featureManager = new FeatureManager();
1128
                featureTypeManager = new FeatureTypeManager(this);
1129
                spatialManager = new SpatialManager(this, provider.getEnvelope());
1130 40435 jjdelcerro
1131 43840 jjdelcerro
                commands = new DefaultFeatureCommandsStack(
1132
                        this, featureManager,
1133 42293 jjdelcerro
                        spatialManager, featureTypeManager);
1134
                this.mode = MODE_FULLEDIT;
1135
                hasStrongChanges = false;
1136
                hasInserts = false;
1137
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1138
                break;
1139
            case MODE_APPEND:
1140
                if (!this.transforms.isEmpty()) {
1141
                    throw new IllegalStateException(this.getName());
1142
                }
1143
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1144
                invalidateIndexes();
1145
                this.provider.beginAppend();
1146
                this.mode = MODE_APPEND;
1147
                hasInserts = false;
1148
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1149
                break;
1150 40435 jjdelcerro
            }
1151
        } catch (Exception e) {
1152
            throw new StoreEditException(e, this.getName());
1153
        }
1154
    }
1155
1156
    private void invalidateIndexes() {
1157
        setIndexesValidStatus(false);
1158
    }
1159
1160
    private void setIndexesValidStatus(boolean valid) {
1161 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1162 40435 jjdelcerro
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
1163 43215 jjdelcerro
            ? Boolean.TRUE : Boolean.FALSE), theIndexes);
1164
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1165 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1166
            if (index instanceof FeatureIndexProviderServices) {
1167 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1168
                    (FeatureIndexProviderServices) index;
1169 40435 jjdelcerro
                indexServices.setValid(valid);
1170
            }
1171
        }
1172
    }
1173
1174
    private void updateIndexes() throws FeatureIndexException {
1175 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1176
        LOG.debug("Refilling indexes: {}", theIndexes);
1177
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1178 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1179
            if (index instanceof FeatureIndexProviderServices) {
1180 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1181
                    (FeatureIndexProviderServices) index;
1182 40435 jjdelcerro
                indexServices.fill(true, null);
1183
            }
1184
        }
1185
    }
1186
1187
    private void waitForIndexes() {
1188 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1189
        LOG.debug("Waiting for indexes to finish filling: {}", theIndexes);
1190
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1191 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1192
            if (index instanceof FeatureIndexProviderServices) {
1193 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1194
                    (FeatureIndexProviderServices) index;
1195 40435 jjdelcerro
                indexServices.waitForIndex();
1196
            }
1197
        }
1198
    }
1199
1200
    private void disposeIndexes() {
1201 43215 jjdelcerro
        FeatureIndexes theIndexes = getIndexes();
1202
        LOG.debug("Disposing indexes: {}", theIndexes);
1203 43377 jjdelcerro
        if( theIndexes==null ) {
1204
            return;
1205
        }
1206 43215 jjdelcerro
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1207 40435 jjdelcerro
            FeatureIndex index = (FeatureIndex) iterator.next();
1208
            if (index instanceof FeatureIndexProviderServices) {
1209 42293 jjdelcerro
                FeatureIndexProviderServices indexServices =
1210
                    (FeatureIndexProviderServices) index;
1211 40435 jjdelcerro
                indexServices.dispose();
1212
            }
1213
        }
1214
    }
1215
1216 43215 jjdelcerro
    @Override
1217 40435 jjdelcerro
    public boolean isEditing() {
1218
        return mode == MODE_FULLEDIT;
1219
    }
1220
1221 43215 jjdelcerro
    @Override
1222 40435 jjdelcerro
    public boolean isAppending() {
1223
        return mode == MODE_APPEND;
1224
    }
1225
1226 43215 jjdelcerro
    @Override
1227 40435 jjdelcerro
    synchronized public void update(EditableFeatureType type)
1228 42293 jjdelcerro
        throws DataException {
1229 40435 jjdelcerro
        try {
1230
            if (type == null) {
1231
                throw new NullFeatureTypeException(getName());
1232
            }
1233 43981 omartinez
            boolean typehasStrongChanges = ((DefaultEditableFeatureType) type).hasStrongChanges();
1234
            if (typehasStrongChanges) {
1235
                checkInEditingMode();
1236 43992 jjdelcerro
            }  else if(this.isAppending()) {
1237 43981 omartinez
                throw new NeedEditingModeException(this.getName());
1238
            }
1239 40435 jjdelcerro
            // FIXME: Comprobar que es un featureType aceptable.
1240
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
1241
            newVersionOfUpdate();
1242 43981 omartinez
1243 44189 jjdelcerro
            FeatureType oldt = type.getSource().getCopy();
1244
            FeatureType newt = type.getCopy();
1245
            commands.update(newt, oldt);
1246 43981 omartinez
            if (typehasStrongChanges) {
1247 40435 jjdelcerro
                hasStrongChanges = true;
1248
            }
1249
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1250
        } catch (Exception e) {
1251
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1252
        }
1253
    }
1254
1255 43215 jjdelcerro
    @Override
1256 41818 fdiaz
    public void delete(Feature feature) throws DataException {
1257 40435 jjdelcerro
        this.commands.delete(feature);
1258
    }
1259 41818 fdiaz
1260 40435 jjdelcerro
    synchronized public void doDelete(Feature feature) throws DataException {
1261
        try {
1262
            checkInEditingMode();
1263
            checkIsOwnFeature(feature);
1264
            if (feature instanceof EditableFeature) {
1265
                throw new StoreDeleteEditableFeatureException(getName());
1266
            }
1267 41818 fdiaz
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1268
1269 40435 jjdelcerro
            //Update the featureManager and the spatialManager
1270
            featureManager.delete(feature.getReference());
1271
            spatialManager.deleteFeature(feature);
1272 41818 fdiaz
1273 40435 jjdelcerro
            newVersionOfUpdate();
1274
            hasStrongChanges = true;
1275
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1276
        } catch (Exception e) {
1277
            throw new StoreDeleteFeatureException(e, this.getName());
1278
        }
1279
    }
1280
1281
    private static EditableFeature lastChangedFeature = null;
1282
1283 43215 jjdelcerro
    @Override
1284 41818 fdiaz
    public synchronized void insert(EditableFeature feature)
1285 42293 jjdelcerro
        throws DataException {
1286 43215 jjdelcerro
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1287 40435 jjdelcerro
        try {
1288
            switch (mode) {
1289 42293 jjdelcerro
            case MODE_QUERY:
1290
                throw new NeedEditingModeException(this.getName());
1291 40435 jjdelcerro
1292 42293 jjdelcerro
            case MODE_APPEND:
1293
                checkIsOwnFeature(feature);
1294
                if (feature.getSource() != null) {
1295
                    throw new NoNewFeatureInsertException(this.getName());
1296
                }
1297
                this.featureCount = null;
1298
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1299
                feature.validate(Feature.UPDATE);
1300
                provider.append(((DefaultEditableFeature) feature).getData());
1301
                hasStrongChanges = true;
1302
                hasInserts = true;
1303
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1304
                break;
1305 40435 jjdelcerro
1306 42293 jjdelcerro
            case MODE_FULLEDIT:
1307
                if (feature.getSource() != null) {
1308
                    throw new NoNewFeatureInsertException(this.getName());
1309
                }
1310
                commands.insert(feature);
1311 40435 jjdelcerro
            }
1312
        } catch (Exception e) {
1313
            throw new StoreInsertFeatureException(e, this.getName());
1314
        }
1315
    }
1316 41818 fdiaz
1317 40435 jjdelcerro
    synchronized public void doInsert(EditableFeature feature)
1318 42293 jjdelcerro
        throws DataException {
1319 40435 jjdelcerro
        checkIsOwnFeature(feature);
1320 41818 fdiaz
1321 40435 jjdelcerro
        waitForIndexes();
1322
1323
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1324
        newVersionOfUpdate();
1325
        if ((lastChangedFeature == null)
1326 42293 jjdelcerro
            || (lastChangedFeature.getSource() != feature.getSource())) {
1327 40435 jjdelcerro
            lastChangedFeature = feature;
1328
            feature.validate(Feature.UPDATE);
1329
            lastChangedFeature = null;
1330
        }
1331
        //Update the featureManager and the spatialManager
1332
        ((DefaultEditableFeature) feature).setInserted(true);
1333
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1334 41818 fdiaz
1335 42293 jjdelcerro
1336 40435 jjdelcerro
        featureManager.add(newFeature);
1337
        spatialManager.insertFeature(newFeature);
1338 41818 fdiaz
1339 40435 jjdelcerro
        hasStrongChanges = true;
1340
        hasInserts = true;
1341 41818 fdiaz
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1342 40435 jjdelcerro
    }
1343 41818 fdiaz
1344 43215 jjdelcerro
    @Override
1345 40435 jjdelcerro
    public void update(EditableFeature feature)
1346 42293 jjdelcerro
    throws DataException {
1347 40435 jjdelcerro
        if ((feature).getSource() == null) {
1348
            insert(feature);
1349
            return;
1350
        }
1351
        commands.update(feature, feature.getSource());
1352
    }
1353
1354
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1355 42293 jjdelcerro
        throws DataException {
1356 41818 fdiaz
        try {
1357 40435 jjdelcerro
            checkInEditingMode();
1358
            checkIsOwnFeature(feature);
1359
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1360
            newVersionOfUpdate();
1361
            if ((lastChangedFeature == null)
1362 42293 jjdelcerro
                || (lastChangedFeature.getSource() != feature.getSource())) {
1363 40435 jjdelcerro
                lastChangedFeature = feature;
1364
                feature.validate(Feature.UPDATE);
1365
                lastChangedFeature = null;
1366
            }
1367 41818 fdiaz
1368 40435 jjdelcerro
            //Update the featureManager and the spatialManager
1369
            Feature newf = feature.getNotEditableCopy();
1370
            featureManager.update(newf, oldFeature);
1371
            spatialManager.updateFeature(newf, oldFeature);
1372 41818 fdiaz
1373 40435 jjdelcerro
            hasStrongChanges = true;
1374
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1375
        } catch (Exception e) {
1376
            throw new StoreUpdateFeatureException(e, this.getName());
1377
        }
1378
    }
1379
1380 43215 jjdelcerro
    @Override
1381 40435 jjdelcerro
    synchronized public void redo() throws RedoException {
1382
        Command redo = commands.getNextRedoCommand();
1383
        try {
1384
            checkInEditingMode();
1385
        } catch (NeedEditingModeException ex) {
1386
            throw new RedoException(redo, ex);
1387
        }
1388
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1389
        newVersionOfUpdate();
1390
        commands.redo();
1391
        hasStrongChanges = true;
1392
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1393
    }
1394
1395 43215 jjdelcerro
    @Override
1396 40435 jjdelcerro
    synchronized public void undo() throws UndoException {
1397
        Command undo = commands.getNextUndoCommand();
1398
        try {
1399
            checkInEditingMode();
1400
        } catch (NeedEditingModeException ex) {
1401
            throw new UndoException(undo, ex);
1402
        }
1403
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1404
        newVersionOfUpdate();
1405
        commands.undo();
1406
        hasStrongChanges = true;
1407
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1408
    }
1409
1410 43215 jjdelcerro
    @Override
1411 40435 jjdelcerro
    public List getRedoInfos() {
1412
        if (isEditing() && (commands != null)) {
1413
            return commands.getRedoInfos();
1414
        } else {
1415
            return null;
1416
        }
1417
    }
1418
1419 43215 jjdelcerro
    @Override
1420 40435 jjdelcerro
    public List getUndoInfos() {
1421
        if (isEditing() && (commands != null)) {
1422
            return commands.getUndoInfos();
1423
        } else {
1424
            return null;
1425
        }
1426
    }
1427
1428
    public synchronized FeatureCommandsStack getCommandsStack()
1429 42293 jjdelcerro
        throws DataException {
1430 40435 jjdelcerro
        checkInEditingMode();
1431
        return commands;
1432
    }
1433
1434 43215 jjdelcerro
    @Override
1435 40435 jjdelcerro
    synchronized public void cancelEditing() throws DataException {
1436 43642 jjdelcerro
        if( spatialManager!=null ) {
1437
            spatialManager.cancelModifies();
1438
        }
1439 40435 jjdelcerro
        try {
1440 43408 jjdelcerro
            switch (mode) {
1441
            case MODE_QUERY:
1442
                throw new NeedEditingModeException(this.getName());
1443 40435 jjdelcerro
1444 43408 jjdelcerro
            case MODE_APPEND:
1445
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1446
                provider.abortAppend();
1447
                exitEditingMode();
1448 40435 jjdelcerro
                ((FeatureSelection) this.getSelection()).deselectAll();
1449 43408 jjdelcerro
                updateIndexes();
1450
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1451
1452
            case MODE_FULLEDIT:
1453
                boolean clearSelection = this.hasStrongChanges;
1454
                if (this.selection instanceof FeatureReferenceSelection) {
1455
                    clearSelection = this.hasInserts;
1456
                }
1457
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1458
                exitEditingMode();
1459
                if (clearSelection) {
1460
                    ((FeatureSelection) this.getSelection()).deselectAll();
1461
                }
1462
                updateIndexes();
1463
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1464 40435 jjdelcerro
            }
1465
        } catch (Exception e) {
1466
            throw new StoreCancelEditingException(e, this.getName());
1467
        }
1468
    }
1469
1470 43215 jjdelcerro
    @Override
1471 40435 jjdelcerro
    synchronized public void finishEditing() throws DataException {
1472 43215 jjdelcerro
        LOG.debug("finish editing of mode: {}", mode);
1473 40435 jjdelcerro
        try {
1474 41818 fdiaz
1475 40435 jjdelcerro
            /*
1476
             * Selection needs to be cleared when editing stops
1477
             * to prevent conflicts with selection remaining from
1478
             * editing mode.
1479
             */
1480 42639 dmartinezizquierdo
//            ((FeatureSelection) this.getSelection()).deselectAll();
1481 43981 omartinez
            Map<String,List<FeatureAttributeDescriptor>> computedFields = this.getComputedFields();
1482 40435 jjdelcerro
            switch (mode) {
1483 42293 jjdelcerro
            case MODE_QUERY:
1484
                throw new NeedEditingModeException(this.getName());
1485 40435 jjdelcerro
1486 42293 jjdelcerro
            case MODE_APPEND:
1487 43377 jjdelcerro
                if( selection!=null ) {
1488
                    selection = null;
1489
                }
1490 42293 jjdelcerro
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1491 44189 jjdelcerro
                saveDALFile();
1492 42293 jjdelcerro
                provider.endAppend();
1493
                exitEditingMode();
1494 43981 omartinez
                this.updateComputedFields(computedFields);
1495 44189 jjdelcerro
                loadDALFile();
1496 42293 jjdelcerro
                updateIndexes();
1497
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1498
                break;
1499 40435 jjdelcerro
1500 42293 jjdelcerro
            case MODE_FULLEDIT:
1501
                if (hasStrongChanges && !this.allowWrite()) {
1502
                    throw new WriteNotAllowedException(getName());
1503
                }
1504 44189 jjdelcerro
                saveDALFile();
1505 43377 jjdelcerro
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1506
                    selection = null;
1507
                }
1508 42293 jjdelcerro
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1509
                if (hasStrongChanges) {
1510
                    validateFeatures(Feature.FINISH_EDITING);
1511 41818 fdiaz
1512 42293 jjdelcerro
                    /*
1513
                     * This will throw a PerformEditingExceptionif the provider
1514
                     * does not accept the changes (for example, an invalid field name)
1515
                     */
1516
                    provider.performChanges(featureManager.getDeleted(),
1517
                        featureManager.getInserted(),
1518
                        featureManager.getUpdated(),
1519 43967 jjdelcerro
                        removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1520 43981 omartinez
1521 43954 jjdelcerro
                }
1522 43981 omartinez
                this.updateComputedFields(computedFields);
1523 44189 jjdelcerro
                exitEditingMode();
1524
                loadDALFile();
1525 42293 jjdelcerro
                updateIndexes();
1526
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1527
                break;
1528 40435 jjdelcerro
            }
1529 40597 jldominguez
        } catch (PerformEditingException pee) {
1530 41437 jjdelcerro
            throw new WriteException(provider.getSourceId().toString(), pee);
1531 40435 jjdelcerro
        } catch (Exception e) {
1532
            throw new FinishEditingException(e);
1533
        }
1534
    }
1535 43981 omartinez
    private Map<String,List<FeatureAttributeDescriptor>> getComputedFields() throws DataException {
1536
        Map<String,List<FeatureAttributeDescriptor>> r = new HashMap<>();
1537
1538
        List<FeatureType> theTypes = new ArrayList<>();
1539
        theTypes.addAll(this.getFeatureTypes());
1540
        theTypes.add(this.getDefaultFeatureType());
1541
        for( int n=0; n<theTypes.size(); n++ ) {
1542
            FeatureType type = theTypes.get(n);
1543
                for (FeatureAttributeDescriptor attrdesc : type) {
1544
                    FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
1545
                    if( emulator!= null) {
1546
                        List<FeatureAttributeDescriptor> l = r.get(type.getId());
1547
                        if (l==null) {
1548
                            l = new ArrayList<>();
1549
                            r.put(type.getId(), l);
1550
                        }
1551
                        l.add(attrdesc);
1552
                    }
1553
            }
1554
        }
1555
        return r;
1556
    }
1557
    private void updateComputedFields(Map<String,List<FeatureAttributeDescriptor>> computedFields) throws DataException {
1558
1559
        List<FeatureType> theTypes = new ArrayList<>();
1560
        theTypes.addAll(this.getFeatureTypes());
1561
        theTypes.add(this.getDefaultFeatureType());
1562
        for( int n=0; n<theTypes.size(); n++ ) {
1563
            DefaultFeatureType type = (DefaultFeatureType) theTypes.get(n);
1564
            List<FeatureAttributeDescriptor> x = computedFields.get(type.getId());
1565
            if(x!=null && !x.isEmpty()) {
1566
                for (FeatureAttributeDescriptor attrdesc : x) {
1567
                    if (type.get(attrdesc.getName())==null) {
1568
                        type.add(attrdesc);
1569
                    }
1570
                }
1571
            }
1572
        }
1573
1574
    }
1575 43967 jjdelcerro
    private List<FeatureStoreProvider.FeatureTypeChanged> removeCalculatedAttributes(List<FeatureStoreProvider.FeatureTypeChanged> ftypes) {
1576
        // FIXME: Falta por implementar
1577 43978 omartinez
//        for (FeatureStoreProvider.FeatureTypeChanged ftype : ftypes) {
1578
//            EditableFeatureType target = (EditableFeatureType) ftype.getTarget();
1579
//            for (FeatureAttributeDescriptor attributeDescriptor : ftype.getSource().getAttributeDescriptors()) {
1580
//                if (attributeDescriptor.isComputed()) {
1581
//                    target.remove(attributeDescriptor.getName());
1582
//                }
1583
//            }
1584
//        }
1585 43967 jjdelcerro
        return ftypes;
1586
    }
1587
1588 40435 jjdelcerro
1589 43954 jjdelcerro
    private void saveDALFile() {
1590 44190 jjdelcerro
        DataResource resource = null;
1591 43954 jjdelcerro
        try {
1592
            DataServerExplorer explorer = this.getExplorer();
1593 43956 jjdelcerro
            if( explorer == null ) {
1594
                return;
1595
            }
1596 44190 jjdelcerro
            resource = explorer.getResource(this, "dal");
1597 44160 jjdelcerro
            if( resource == null ) {
1598 43954 jjdelcerro
                return;
1599
            }
1600
            DALFile dalFile = DALFile.getDALFile();
1601
            dalFile.setStore(this);
1602
            if( !dalFile.isEmpty() ) {
1603 44160 jjdelcerro
                dalFile.write(resource);
1604 43954 jjdelcerro
            }
1605 44190 jjdelcerro
        } catch (Throwable ex) {
1606
            LOG.warn("Can't save DAL resource", ex);
1607
        } finally {
1608
            IOUtils.closeQuietly(resource);
1609 43954 jjdelcerro
        }
1610
    }
1611
1612
    private void loadDALFile() {
1613 44190 jjdelcerro
        DataResource resource = null;
1614 43954 jjdelcerro
        try {
1615
            DataServerExplorer explorer = this.getExplorer();
1616 43956 jjdelcerro
            if( explorer == null ) {
1617
                return;
1618
            }
1619 44190 jjdelcerro
            resource = explorer.getResource(this, "dal");
1620 44160 jjdelcerro
            if( resource == null || !resource.exists() ) {
1621 43954 jjdelcerro
                return;
1622
            }
1623 44160 jjdelcerro
            DALFile dalFile = DALFile.getDALFile(resource);
1624 43954 jjdelcerro
            if( !dalFile.isEmpty() ) {
1625
                dalFile.updateStore(this);
1626
            }
1627 44190 jjdelcerro
        } catch (Throwable ex) {
1628
            LOG.warn("Can't load DAL resource", ex);
1629
        } finally {
1630
            IOUtils.closeQuietly(resource);
1631 43954 jjdelcerro
        }
1632
    }
1633
1634 40435 jjdelcerro
    /**
1635 42293 jjdelcerro
     * Save changes in the provider without leaving the edit mode.
1636
     * Do not call observers to communicate a change of ediding mode.
1637
     * The operation's history is eliminated to prevent inconsistencies
1638
     * in the data.
1639 40435 jjdelcerro
     *
1640
     * @throws DataException
1641
     */
1642 43215 jjdelcerro
    @Override
1643 40435 jjdelcerro
    synchronized public void commitChanges() throws DataException {
1644 43215 jjdelcerro
      LOG.debug("commitChanges of mode: {}", mode);
1645 42293 jjdelcerro
      if( !canCommitChanges() ) {
1646
              throw new WriteNotAllowedException(getName());
1647
      }
1648
      try {
1649
        switch (mode) {
1650
        case MODE_QUERY:
1651
          throw new NeedEditingModeException(this.getName());
1652 40435 jjdelcerro
1653 42293 jjdelcerro
        case MODE_APPEND:
1654
          this.provider.endAppend();
1655
          exitEditingMode();
1656
          invalidateIndexes();
1657
          this.provider.beginAppend();
1658
          hasInserts = false;
1659
          break;
1660 40435 jjdelcerro
1661 42293 jjdelcerro
        case MODE_FULLEDIT:
1662
          if (hasStrongChanges && !this.allowWrite()) {
1663
            throw new WriteNotAllowedException(getName());
1664
          }
1665
          if (hasStrongChanges) {
1666
            validateFeatures(Feature.FINISH_EDITING);
1667
            provider.performChanges(featureManager.getDeleted(),
1668
              featureManager.getInserted(),
1669
              featureManager.getUpdated(),
1670 43967 jjdelcerro
              removeCalculatedAttributes(featureTypeManager.getFeatureTypesChanged()).iterator());
1671 42293 jjdelcerro
          }
1672
          invalidateIndexes();
1673 43840 jjdelcerro
          featureManager = new FeatureManager();
1674
          featureTypeManager = new FeatureTypeManager(this);
1675
          spatialManager = new SpatialManager(this, provider.getEnvelope());
1676 40435 jjdelcerro
1677 42293 jjdelcerro
          commands =
1678
            new DefaultFeatureCommandsStack(this, featureManager,
1679
              spatialManager, featureTypeManager);
1680
          featureCount = null;
1681
          hasStrongChanges = false;
1682
          hasInserts = false;
1683
          break;
1684 40435 jjdelcerro
        }
1685 42293 jjdelcerro
      } catch (Exception e) {
1686
        throw new FinishEditingException(e);
1687
      }
1688 40435 jjdelcerro
    }
1689
1690 43215 jjdelcerro
    @Override
1691 40435 jjdelcerro
    synchronized public boolean canCommitChanges() throws DataException {
1692 42293 jjdelcerro
        if ( !this.allowWrite()) {
1693
                return false;
1694 40435 jjdelcerro
        }
1695 42293 jjdelcerro
            switch (mode) {
1696
            default:
1697
        case MODE_QUERY:
1698
                return false;
1699 41818 fdiaz
1700 42293 jjdelcerro
        case MODE_APPEND:
1701
                return true;
1702 41818 fdiaz
1703 42293 jjdelcerro
        case MODE_FULLEDIT:
1704
            List types = this.getFeatureTypes();
1705
            for( int i=0; i<types.size(); i++ ) {
1706
                    Object type = types.get(i);
1707
                    if( type instanceof DefaultEditableFeatureType ) {
1708
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1709
                                    return false;
1710
                            }
1711
                    }
1712
            }
1713
            return true;
1714
            }
1715 40435 jjdelcerro
    }
1716 41818 fdiaz
1717 43215 jjdelcerro
    @Override
1718 40435 jjdelcerro
    public void beginEditingGroup(String description)
1719 42293 jjdelcerro
        throws NeedEditingModeException {
1720 40435 jjdelcerro
        checkInEditingMode();
1721
        commands.startComplex(description);
1722
    }
1723
1724 43215 jjdelcerro
    @Override
1725 40435 jjdelcerro
    public void endEditingGroup() throws NeedEditingModeException {
1726
        checkInEditingMode();
1727
        commands.endComplex();
1728
    }
1729
1730 43215 jjdelcerro
    @Override
1731 40435 jjdelcerro
    public boolean isAppendModeSupported() {
1732
        return this.provider.supportsAppendMode();
1733
    }
1734
1735 43215 jjdelcerro
    @Override
1736 40435 jjdelcerro
    public void export(DataServerExplorer explorer, String provider,
1737 42293 jjdelcerro
        NewFeatureStoreParameters params) throws DataException {
1738 40435 jjdelcerro
1739
        if (this.getFeatureTypes().size() != 1) {
1740
            throw new NotYetImplemented(
1741 42293 jjdelcerro
                "export whith more than one type not yet implemented");
1742 40435 jjdelcerro
        }
1743
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1744
        FeatureStore target = null;
1745
        FeatureSet features = null;
1746
        DisposableIterator iterator = null;
1747
        try {
1748
            FeatureType type = this.getDefaultFeatureType();
1749
            if ((params.getDefaultFeatureType() == null)
1750 42293 jjdelcerro
                || (params.getDefaultFeatureType().size() == 0)) {
1751 40435 jjdelcerro
                params.setDefaultFeatureType(type.getEditable());
1752
1753
            }
1754
            explorer.add(provider, params, true);
1755
1756
            DataManager manager = DALLocator.getDataManager();
1757
            target = (FeatureStore) manager.openStore(provider, params);
1758
            FeatureType targetType = target.getDefaultFeatureType();
1759
1760
            target.edit(MODE_APPEND);
1761 43840 jjdelcerro
            FeatureAttributeDescriptor[] pkattrs = type.getPrimaryKey();
1762 40435 jjdelcerro
            if (featureSelection.getSize() > 0) {
1763
                features = this.getFeatureSelection();
1764
            } else {
1765 43840 jjdelcerro
                if ((pkattrs != null) && (pkattrs.length > 0)) {
1766 40435 jjdelcerro
                    FeatureQuery query = createFeatureQuery();
1767 43840 jjdelcerro
                    for (FeatureAttributeDescriptor pkattr : pkattrs) {
1768
                        query.getOrder().add(pkattr.getName(), true);
1769 40435 jjdelcerro
                    }
1770
                    features = this.getFeatureSet(query);
1771
                } else {
1772
                    features = this.getFeatureSet();
1773
                }
1774
            }
1775
            iterator = features.fastIterator();
1776
            while (iterator.hasNext()) {
1777
                DefaultFeature feature = (DefaultFeature) iterator.next();
1778
                target.insert(target.createNewFeature(targetType, feature));
1779
            }
1780
            target.finishEditing();
1781
            target.dispose();
1782
        } catch (Exception e) {
1783
            throw new DataExportException(e, params.toString());
1784
        } finally {
1785
            dispose(iterator);
1786
            dispose(features);
1787
            dispose(target);
1788
        }
1789
    }
1790
1791
    //
1792
    // ====================================================================
1793
    // Obtencion de datos
1794
    // getDataCollection, getFeatureCollection
1795
    //
1796 42293 jjdelcerro
1797 43215 jjdelcerro
    @Override
1798 40435 jjdelcerro
    public DataSet getDataSet() throws DataException {
1799
        checkNotInAppendMode();
1800 42293 jjdelcerro
        FeatureQuery query =
1801
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1802 40435 jjdelcerro
        return new DefaultFeatureSet(this, query);
1803
    }
1804
1805 43215 jjdelcerro
    @Override
1806 40435 jjdelcerro
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1807
        checkNotInAppendMode();
1808
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1809
    }
1810
1811 43215 jjdelcerro
    @Override
1812 40435 jjdelcerro
    public void getDataSet(Observer observer) throws DataException {
1813
        checkNotInAppendMode();
1814
        this.getFeatureSet(null, observer);
1815
    }
1816
1817 43215 jjdelcerro
    @Override
1818 40435 jjdelcerro
    public void getDataSet(DataQuery dataQuery, Observer observer)
1819 42293 jjdelcerro
        throws DataException {
1820 40435 jjdelcerro
        checkNotInAppendMode();
1821
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1822
    }
1823
1824 42799 jjdelcerro
    @Override
1825 40435 jjdelcerro
    public FeatureSet getFeatureSet() throws DataException {
1826 42799 jjdelcerro
        return this.getFeatureSet((FeatureQuery)null);
1827 40435 jjdelcerro
    }
1828
1829 42799 jjdelcerro
    @Override
1830 40435 jjdelcerro
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1831 42293 jjdelcerro
        throws DataException {
1832 40435 jjdelcerro
        checkNotInAppendMode();
1833 42799 jjdelcerro
        if( featureQuery==null ) {
1834
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1835
        }
1836 40435 jjdelcerro
        return new DefaultFeatureSet(this, featureQuery);
1837
    }
1838
1839 42925 jjdelcerro
    @Override
1840 43533 jjdelcerro
    public FeatureSet getFeatureSet(String filter) throws DataException {
1841
        return this.getFeatureSet(filter, null, true);
1842
    }
1843
1844
    @Override
1845
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1846
        return this.getFeatureSet(filter, sortBy, true);
1847
    }
1848
1849
    @Override
1850 44023 jjdelcerro
    public FeatureSet getFeatureSet(Expression filter) throws DataException {
1851
        return this.getFeatureSet(filter, null, true);
1852
    }
1853
1854
    @Override
1855
    public FeatureSet getFeatureSet(Expression filter, String sortBy) throws DataException {
1856
        return this.getFeatureSet(filter, sortBy, true);
1857
    }
1858 44190 jjdelcerro
1859 44023 jjdelcerro
    @Override
1860
    public FeatureSet getFeatureSet(Expression filter, String sortBy, boolean asc) throws DataException {
1861 44190 jjdelcerro
        FeatureQuery query = this.createFeatureQuery(filter, sortBy, asc);
1862 44023 jjdelcerro
        return this.getFeatureSet(query);
1863
    }
1864
1865
    @Override
1866 43533 jjdelcerro
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1867 44190 jjdelcerro
        FeatureQuery query = this.createFeatureQuery(filter, sortBy, asc);
1868 43533 jjdelcerro
        return this.getFeatureSet(query);
1869
    }
1870 43628 jjdelcerro
1871
    @Override
1872
    public List<Feature> getFeatures(String filter)  {
1873
        return this.getFeatures(filter, null, true);
1874
    }
1875 43533 jjdelcerro
1876
    @Override
1877 43628 jjdelcerro
    public List<Feature> getFeatures(String filter, String sortBy)  {
1878
        return this.getFeatures(filter, sortBy, true);
1879
    }
1880
1881
    @Override
1882
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1883 44190 jjdelcerro
        FeatureQuery query = this.createFeatureQuery(filter, sortBy, asc);
1884 43628 jjdelcerro
        return this.getFeatures(query, 100);
1885
    }
1886
1887
    @Override
1888 44023 jjdelcerro
    public List<Feature> getFeatures(Expression filter)  {
1889
        return this.getFeatures(filter, null, true);
1890
    }
1891
1892
    @Override
1893
    public List<Feature> getFeatures(Expression filter, String sortBy)  {
1894
        return this.getFeatures(filter, sortBy, true);
1895
    }
1896
1897
    @Override
1898
    public List<Feature> getFeatures(Expression filter, String sortBy, boolean asc)  {
1899 44190 jjdelcerro
        FeatureQuery query = this.createFeatureQuery(filter, sortBy, asc);
1900 44023 jjdelcerro
        return this.getFeatures(query, 100);
1901
    }
1902
1903
    @Override
1904 43550 jjdelcerro
    public List<Feature> getFeatures(FeatureQuery query)  {
1905
        return this.getFeatures(query, 100);
1906
    }
1907
1908
    @Override
1909 42925 jjdelcerro
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1910
        try {
1911
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1912
            return pager.asList();
1913
        } catch (BaseException ex) {
1914
            throw new RuntimeException("Can't create the list of features.", ex);
1915
        }
1916
    }
1917 43020 jjdelcerro
1918
    @Override
1919
    public List<Feature> getFeatures() {
1920
        return this.getFeatures(null, 500);
1921
    }
1922 43152 fdiaz
1923 43215 jjdelcerro
    @Override
1924 44100 jjdelcerro
    public Feature first() throws DataException {
1925 44190 jjdelcerro
        return this.findFirst((FeatureQuery)null);
1926 44100 jjdelcerro
    }
1927
1928
    @Override
1929 43628 jjdelcerro
    public Feature findFirst(String filter) throws DataException {
1930
        return this.findFirst(filter, null, true);
1931
    }
1932
1933
    @Override
1934
    public Feature findFirst(String filter, String sortBy) throws DataException {
1935
        return this.findFirst(filter, sortBy, true);
1936
    }
1937
1938
    @Override
1939
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1940 44190 jjdelcerro
        FeatureQuery query = this.createFeatureQuery(filter, sortBy, asc);
1941
        return findFirst(query);
1942 43628 jjdelcerro
    }
1943
1944
    @Override
1945 44023 jjdelcerro
    public Feature findFirst(Expression filter) throws DataException {
1946
        return this.findFirst(filter, null, true);
1947
    }
1948
1949
    @Override
1950
    public Feature findFirst(Expression filter, String sortBy) throws DataException {
1951
        return this.findFirst(filter, sortBy, true);
1952
    }
1953
1954
    @Override
1955
    public Feature findFirst(Expression filter, String sortBy, boolean asc) throws DataException {
1956 44190 jjdelcerro
        FeatureQuery query = this.createFeatureQuery(filter, sortBy, asc);
1957
        return findFirst(query);
1958
    }
1959
1960
    public Feature findFirst(FeatureQuery query) throws DataException {
1961
        final MutableObject<Feature> feature = new MutableObject<>();
1962
        try {
1963
            this.accept(new Visitor() {
1964
                @Override
1965
                public void visit(Object obj) throws VisitCanceledException, BaseException {
1966
                    feature.setValue((Feature) obj);
1967
                    throw new VisitCanceledException();
1968
                }
1969
            }, query);
1970
        } catch(VisitCanceledException ex) {
1971 44207 jjdelcerro
1972 44190 jjdelcerro
        } catch(DataException ex) {
1973
            throw ex;
1974
        } catch(Exception ex) {
1975
            throw new RuntimeException("", ex);
1976 44023 jjdelcerro
        }
1977 44207 jjdelcerro
        return feature.getValue();
1978 44023 jjdelcerro
    }
1979 44190 jjdelcerro
1980 44023 jjdelcerro
    @Override
1981 40435 jjdelcerro
    public void accept(Visitor visitor) throws BaseException {
1982 44190 jjdelcerro
        this.accept(visitor, null);
1983 40435 jjdelcerro
    }
1984
1985 43215 jjdelcerro
    @Override
1986 40435 jjdelcerro
    public void accept(Visitor visitor, DataQuery dataQuery)
1987 42293 jjdelcerro
        throws BaseException {
1988 40435 jjdelcerro
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1989
        try {
1990
            set.accept(visitor);
1991
        } finally {
1992
            set.dispose();
1993
        }
1994
    }
1995
1996
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1997 42293 jjdelcerro
        throws DataException {
1998
        DefaultFeatureType fType =
1999
            (DefaultFeatureType) this.getFeatureType(featureQuery
2000
                .getFeatureTypeId());
2001 43998 jjdelcerro
        if( featureQuery.hasAttributeNames() ||
2002
            featureQuery.hasConstantsAttributeNames() ||
2003
            fType.hasRequiredFields()
2004
            ) {
2005 42293 jjdelcerro
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
2006 40435 jjdelcerro
        }
2007
        return fType;
2008
    }
2009
2010 43215 jjdelcerro
    @Override
2011 40435 jjdelcerro
    public void getFeatureSet(Observer observer) throws DataException {
2012
        checkNotInAppendMode();
2013
        this.getFeatureSet(null, observer);
2014
    }
2015
2016 43215 jjdelcerro
    @Override
2017 40435 jjdelcerro
    public void getFeatureSet(FeatureQuery query, Observer observer)
2018 42293 jjdelcerro
        throws DataException {
2019 40435 jjdelcerro
        class LoadInBackGround implements Runnable {
2020
2021 43215 jjdelcerro
            private final FeatureStore store;
2022
            private final FeatureQuery query;
2023
            private final Observer observer;
2024 40435 jjdelcerro
2025
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
2026 42293 jjdelcerro
                Observer observer) {
2027 40435 jjdelcerro
                this.store = store;
2028
                this.query = query;
2029
                this.observer = observer;
2030
            }
2031
2032
            void notify(FeatureStoreNotification theNotification) {
2033
                observer.update(store, theNotification);
2034
            }
2035
2036 43215 jjdelcerro
            @Override
2037 40435 jjdelcerro
            public void run() {
2038
                FeatureSet set = null;
2039
                try {
2040
                    set = store.getFeatureSet(query);
2041
                    notify(new DefaultFeatureStoreNotification(store,
2042 42293 jjdelcerro
                        FeatureStoreNotification.LOAD_FINISHED, set));
2043 40435 jjdelcerro
                } catch (Exception e) {
2044
                    notify(new DefaultFeatureStoreNotification(store,
2045 42293 jjdelcerro
                        FeatureStoreNotification.LOAD_FINISHED, e));
2046 40435 jjdelcerro
                } finally {
2047
                    dispose(set);
2048
                }
2049
            }
2050
        }
2051
2052
        checkNotInAppendMode();
2053
        if (query == null) {
2054
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
2055
        }
2056
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
2057
        Thread thread = new Thread(task, "Load Feature Set in background");
2058
        thread.start();
2059
    }
2060
2061 43215 jjdelcerro
    @Override
2062 40435 jjdelcerro
    public Feature getFeatureByReference(FeatureReference reference)
2063 42293 jjdelcerro
        throws DataException {
2064 40435 jjdelcerro
        checkNotInAppendMode();
2065
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
2066
        FeatureType featureType;
2067
        if (ref.getFeatureTypeId() == null) {
2068
            featureType = this.getDefaultFeatureType();
2069
        } else {
2070
            featureType = this.getFeatureType(ref.getFeatureTypeId());
2071
        }
2072
        return this.getFeatureByReference(reference, featureType);
2073
    }
2074
2075 43215 jjdelcerro
    @Override
2076 40435 jjdelcerro
    public Feature getFeatureByReference(FeatureReference reference,
2077 42293 jjdelcerro
        FeatureType featureType) throws DataException {
2078 40435 jjdelcerro
        checkNotInAppendMode();
2079
        featureType = fixFeatureType((DefaultFeatureType) featureType);
2080
        if (this.mode == MODE_FULLEDIT) {
2081
            Feature f = featureManager.get(reference, this, featureType);
2082
            if (f != null) {
2083
                return f;
2084
            }
2085
        }
2086 41818 fdiaz
2087 42092 fdiaz
        FeatureType sourceFeatureType = featureType;
2088
        if (!this.transforms.isEmpty()) {
2089
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
2090
        }
2091
        // TODO comprobar que el id es de este store
2092 41818 fdiaz
2093 42293 jjdelcerro
        DefaultFeature feature =
2094
            new DefaultFeature(this,
2095
                this.provider.getFeatureProviderByReference(
2096
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
2097 40435 jjdelcerro
2098
        if (!this.transforms.isEmpty()) {
2099
            return this.transforms.applyTransform(feature, featureType);
2100
        }
2101
        return feature;
2102
    }
2103
2104
    //
2105
    // ====================================================================
2106
    // Gestion de features
2107
    //
2108 42293 jjdelcerro
2109 40435 jjdelcerro
    private FeatureType fixFeatureType(DefaultFeatureType type)
2110 42293 jjdelcerro
        throws DataException {
2111 40435 jjdelcerro
        FeatureType original = this.getDefaultFeatureType();
2112
2113
        if ((type == null) || type.equals(original)) {
2114
            return original;
2115
        } else {
2116
            if (!type.isSubtypeOf(original)) {
2117
                Iterator iter = this.getFeatureTypes().iterator();
2118
                FeatureType tmpType;
2119
                boolean found = false;
2120
                while (iter.hasNext()) {
2121
                    tmpType = (FeatureType) iter.next();
2122
                    if (type.equals(tmpType)) {
2123
                        return type;
2124
2125 42293 jjdelcerro
                    } else
2126
                        if (type.isSubtypeOf(tmpType)) {
2127
                            found = true;
2128
                            original = tmpType;
2129
                            break;
2130
                        }
2131 40435 jjdelcerro
2132
                }
2133
                if (!found) {
2134
                    throw new IllegalFeatureTypeException(getName());
2135
                }
2136
            }
2137
        }
2138
2139
        // Checks that type has all fields of pk
2140
        // else add the missing attributes at the end.
2141
        if (!original.hasOID()) {
2142
            // Gets original pk attributes
2143 42293 jjdelcerro
            DefaultEditableFeatureType edOriginal =
2144
                (DefaultEditableFeatureType) original.getEditable();
2145 40435 jjdelcerro
            FeatureAttributeDescriptor orgAttr;
2146
            Iterator edOriginalIter = edOriginal.iterator();
2147
            while (edOriginalIter.hasNext()) {
2148
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2149
                if (!orgAttr.isPrimaryKey()) {
2150
                    edOriginalIter.remove();
2151
                }
2152
            }
2153
2154
            // Checks if all pk attributes are in type
2155
            Iterator typeIterator;
2156
            edOriginalIter = edOriginal.iterator();
2157
            FeatureAttributeDescriptor attr;
2158
            while (edOriginalIter.hasNext()) {
2159
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
2160
                typeIterator = type.iterator();
2161
                while (typeIterator.hasNext()) {
2162
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
2163
                    if (attr.getName().equals(orgAttr.getName())) {
2164
                        edOriginalIter.remove();
2165
                        break;
2166
                    }
2167
                }
2168
            }
2169
2170
            // add missing pk attributes if any
2171
            if (edOriginal.size() > 0) {
2172
                boolean isEditable = type instanceof DefaultEditableFeatureType;
2173 42293 jjdelcerro
                DefaultEditableFeatureType edType =
2174
                    (DefaultEditableFeatureType) original.getEditable();
2175 40435 jjdelcerro
                edType.clear();
2176
                edType.addAll(type);
2177
                edType.addAll(edOriginal);
2178
                if (!isEditable) {
2179
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
2180
                }
2181
            }
2182
2183
        }
2184
2185
        return type;
2186
    }
2187
2188 43215 jjdelcerro
    @Override
2189 40435 jjdelcerro
    public void validateFeatures(int mode) throws DataException {
2190
        FeatureSet collection = null;
2191
        DisposableIterator iter = null;
2192
        try {
2193 43642 jjdelcerro
            FeatureRules rules = this.getDefaultFeatureType().getRules();
2194
            if( rules==null || rules.isEmpty() ) {
2195
                return;
2196
            }
2197 40435 jjdelcerro
            checkNotInAppendMode();
2198
            collection = this.getFeatureSet();
2199
            iter = collection.fastIterator();
2200
            long previousVersionOfUpdate = currentVersionOfUpdate();
2201
            while (iter.hasNext()) {
2202
                ((DefaultFeature) iter.next()).validate(mode);
2203
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
2204
                    throw new ConcurrentDataModificationException(getName());
2205
                }
2206
            }
2207
        } catch (Exception e) {
2208
            throw new ValidateFeaturesException(e, getName());
2209
        } finally {
2210 43642 jjdelcerro
            DisposeUtils.disposeQuietly(iter);
2211
            DisposeUtils.disposeQuietly(collection);
2212 40435 jjdelcerro
        }
2213
    }
2214
2215 43215 jjdelcerro
    @Override
2216 40435 jjdelcerro
    public FeatureType getDefaultFeatureType() throws DataException {
2217
        try {
2218 41818 fdiaz
2219 40435 jjdelcerro
            if (isEditing()) {
2220 42293 jjdelcerro
                FeatureType auxFeatureType =
2221
                    featureTypeManager.getType(defaultFeatureType.getId());
2222 40435 jjdelcerro
                if (auxFeatureType != null) {
2223
                    return avoidEditable(auxFeatureType);
2224
                }
2225
            }
2226
            FeatureType type = this.transforms.getDefaultFeatureType();
2227 43998 jjdelcerro
                if (type != null) {
2228 40435 jjdelcerro
                return avoidEditable(type);
2229 43998 jjdelcerro
                }
2230 41818 fdiaz
2231 40435 jjdelcerro
            return avoidEditable(defaultFeatureType);
2232 41818 fdiaz
2233 40435 jjdelcerro
        } catch (Exception e) {
2234
            throw new GetFeatureTypeException(e, getName());
2235
        }
2236
    }
2237 44190 jjdelcerro
2238 40435 jjdelcerro
    private FeatureType avoidEditable(FeatureType ft) {
2239
        if (ft instanceof EditableFeatureType) {
2240
            return ((EditableFeatureType) ft).getNotEditableCopy();
2241
        } else {
2242
            return ft;
2243
        }
2244
    }
2245
2246 43215 jjdelcerro
    @Override
2247 40435 jjdelcerro
    public FeatureType getFeatureType(String featureTypeId)
2248 42293 jjdelcerro
        throws DataException {
2249 40435 jjdelcerro
        if (featureTypeId == null) {
2250
            return this.getDefaultFeatureType();
2251
        }
2252
        try {
2253
            if (isEditing()) {
2254 42293 jjdelcerro
                FeatureType auxFeatureType =
2255
                    featureTypeManager.getType(featureTypeId);
2256 40435 jjdelcerro
                if (auxFeatureType != null) {
2257
                    return auxFeatureType;
2258
                }
2259
            }
2260
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2261
            if (type != null) {
2262
                return type;
2263
            }
2264
            Iterator iter = this.featureTypes.iterator();
2265
            while (iter.hasNext()) {
2266
                type = (FeatureType) iter.next();
2267
                if (type.getId().equals(featureTypeId)) {
2268
                    return type;
2269
                }
2270
            }
2271
            return null;
2272
        } catch (Exception e) {
2273
            throw new GetFeatureTypeException(e, getName());
2274
        }
2275
    }
2276
2277
    public FeatureType getProviderDefaultFeatureType() {
2278
        return defaultFeatureType;
2279
    }
2280
2281 43215 jjdelcerro
    @Override
2282 40435 jjdelcerro
    public List getFeatureTypes() throws DataException {
2283
        try {
2284
            List types;
2285
            if (isEditing()) {
2286
                types = new ArrayList();
2287
                Iterator it = featureTypes.iterator();
2288
                while (it.hasNext()) {
2289
                    FeatureType type = (FeatureType) it.next();
2290 42293 jjdelcerro
                    FeatureType typeaux =
2291
                        featureTypeManager.getType(type.getId());
2292 40435 jjdelcerro
                    if (typeaux != null) {
2293
                        types.add(typeaux);
2294
                    } else {
2295
                        types.add(type);
2296
                    }
2297
                }
2298
                it = featureTypeManager.newsIterator();
2299
                while (it.hasNext()) {
2300
                    FeatureType type = (FeatureType) it.next();
2301
                    types.add(type);
2302
                }
2303
            } else {
2304
                types = this.transforms.getFeatureTypes();
2305
                if (types == null) {
2306
                    types = featureTypes;
2307
                }
2308
            }
2309
            return Collections.unmodifiableList(types);
2310
        } catch (Exception e) {
2311
            throw new GetFeatureTypeException(e, getName());
2312
        }
2313
    }
2314
2315
    public List getProviderFeatureTypes() throws DataException {
2316
        return Collections.unmodifiableList(this.featureTypes);
2317
    }
2318
2319 43215 jjdelcerro
    @Override
2320 40435 jjdelcerro
    public Feature createFeature(FeatureProvider data) throws DataException {
2321
        DefaultFeature feature = new DefaultFeature(this, data);
2322
        return feature;
2323
    }
2324
2325
    public Feature createFeature(FeatureProvider data, FeatureType type)
2326 42293 jjdelcerro
        throws DataException {
2327 40435 jjdelcerro
        // FIXME: falta por implementar
2328
        // Comprobar si es un subtipo del feature de data
2329
        // y construir un feature usando el subtipo.
2330
        // Probablemente requiera generar una copia del data.
2331
        throw new NotYetImplemented();
2332
    }
2333
2334 43215 jjdelcerro
    @Override
2335 40435 jjdelcerro
    public EditableFeature createNewFeature(FeatureType type,
2336 42293 jjdelcerro
        Feature defaultValues) throws DataException {
2337 40435 jjdelcerro
        try {
2338
            FeatureProvider data = createNewFeatureProvider(type);
2339 42293 jjdelcerro
            DefaultEditableFeature feature =
2340
                new DefaultEditableFeature(this, data);
2341 40435 jjdelcerro
            feature.initializeValues(defaultValues);
2342
            data.setNew(true);
2343 41818 fdiaz
2344 40435 jjdelcerro
            return feature;
2345
        } catch (Exception e) {
2346
            throw new CreateFeatureException(e, getName());
2347
        }
2348
    }
2349
2350
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2351 42293 jjdelcerro
        throws DataException {
2352 40435 jjdelcerro
        type = this.fixFeatureType((DefaultFeatureType) type);
2353
        FeatureProvider data = this.provider.createFeatureProvider(type);
2354
        data.setNew(true);
2355
        if (type.hasOID() && (data.getOID() == null)) {
2356
            data.setOID(this.provider.createNewOID());
2357
        } else {
2358
            data.setOID(this.getTemporalOID());
2359
        }
2360
        return data;
2361
2362
    }
2363
2364 43215 jjdelcerro
    @Override
2365 40435 jjdelcerro
    public EditableFeature createNewFeature(FeatureType type,
2366 42293 jjdelcerro
        boolean defaultValues) throws DataException {
2367 40435 jjdelcerro
        try {
2368
            FeatureProvider data = createNewFeatureProvider(type);
2369 42293 jjdelcerro
            DefaultEditableFeature feature =
2370
                new DefaultEditableFeature(this, data);
2371 40435 jjdelcerro
            if (defaultValues) {
2372
                feature.initializeValues();
2373
            }
2374
            return feature;
2375
        } catch (Exception e) {
2376
            throw new CreateFeatureException(e, getName());
2377
        }
2378
    }
2379
2380 43215 jjdelcerro
    @Override
2381 40435 jjdelcerro
    public EditableFeature createNewFeature(boolean defaultValues)
2382 42293 jjdelcerro
        throws DataException {
2383 40435 jjdelcerro
        return this.createNewFeature(this.getDefaultFeatureType(),
2384 42293 jjdelcerro
            defaultValues);
2385 40435 jjdelcerro
    }
2386
2387 43215 jjdelcerro
    @Override
2388 40435 jjdelcerro
    public EditableFeature createNewFeature() throws DataException {
2389
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2390
    }
2391
2392 43215 jjdelcerro
    @Override
2393 42293 jjdelcerro
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2394
        FeatureType ft = this.getDefaultFeatureType();
2395
        EditableFeature f = this.createNewFeature(ft, false);
2396 43215 jjdelcerro
                for( FeatureAttributeDescriptor desc : ft ) {
2397
                        try {
2398
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2399
                        } catch(Throwable th) {
2400
                                // Ignore
2401
                        }
2402
                }
2403 42293 jjdelcerro
        return f;
2404
    }
2405
2406 43215 jjdelcerro
    @Override
2407 40435 jjdelcerro
    public EditableFeatureType createFeatureType() {
2408 43739 jjdelcerro
        EditableFeatureType ftype = new DefaultEditableFeatureType(this);
2409 40435 jjdelcerro
        return ftype;
2410
    }
2411
2412 43215 jjdelcerro
    @Override
2413 40435 jjdelcerro
    public EditableFeatureType createFeatureType(String id) {
2414 43739 jjdelcerro
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(this, id);
2415 40435 jjdelcerro
        return ftype;
2416
    }
2417
2418
    //
2419
    // ====================================================================
2420
    // Index related methods
2421
    //
2422 42293 jjdelcerro
2423 43215 jjdelcerro
    @Override
2424 40435 jjdelcerro
    public FeatureIndexes getIndexes() {
2425
        return this.indexes;
2426
    }
2427
2428 43215 jjdelcerro
    @Override
2429 40435 jjdelcerro
    public FeatureIndex createIndex(FeatureType featureType,
2430 42293 jjdelcerro
        String attributeName, String indexName) throws DataException {
2431 40435 jjdelcerro
        return createIndex(null, featureType, attributeName, indexName);
2432
    }
2433
2434 43215 jjdelcerro
    @Override
2435 40435 jjdelcerro
    public FeatureIndex createIndex(String indexTypeName,
2436 42293 jjdelcerro
        FeatureType featureType, String attributeName, String indexName)
2437
        throws DataException {
2438 40435 jjdelcerro
2439
        return createIndex(indexTypeName, featureType, attributeName,
2440 42293 jjdelcerro
            indexName, false, null);
2441 40435 jjdelcerro
    }
2442
2443 43215 jjdelcerro
    @Override
2444 40435 jjdelcerro
    public FeatureIndex createIndex(FeatureType featureType,
2445 42293 jjdelcerro
        String attributeName, String indexName, Observer observer)
2446
        throws DataException {
2447 40435 jjdelcerro
        return createIndex(null, featureType, attributeName, indexName,
2448 42293 jjdelcerro
            observer);
2449 40435 jjdelcerro
    }
2450
2451 43215 jjdelcerro
    @Override
2452 40435 jjdelcerro
    public FeatureIndex createIndex(String indexTypeName,
2453 42293 jjdelcerro
        FeatureType featureType, String attributeName, String indexName,
2454
        final Observer observer) throws DataException {
2455 40435 jjdelcerro
2456
        return createIndex(indexTypeName, featureType, attributeName,
2457 42293 jjdelcerro
            indexName, true, observer);
2458 40435 jjdelcerro
    }
2459
2460
    private FeatureIndex createIndex(String indexTypeName,
2461 42293 jjdelcerro
        FeatureType featureType, String attributeName, String indexName,
2462
        boolean background, final Observer observer) throws DataException {
2463 40435 jjdelcerro
2464
        checkNotInAppendMode();
2465 43215 jjdelcerro
        FeatureIndexProviderServices index;
2466
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2467 42293 jjdelcerro
                featureType, indexName,
2468
                featureType.getAttributeDescriptor(attributeName));
2469 40435 jjdelcerro
2470
        try {
2471
            index.fill(background, observer);
2472
        } catch (FeatureIndexException e) {
2473
            throw new InitializeException(index.getName(), e);
2474
        }
2475
2476
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2477
        return index;
2478
    }
2479
2480
    //
2481
    // ====================================================================
2482
    // Transforms related methods
2483
    //
2484 42293 jjdelcerro
2485 43215 jjdelcerro
    @Override
2486 40435 jjdelcerro
    public FeatureStoreTransforms getTransforms() {
2487
        return this.transforms;
2488
    }
2489
2490 43215 jjdelcerro
    @Override
2491 40435 jjdelcerro
    public FeatureQuery createFeatureQuery() {
2492
        return new DefaultFeatureQuery();
2493
    }
2494 44190 jjdelcerro
2495
    private FeatureQuery createFeatureQuery(Expression filter, String sortBy, boolean asc) {
2496
        FeatureQuery query = null;
2497
        if( filter!=null ) {
2498
            query = this.createFeatureQuery();
2499
            query.setFilter(filter);
2500
        }
2501
        if( !StringUtils.isEmpty(sortBy) ) {
2502
            if( query == null ) {
2503
                query = this.createFeatureQuery();
2504
            }
2505
            query.getOrder().add(sortBy, asc);
2506
        }
2507
        if( query != null ) {
2508
            query.retrievesAllAttributes();
2509
        }
2510
        return query;
2511
    }
2512
2513
    private FeatureQuery createFeatureQuery(String filter, String sortBy, boolean asc) {
2514
        FeatureQuery query = null;
2515
        if( !StringUtils.isEmpty(filter) ) {
2516
            query = this.createFeatureQuery();
2517
            query.setFilter(filter);
2518
        }
2519
        if( !StringUtils.isEmpty(sortBy) ) {
2520
            if( query == null ) {
2521
                query = this.createFeatureQuery();
2522
            }
2523
            query.getOrder().add(sortBy, asc);
2524
        }
2525
        if( query != null ) {
2526
            query.retrievesAllAttributes();
2527
        }
2528
        return query;
2529
    }
2530
2531 43215 jjdelcerro
    @Override
2532 40435 jjdelcerro
    public DataQuery createQuery() {
2533
        return createFeatureQuery();
2534
    }
2535
2536
    //
2537
    // ====================================================================
2538
    // UndoRedo related methods
2539
    //
2540 42293 jjdelcerro
2541 43215 jjdelcerro
    @Override
2542 40435 jjdelcerro
    public boolean canRedo() {
2543
        return commands.canRedo();
2544
    }
2545
2546 43215 jjdelcerro
    @Override
2547 40435 jjdelcerro
    public boolean canUndo() {
2548
        return commands.canUndo();
2549
    }
2550
2551 43215 jjdelcerro
    @Override
2552 40435 jjdelcerro
    public void redo(int num) throws RedoException {
2553
        for (int i = 0; i < num; i++) {
2554
            redo();
2555
        }
2556
    }
2557
2558 43215 jjdelcerro
    @Override
2559 40435 jjdelcerro
    public void undo(int num) throws UndoException {
2560
        for (int i = 0; i < num; i++) {
2561
            undo();
2562
        }
2563
    }
2564
2565
    //
2566
    // ====================================================================
2567
    // Metadata related methods
2568
    //
2569 42293 jjdelcerro
2570 43215 jjdelcerro
    @Override
2571 40435 jjdelcerro
    public Object getMetadataID() {
2572
        return this.provider.getSourceId();
2573
    }
2574
2575 43215 jjdelcerro
    @Override
2576 40435 jjdelcerro
    public void delegate(DynObject dynObject) {
2577
        this.metadata.delegate(dynObject);
2578
    }
2579
2580 43215 jjdelcerro
    @Override
2581 40435 jjdelcerro
    public DynClass getDynClass() {
2582
        return this.metadata.getDynClass();
2583
    }
2584
2585 43215 jjdelcerro
    @Override
2586 44165 jjdelcerro
    public Object getDynValue(String name) throws DynFieldNotFoundException {
2587
        try {
2588
            if (this.transforms.hasDynValue(name)) {
2589
                return this.transforms.getDynValue(name);
2590
            }
2591
            if (this.metadata.hasDynValue(name)) {
2592
                return this.metadata.getDynValue(name);
2593
            }
2594
            if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2595
                return this.provider.getProviderName();
2596
            } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2597
                return this.provider.getSourceId();
2598
            } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2599
                try {
2600
                    return this.getDefaultFeatureType();
2601
                } catch (DataException e) {
2602
                    return null;
2603
                }
2604
            }
2605
            return this.metadata.getDynValue(name);
2606
        } catch(Exception ex ) {
2607
            LOG.debug("Can't retrieve the value of '"+name+"' in store '"+this.getName()+"'.",ex);
2608
            return null;
2609
        }
2610
    }
2611 40435 jjdelcerro
2612 43215 jjdelcerro
    @Override
2613 40435 jjdelcerro
    public boolean hasDynValue(String name) {
2614 44165 jjdelcerro
        if (this.transforms.hasDynValue(name)) {
2615
            return true;
2616
        }
2617 40435 jjdelcerro
        return this.metadata.hasDynValue(name);
2618
    }
2619 43270 fdiaz
2620 43215 jjdelcerro
    @Override
2621 43246 jjdelcerro
    public boolean hasDynMethod(String name) {
2622
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2623
    }
2624 43270 fdiaz
2625 43246 jjdelcerro
    @Override
2626 40435 jjdelcerro
    public void implement(DynClass dynClass) {
2627
        this.metadata.implement(dynClass);
2628
    }
2629
2630 43215 jjdelcerro
    @Override
2631 42775 jjdelcerro
    public Object invokeDynMethod(String name, Object[] args)
2632 42293 jjdelcerro
        throws DynMethodException {
2633 42775 jjdelcerro
        return this.metadata.invokeDynMethod(this, name, args);
2634 40435 jjdelcerro
    }
2635
2636 43215 jjdelcerro
    @Override
2637 42775 jjdelcerro
    public Object invokeDynMethod(int code, Object[] args)
2638 42293 jjdelcerro
        throws DynMethodException {
2639 42775 jjdelcerro
        return this.metadata.invokeDynMethod(this, code, args);
2640 40435 jjdelcerro
    }
2641
2642 43215 jjdelcerro
    @Override
2643 40435 jjdelcerro
    public void setDynValue(String name, Object value)
2644 42293 jjdelcerro
        throws DynFieldNotFoundException {
2645
                if( this.transforms.hasDynValue(name) ) {
2646
                        this.transforms.setDynValue(name, value);
2647
                        return;
2648
                }
2649 40435 jjdelcerro
        this.metadata.setDynValue(name, value);
2650
2651
    }
2652
2653
    /*
2654
     * (non-Javadoc)
2655 41818 fdiaz
     *
2656 40435 jjdelcerro
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2657
     */
2658 43215 jjdelcerro
    @Override
2659 40435 jjdelcerro
    public Set getMetadataChildren() {
2660
        return this.metadataChildren;
2661
    }
2662
2663
    /*
2664
     * (non-Javadoc)
2665 41818 fdiaz
     *
2666 40435 jjdelcerro
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2667
     */
2668 43215 jjdelcerro
    @Override
2669 40435 jjdelcerro
    public String getMetadataName() {
2670
        return this.provider.getProviderName();
2671
    }
2672
2673
    public FeatureTypeManager getFeatureTypeManager() {
2674
        return this.featureTypeManager;
2675
    }
2676
2677 43215 jjdelcerro
    @Override
2678 40435 jjdelcerro
    public long getFeatureCount() throws DataException {
2679
        if (featureCount == null) {
2680 43215 jjdelcerro
            featureCount = this.provider.getFeatureCount();
2681 40435 jjdelcerro
        }
2682 42556 dmartinezizquierdo
        if (this.isEditing()) {
2683
            if(this.isAppending()) {
2684
                try{
2685
                    throw new IllegalStateException();
2686
                } catch(IllegalStateException e) {
2687 43840 jjdelcerro
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND",e);
2688 42556 dmartinezizquierdo
                }
2689
                return -1;
2690
            } else {
2691 43215 jjdelcerro
                return featureCount
2692 42556 dmartinezizquierdo
                    + this.featureManager.getDeltaSize();
2693
            }
2694 40435 jjdelcerro
        }
2695 43215 jjdelcerro
        return featureCount;
2696 40435 jjdelcerro
    }
2697
2698
    private Long getTemporalOID() {
2699 43215 jjdelcerro
        return this.temporalOid++;
2700 40435 jjdelcerro
    }
2701
2702 43215 jjdelcerro
    @Override
2703 40435 jjdelcerro
    public FeatureType getProviderFeatureType(String featureTypeId) {
2704
        if (featureTypeId == null) {
2705
            return this.defaultFeatureType;
2706
        }
2707
        FeatureType type;
2708
        Iterator iter = this.featureTypes.iterator();
2709
        while (iter.hasNext()) {
2710
            type = (FeatureType) iter.next();
2711
            if (type.getId().equals(featureTypeId)) {
2712
                return type;
2713
            }
2714
        }
2715
        return null;
2716
    }
2717
2718 43215 jjdelcerro
    @Override
2719 40435 jjdelcerro
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2720
        return ((DefaultFeature) feature).getData();
2721
    }
2722
2723 43215 jjdelcerro
    @Override
2724 40435 jjdelcerro
    public DataStore getStore() {
2725
        return this;
2726
    }
2727
2728 43215 jjdelcerro
    @Override
2729 40435 jjdelcerro
    public FeatureStore getFeatureStore() {
2730
        return this;
2731
    }
2732
2733 43215 jjdelcerro
    @Override
2734 43056 jjdelcerro
    public void createCache(String name, DynObject parameters)
2735
        throws DataException {
2736
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2737
        if (cache == null) {
2738
            throw new CreateException("FeaureCacheProvider", null);
2739
        }
2740
        cache.apply(this, provider);
2741
        provider = cache;
2742 40435 jjdelcerro
2743 43056 jjdelcerro
        featureCount = null;
2744
    }
2745
2746 43215 jjdelcerro
    @Override
2747 43056 jjdelcerro
    public FeatureCache getCache() {
2748
        return cache;
2749
    }
2750
2751 43215 jjdelcerro
    @Override
2752 40435 jjdelcerro
    public void clear() {
2753
        if (metadata != null) {
2754
            metadata.clear();
2755
        }
2756
    }
2757
2758 43215 jjdelcerro
    @Override
2759 40435 jjdelcerro
    public String getName() {
2760 43215 jjdelcerro
        if( this.provider != null ) {
2761
            return this.provider.getName();
2762
        }
2763
        if( this.parameters instanceof HasAFile ) {
2764
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2765
        }
2766
        return "unknow";
2767 40435 jjdelcerro
    }
2768
2769 43215 jjdelcerro
    @Override
2770 40435 jjdelcerro
    public String getFullName() {
2771 42049 jjdelcerro
        try {
2772 43215 jjdelcerro
            if( this.provider!=null ) {
2773
                return this.provider.getFullName();
2774
            }
2775
            if( this.parameters instanceof HasAFile ) {
2776
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2777
            }
2778
            return null;
2779 42293 jjdelcerro
        } catch(Throwable th) {
2780 42049 jjdelcerro
            return null;
2781
        }
2782 40435 jjdelcerro
    }
2783
2784 43215 jjdelcerro
    @Override
2785 40435 jjdelcerro
    public String getProviderName() {
2786 43215 jjdelcerro
        if( this.provider!=null ) {
2787
            return this.provider.getProviderName();
2788
        }
2789
        if( this.parameters != null ) {
2790
            return this.parameters.getDataStoreName();
2791
        }
2792
        return null;
2793 43270 fdiaz
2794 40435 jjdelcerro
    }
2795
2796 43215 jjdelcerro
    @Override
2797 40435 jjdelcerro
    public boolean isKnownEnvelope() {
2798
        return this.provider.isKnownEnvelope();
2799
    }
2800
2801 43215 jjdelcerro
    @Override
2802 40435 jjdelcerro
    public boolean hasRetrievedFeaturesLimit() {
2803
        return this.provider.hasRetrievedFeaturesLimit();
2804
    }
2805
2806 43215 jjdelcerro
    @Override
2807 40435 jjdelcerro
    public int getRetrievedFeaturesLimit() {
2808
        return this.provider.getRetrievedFeaturesLimit();
2809
    }
2810
2811 43215 jjdelcerro
    @Override
2812 41818 fdiaz
    public Interval getInterval() {
2813 43135 jjdelcerro
        if( this.timeSupport!=null ) {
2814
            return this.timeSupport.getInterval();
2815
        }
2816 44077 jjdelcerro
        try {
2817
            FeatureType type = this.getDefaultFeatureType();
2818
            FeatureAttributeDescriptor attr = type.getDefaultTimeAttribute();
2819
            if( attr!=null ) {
2820
                Interval interval = attr.getInterval();
2821
                if( interval!=null ) {
2822
                    return interval;
2823
                }
2824
            }
2825
        } catch (DataException ex) {
2826
        }
2827 40435 jjdelcerro
        return this.provider.getInterval();
2828
    }
2829
2830 43215 jjdelcerro
    @Override
2831 41818 fdiaz
    public Collection getTimes() {
2832 43135 jjdelcerro
        if( this.timeSupport!=null ) {
2833
            return this.timeSupport.getTimes();
2834
        }
2835 40435 jjdelcerro
        return this.provider.getTimes();
2836
    }
2837
2838 43215 jjdelcerro
    @Override
2839 41818 fdiaz
    public Collection getTimes(Interval interval) {
2840 43135 jjdelcerro
        if( this.timeSupport!=null ) {
2841
            return this.timeSupport.getTimes(interval);
2842
        }
2843 40435 jjdelcerro
        return this.provider.getTimes(interval);
2844
    }
2845 41818 fdiaz
2846 43135 jjdelcerro
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2847 43610 jjdelcerro
        if( this.isEditing() ) {
2848
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2849 43135 jjdelcerro
        }
2850 43610 jjdelcerro
        if( !this.transforms.isEmpty() ) {
2851
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2852 43135 jjdelcerro
        }
2853 43610 jjdelcerro
        FeatureType ft = this.defaultFeatureType;
2854
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2855
        if( attr == null ) {
2856 43135 jjdelcerro
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2857
        }
2858 43610 jjdelcerro
        EditableFeatureType eft = ft.getEditable();
2859
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2860
        if( attr != null ) {
2861
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2862
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2863
            }
2864
            eft.remove(attr.getName());
2865
        }
2866
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2867
            timeSupport.getAttributeName(),
2868
            timeSupport.getDataType()
2869
        );
2870
        attrTime.setIsTime(true);
2871
        attrTime.setFeatureAttributeEmulator(timeSupport);
2872
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2873
        this.defaultFeatureType = eft.getNotEditableCopy();
2874
2875 43135 jjdelcerro
        this.timeSupport = timeSupport;
2876
    }
2877 43152 fdiaz
2878 43215 jjdelcerro
    @Override
2879 43840 jjdelcerro
    @SuppressWarnings("CloneDoesntCallSuperClone")
2880 40435 jjdelcerro
    public Object clone() throws CloneNotSupportedException {
2881 41818 fdiaz
2882 40435 jjdelcerro
        DataStoreParameters dsp = getParameters();
2883 41818 fdiaz
2884 40435 jjdelcerro
        DefaultFeatureStore cloned_store = null;
2885 41818 fdiaz
2886 40435 jjdelcerro
        try {
2887
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2888 42293 jjdelcerro
                openStore(this.getProviderName(), dsp);
2889 40435 jjdelcerro
            if (transforms != null) {
2890
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2891 41093 jldominguez
                cloned_store.transforms.setStoreForClone(cloned_store);
2892 40435 jjdelcerro
            }
2893
        } catch (Exception e) {
2894
            throw new CloneException(e);
2895 41818 fdiaz
        }
2896 40435 jjdelcerro
        return cloned_store;
2897 41818 fdiaz
2898 40435 jjdelcerro
    }
2899 41818 fdiaz
2900 43215 jjdelcerro
    @Override
2901 41818 fdiaz
    public Feature getFeature(DynObject dynobject) {
2902 42293 jjdelcerro
        if (dynobject instanceof DynObjectFeatureFacade){
2903
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2904 41818 fdiaz
            return f;
2905
        }
2906
        return null;
2907
    }
2908 42533 dmartinezizquierdo
2909 43215 jjdelcerro
    @Override
2910 42293 jjdelcerro
    public Iterator iterator() {
2911
        try {
2912
            return this.getFeatureSet().fastIterator();
2913
        } catch (DataException ex) {
2914
            throw new RuntimeException(ex);
2915
        }
2916
    }
2917 43020 jjdelcerro
2918
    @Override
2919 43521 jjdelcerro
    public ExpressionBuilder createExpressionBuilder() {
2920 44259 jjdelcerro
        ExpressionBuilder builder;
2921
        builder = ExpressionEvaluatorLocator.getManager().createExpressionBuilder();
2922 44042 jjdelcerro
        return builder;
2923 43020 jjdelcerro
    }
2924 43062 jjdelcerro
2925 43521 jjdelcerro
    @Override
2926
    public ExpressionBuilder createExpression() {
2927
        return createExpressionBuilder();
2928
    }
2929 43152 fdiaz
2930 43062 jjdelcerro
    public FeatureSet features() throws DataException {
2931
        // This is to avoid jython to create a property with this name
2932
        // to access method getFeatures.
2933
        return this.getFeatureSet();
2934
    }
2935 43152 fdiaz
2936
    @Override
2937 43190 jjdelcerro
    public DataStoreProviderFactory getProviderFactory() {
2938 43152 fdiaz
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2939
        return factory;
2940
    }
2941
2942
    @Override
2943
    public void useCache(String providerName, DynObject parameters) throws DataException {
2944
        throw new UnsupportedOperationException();
2945
    }
2946 43270 fdiaz
2947 43215 jjdelcerro
    @Override
2948
    public boolean isBroken() {
2949
        return this.state.isBroken();
2950
    }
2951
2952
    @Override
2953
    public Throwable getBreakingsCause() {
2954
            return this.state.getBreakingsCause();
2955
    }
2956 43371 fdiaz
2957
    @Override
2958
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2959 43705 jjdelcerro
      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2960
      if( !factory.supportNumericOID() ) {
2961
          return null;
2962
      }
2963 43371 fdiaz
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2964
      return wrappedIndex;
2965
  }
2966 43824 jjdelcerro
2967
    @Override
2968
    public FeatureReference getFeatureReference(String code) {
2969
        FeatureReference featureReference = new DefaultFeatureReference(this, code);
2970
        return featureReference;
2971
    }
2972 44111 jjdelcerro
2973
    @Override
2974
    public long getPendingChangesCount() {
2975
        if( this.featureManager==null ) {
2976
            return 0;
2977
        }
2978
        return this.featureManager.getPendingChangesCount();
2979
    }
2980 44251 jjdelcerro
2981
    @Override
2982
    public ResourcesStorage getResourcesStorage() {
2983
        return new DALResourcesStorage(this);
2984
    }
2985 44259 jjdelcerro
2986
    @Override
2987
    public StoresRepository getStoresRepository() {
2988
        final StoresRepository mainRepository = this.dataManager.getStoresRepository();
2989
        StoresRepository repository = new StoresRepository() {
2990
            @Override
2991
            public void add(String name, DataStoreParameters parameters) {
2992
                mainRepository.add(name, parameters);
2993
            }
2994
2995
            @Override
2996
            public void remove(String name) {
2997
                mainRepository.remove(name);
2998
            }
2999
3000
            @Override
3001
            public DataStore get(String key) {
3002
                DataStore store = getChildren().get(key);
3003
                if( store != null ) {
3004
                    return store;
3005
                }
3006
                return mainRepository.get(key);
3007
            }
3008
3009
            @Override
3010
            public boolean isEmpty() {
3011
                return getChildren().isEmpty() && mainRepository.isEmpty();
3012
            }
3013
3014
            @Override
3015
            public boolean containsKey(String key) {
3016
                return getChildren().containsKey(key) || mainRepository.containsKey(key);
3017
            }
3018
3019
            @Override
3020
            public Map<String, DataStore> toMap() {
3021
                return null;
3022
            }
3023
3024
            @Override
3025
            public int size() {
3026
                return getChildren().size()+mainRepository.size();
3027
            }
3028
3029
            @Override
3030
            public UnmodifiableBasicSet<String> keySet() {
3031
                UnmodifiableBasicMap<String, DataStore> children = getChildren();
3032
                if( children.isEmpty() ) {
3033
                    return mainRepository.keySet();
3034
                }
3035
                return new UnmodifiableBasicSetChained<>(
3036
                        children.keySet(),
3037
                        mainRepository.keySet()
3038
                );
3039
            }
3040
3041
            @Override
3042
            public Iterator<DataStore> iterator() {
3043
                final Iterator<String> it = this.keySet().iterator();
3044
                return new Iterator<DataStore>() {
3045
                    @Override
3046
                    public boolean hasNext() {
3047
                        return it.hasNext();
3048
                    }
3049
3050
                    @Override
3051
                    public DataStore next() {
3052
                        String name = it.next();
3053
                        return get(name);
3054
                    }
3055
                };
3056
            }
3057
        };
3058
        return repository;
3059
    }
3060 44111 jjdelcerro
3061 42293 jjdelcerro
}