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

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