Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 43093

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