Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 37327

History | View | Annotate | Download (66.7 KB)

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