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

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