Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / 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 @ 43828

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