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

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