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

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