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

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