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

History | View | Annotate | Download (72.9 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
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.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

    
42
import org.gvsig.fmap.dal.DALLocator;
43
import org.gvsig.fmap.dal.DataManager;
44
import org.gvsig.fmap.dal.DataQuery;
45
import org.gvsig.fmap.dal.DataServerExplorer;
46
import org.gvsig.fmap.dal.DataSet;
47
import org.gvsig.fmap.dal.DataStore;
48
import org.gvsig.fmap.dal.DataStoreNotification;
49
import org.gvsig.fmap.dal.DataStoreParameters;
50
import org.gvsig.fmap.dal.exception.CloneException;
51
import org.gvsig.fmap.dal.exception.CloseException;
52
import org.gvsig.fmap.dal.exception.CreateException;
53
import org.gvsig.fmap.dal.exception.DataException;
54
import org.gvsig.fmap.dal.exception.InitializeException;
55
import org.gvsig.fmap.dal.exception.OpenException;
56
import org.gvsig.fmap.dal.exception.ReadException;
57
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
58
import org.gvsig.fmap.dal.exception.WriteException;
59
import org.gvsig.fmap.dal.feature.EditableFeature;
60
import org.gvsig.fmap.dal.feature.EditableFeatureType;
61
import org.gvsig.fmap.dal.feature.Feature;
62
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
63
import org.gvsig.fmap.dal.feature.FeatureCache;
64
import org.gvsig.fmap.dal.feature.FeatureIndex;
65
import org.gvsig.fmap.dal.feature.FeatureIndexes;
66
import org.gvsig.fmap.dal.feature.FeatureLocks;
67
import org.gvsig.fmap.dal.feature.FeatureQuery;
68
import org.gvsig.fmap.dal.feature.FeatureReference;
69
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
70
import org.gvsig.fmap.dal.feature.FeatureSelection;
71
import org.gvsig.fmap.dal.feature.FeatureSet;
72
import org.gvsig.fmap.dal.feature.FeatureStore;
73
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
74
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
75
import org.gvsig.fmap.dal.feature.FeatureType;
76
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
77
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
78
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
79
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
80
import org.gvsig.fmap.dal.feature.exception.DataExportException;
81
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
82
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
83
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
84
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
85
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
86
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
87
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
88
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
89
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
90
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
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
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
104
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
105
import org.gvsig.fmap.dal.feature.impl.featureset.DynObjectFeatureFacade;
106
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
107
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
108
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
109
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
110
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
111
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
112
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
113
import org.gvsig.fmap.dal.feature.spi.cache.FeatureCacheProvider;
114
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
115
import org.gvsig.fmap.dal.impl.DefaultDataManager;
116
import org.gvsig.fmap.dal.resource.Resource;
117
import org.gvsig.fmap.dal.spi.DataStoreInitializer;
118
import org.gvsig.fmap.dal.spi.DataStoreProvider;
119
import org.gvsig.fmap.geom.primitive.Envelope;
120
import org.gvsig.metadata.MetadataLocator;
121
import org.gvsig.metadata.MetadataManager;
122
import org.gvsig.metadata.exceptions.MetadataException;
123
import org.gvsig.timesupport.Interval;
124
import org.gvsig.tools.ToolsLocator;
125
import org.gvsig.tools.dispose.DisposableIterator;
126
import org.gvsig.tools.dispose.impl.AbstractDisposable;
127
import org.gvsig.tools.dynobject.DelegatedDynObject;
128
import org.gvsig.tools.dynobject.DynClass;
129
import org.gvsig.tools.dynobject.DynObject;
130
import org.gvsig.tools.dynobject.DynObjectManager;
131
import org.gvsig.tools.dynobject.DynStruct;
132
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
133
import org.gvsig.tools.dynobject.exception.DynMethodException;
134
import org.gvsig.tools.exception.BaseException;
135
import org.gvsig.tools.exception.NotYetImplemented;
136
import org.gvsig.tools.identitymanagement.SimpleIdentityManager;
137
import org.gvsig.tools.observer.Observable;
138
import org.gvsig.tools.observer.Observer;
139
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
140
import org.gvsig.tools.persistence.PersistenceManager;
141
import org.gvsig.tools.persistence.Persistent;
142
import org.gvsig.tools.persistence.PersistentState;
143
import org.gvsig.tools.persistence.exception.PersistenceException;
144
import org.gvsig.tools.undo.RedoException;
145
import org.gvsig.tools.undo.UndoException;
146
import org.gvsig.tools.undo.command.Command;
147
import org.gvsig.tools.visitor.Visitor;
148

    
149
public class DefaultFeatureStore extends AbstractDisposable implements
150
    DataStoreInitializer, FeatureStoreProviderServices, FeatureStore, Observer {
151

    
152
    private static final Logger LOG = LoggerFactory
153
        .getLogger(DefaultFeatureStore.class);
154

    
155
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
156

    
157
    private DataStoreParameters parameters = null;
158
    private FeatureSelection selection;
159
    private FeatureLocks locks;
160

    
161
    private DelegateWeakReferencingObservable delegateObservable =
162
        new DelegateWeakReferencingObservable(this);
163

    
164
    private FeatureCommandsStack commands;
165
    private FeatureTypeManager featureTypeManager;
166
    private FeatureManager featureManager;
167
    private SpatialManager spatialManager;
168

    
169
    private FeatureType defaultFeatureType = null;
170
    private List featureTypes = new ArrayList();
171

    
172
    private int mode = MODE_QUERY;
173
    private long versionOfUpdate = 0;
174
    private boolean hasStrongChanges = true;
175
    private boolean hasInserts = true;
176

    
177
    private DefaultDataManager dataManager = null;
178

    
179
    private FeatureStoreProvider provider = null;
180

    
181
    private DefaultFeatureIndexes indexes;
182

    
183
    private DefaultFeatureStoreTransforms transforms;
184

    
185
    DelegatedDynObject metadata;
186

    
187
    private Set metadataChildren;
188

    
189
    private Long featureCount = null;
190

    
191
    private long temporalOid = 0;
192

    
193
    private FeatureCacheProvider cache;
194

    
195
    /*
196
     * TODO:
197
     *
198
     * - Comprobar que solo se pueden a�adir reglas de validacion sobre un
199
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
200
     * featureType al que se le han cambiado las reglas de validacion cuando
201
     * hasStrongChanges=false.
202
     */
203

    
204
    public DefaultFeatureStore() {
205

    
206
    }
207

    
208
    public void intializePhase1(DataManager dataManager,
209
        DataStoreParameters parameters) throws InitializeException {
210

    
211
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
212

    
213
        this.metadata =
214
            (DelegatedDynObject) dynManager.createDynObject(
215
                METADATA_DEFINITION_NAME, MetadataManager.METADATA_NAMESPACE);
216

    
217
        this.dataManager = (DefaultDataManager) dataManager;
218

    
219
        this.parameters = parameters;
220
        this.transforms = new DefaultFeatureStoreTransforms(this);
221
        try {
222
            indexes = new DefaultFeatureIndexes(this);
223
        } catch (DataException e) {
224
            throw new InitializeException(e);
225
        }
226

    
227
    }
228

    
229
    public void intializePhase2(DataStoreProvider provider) {
230
        this.provider = (FeatureStoreProvider) provider;
231
        this.delegate(provider);
232
        this.metadataChildren = new HashSet();
233
        this.metadataChildren.add(provider);
234
    }
235

    
236
    public DataStoreParameters getParameters() {
237
        return parameters;
238
    }
239

    
240
    public int getMode() {
241
        return this.mode;
242
    }
243

    
244
    public DataManager getManager() {
245
        return this.dataManager;
246
    }
247

    
248
    public Iterator getChildren() {
249
        return this.provider.getChilds();
250
    }
251

    
252
    public FeatureStoreProvider getProvider() {
253
        return this.provider;
254
    }
255

    
256
    public FeatureManager getFeatureManager() {
257
        return this.featureManager;
258
    }
259

    
260
    public void setFeatureTypes(List types, FeatureType defaultType) {
261
        this.featureTypes = types;
262
        this.defaultFeatureType = defaultType;
263
    }
264

    
265
    public void open() throws OpenException {
266
        // TODO: Se puede hacer un open estando en edicion ?
267
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
268
        this.provider.open();
269
        this.notifyChange(DataStoreNotification.AFTER_OPEN);
270
    }
271

    
272
    public void refresh() throws OpenException, InitializeException {
273
        if (this.mode != MODE_QUERY) {
274
            throw new IllegalStateException();
275
        }
276
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
277
        this.featureCount = null;
278
        this.provider.refresh();
279
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
280
    }
281

    
282
    public void close() throws CloseException {
283
        // TODO: Se puede hacer un close estando en edicion ?
284
        this.notifyChange(DataStoreNotification.BEFORE_CLOSE);
285
        this.featureCount = null;
286
        this.provider.close();
287
        this.notifyChange(DataStoreNotification.AFTER_CLOSE);
288
    }
289

    
290
    protected void doDispose() throws BaseException {
291
        this.notifyChange(DataStoreNotification.BEFORE_DISPOSE);
292
        this.disposeIndexes();
293
        this.provider.dispose();
294
        if (this.selection != null) {
295
            this.selection.dispose();
296
            this.selection = null;
297
        }
298
        this.commands = null;
299
        this.featureCount = null;
300
        if (this.locks != null) {
301
            // this.locks.dispose();
302
            this.locks = null;
303
        }
304

    
305
        if (this.featureTypeManager != null) {
306
            this.featureTypeManager.dispose();
307
            this.featureTypeManager = null;
308
        }
309

    
310
        this.featureManager = null;
311
        this.spatialManager = null;
312

    
313
        this.parameters = null;
314
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
315
        if (delegateObservable != null) {
316
            this.delegateObservable.deleteObservers();
317
            this.delegateObservable = null;
318
        }
319
    }
320

    
321
    public boolean allowWrite() {
322
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
323
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
324
            return false;
325
        }
326
        return this.provider.allowWrite();
327
    }
328

    
329
    public boolean canWriteGeometry(int geometryType) throws DataException {
330
        return this.provider.canWriteGeometry(geometryType, 0);
331
    }
332

    
333
    public DataServerExplorer getExplorer() throws ReadException,
334
        ValidateDataParametersException {
335
        return this.provider.getExplorer();
336
    }
337

    
338
    /*
339
     * public Metadata getMetadata() throws MetadataNotFoundException {
340
     * // TODO:
341
     * // Si el provider devuelbe null habria que ver de construir aqui
342
     * // los metadatos basicos, como el Envelope y el SRS.
343
     *
344
     * // TODO: Estando en edicion el Envelope deberia de
345
     * // actualizarse usando el spatialManager
346
     * return this.provider.getMetadata();
347
     * }
348
     */
349

    
350
    public Envelope getEnvelope() throws DataException {
351
        if (this.mode == MODE_FULLEDIT) {
352
                // Just in case another thread tries to write in the store
353
                synchronized (this) {
354
                        return this.spatialManager.getEnvelope();
355
                        }
356
        }
357
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
358
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
359
        }
360
        return this.provider.getEnvelope();
361
    }
362

    
363
    /**
364
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
365
     */
366
    public IProjection getSRSDefaultGeometry() throws DataException {
367
        return this.getDefaultFeatureType().getDefaultSRS();
368
    }
369

    
370
    public FeatureSelection createDefaultFeatureSelection()
371
        throws DataException {
372
        return new DefaultFeatureSelection(this);
373
    }
374

    
375
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
376
        throws DataException {
377
        if (type.hasOID()) {
378
            return new DefaultFeatureProvider(type,
379
                this.provider.createNewOID());
380
        }
381
        return new DefaultFeatureProvider(type);
382
    }
383

    
384
    public void saveToState(PersistentState state) throws PersistenceException {
385
        /*if (this.mode != FeatureStore.MODE_QUERY) {
386
            throw new PersistenceException(new IllegalStateException(
387
                this.getName()));
388
        }*/
389
        state.set("dataStoreName", this.getName());
390
        state.set("parameters", this.parameters);
391
        state.set("selection", this.selection);
392
        state.set("transforms", this.transforms);
393
        // TODO locks persistence
394
        // state.set("locks", this.locks);
395
        // TODO indexes persistence
396
        // state.set("indexes", this.indexes);
397
        Map evaluatedAttr = new HashMap(1);
398
        Iterator iterType = featureTypes.iterator();
399
        Iterator iterAttr;
400
        FeatureType type;
401
        DefaultFeatureAttributeDescriptor attr;
402
        List attrs;
403
        while (iterType.hasNext()) {
404
            type = (FeatureType) iterType.next();
405
            attrs = new ArrayList();
406
            iterAttr = type.iterator();
407
            while (iterAttr.hasNext()) {
408
                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
409
                if ((attr.getEvaluator() != null)
410
                    && (attr.getEvaluator() instanceof Persistent)) {
411
                    attrs.add(attr);
412
                }
413
            }
414
            if (!attrs.isEmpty()) {
415
                evaluatedAttr.put(type.getId(), attrs);
416
            }
417

    
418
        }
419

    
420
        if (evaluatedAttr.isEmpty()) {
421
            evaluatedAttr = null;
422
        }
423

    
424
        state.set("evaluatedAttributes", evaluatedAttr);
425
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
426

    
427
    }
428

    
429
    public void loadFromState(PersistentState state)
430
        throws PersistenceException {
431
        if (this.provider != null) {
432
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
433
        }
434
        if (this.getManager() == null) {
435
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
436
        }
437

    
438
        DataStoreParameters params =
439
            (DataStoreParameters) state.get("parameters");
440

    
441
        try {
442

    
443
            this.dataManager.intializeDataStore(this, params);
444
            this.selection = (FeatureSelection) state.get("selection");
445
            this.transforms =
446
                (DefaultFeatureStoreTransforms) state.get("transforms");
447
            Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
448
            if ((evaluatedAttributes != null) && !evaluatedAttributes.isEmpty()) {
449
                List attrs;
450
                Iterator iterEntries =
451
                    evaluatedAttributes.entrySet().iterator();
452
                Entry entry;
453
                while (iterEntries.hasNext()) {
454
                    entry = (Entry) iterEntries.next();
455
                    attrs = (List) entry.getValue();
456
                    if (attrs.isEmpty()) {
457
                        continue;
458
                    }
459
                    int fTypePos = -1;
460
                    DefaultFeatureType type = null;
461
                    for (int i = 0; i < featureTypes.size(); i++) {
462
                        type = (DefaultFeatureType) featureTypes.get(i);
463
                        if (type.getId().equals(entry.getKey())) {
464
                            fTypePos = i;
465
                            break;
466
                        }
467
                    }
468
                    if (fTypePos < 0) {
469
                        throw new PersistenceCantFindFeatureTypeException(
470
                            this.getName(), (String) entry.getKey());
471
                    }
472
                    DefaultEditableFeatureType eType =
473
                        (DefaultEditableFeatureType) type.getEditable();
474
                    Iterator iterAttr = attrs.iterator();
475
                    FeatureAttributeDescriptor attr;
476
                    while (iterAttr.hasNext()) {
477
                        attr = (FeatureAttributeDescriptor) iterAttr.next();
478
                        eType.addLike(attr);
479
                    }
480
                    featureTypes.set(fTypePos, eType.getNotEditableCopy());
481

    
482
                }
483

    
484
            }
485

    
486
            String defFTypeid = state.getString("defaultFeatureTypeId");
487
            FeatureType ftype = null;
488

    
489
            if (this.defaultFeatureType == null ||
490
                this.defaultFeatureType.getId() == null ||
491
                !this.defaultFeatureType.getId().equals(
492
                state.getString("defaultFeatureTypeId"))) {
493

    
494
                ftype = getFeatureType(defFTypeid);
495
                if (ftype == null) {
496
                    throw new PersistenceCantFindDefaultFeatureTypeException(
497
                        this.getName(), defFTypeid);
498
                }
499
                this.defaultFeatureType = ftype;
500
            }
501

    
502
        } catch (InitializeException e) {
503
            throw new PersistenceException(e);
504
        } catch (DataException e) {
505
            throw new PersistenceException(e);
506
        }
507

    
508
    }
509

    
510
    public static void registerPersistenceDefinition() {
511
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
512
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
513
            DynStruct definition =
514
                manager.addDefinition(DefaultFeatureStore.class,
515
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
516
                        + " Persistent definition", null, null);
517
            definition.addDynFieldString("dataStoreName").setMandatory(true)
518
                .setPersistent(true);
519

    
520
            definition.addDynFieldObject("parameters")
521
                .setClassOfValue(DynObject.class).setMandatory(true)
522
                .setPersistent(true);
523

    
524
            definition.addDynFieldObject("selection")
525
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
526
                .setPersistent(true);
527

    
528
            definition.addDynFieldObject("transforms")
529
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
530
                .setMandatory(true).setPersistent(true);
531

    
532
            definition.addDynFieldMap("evaluatedAttributes")
533
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
534
                .setMandatory(false).setPersistent(true);
535

    
536
            definition.addDynFieldString("defaultFeatureTypeId")
537
                .setMandatory(true).setPersistent(true);
538
        }
539
    }
540

    
541
    public static void registerMetadataDefinition() throws MetadataException {
542
        MetadataManager manager = MetadataLocator.getMetadataManager();
543
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
544
            DynStruct metadataDefinition =
545
                manager.addDefinition(METADATA_DEFINITION_NAME, null);
546
            metadataDefinition.extend(manager
547
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
548
        }
549
    }
550

    
551
    //
552
    // ====================================================================
553
    // Gestion de la seleccion
554
    //
555

    
556
    public void setSelection(DataSet selection) throws DataException {
557
        this.setSelection((FeatureSet) selection);
558
    }
559

    
560
    public DataSet createSelection() throws DataException {
561
        return createFeatureSelection();
562
    }
563

    
564
    public DataSet getSelection() throws DataException {
565
        return this.getFeatureSelection();
566
    }
567

    
568
    public void setSelection(FeatureSet selection) throws DataException {
569
        setSelection(selection, true);
570
    }
571

    
572
    /**
573
     * @see #setSelection(FeatureSet)
574
     * @param undoable
575
     *            if the action must be undoable
576
     */
577
    public void setSelection(FeatureSet selection, boolean undoable)
578
        throws DataException {
579
        if (selection == null) {
580
            if (undoable) {
581
                throw new SelectionNotAllowedException(getName());
582
            }
583

    
584
        } else {
585
            if (selection.equals(this.selection)) {
586
                return;
587
            }
588
            if (!selection.isFromStore(this)) {
589
                throw new SelectionNotAllowedException(getName());
590
            }
591
        }
592

    
593
        if (this.selection != null) {
594
            this.selection.deleteObserver(this);
595
        }
596
        if (selection == null) {
597
            if (this.selection != null) {
598
                this.selection.dispose();
599
            }
600
            this.selection = null;
601
            return;
602
        }
603
        if (selection instanceof FeatureSelection) {
604
            if (undoable && isEditing()) {
605
                commands.selectionSet(this, this.selection,
606
                    (FeatureSelection) selection);
607
            }
608
            if (this.selection != null) {
609
                this.selection.dispose();
610
            }
611
            this.selection = (FeatureSelection) selection;
612
        } else {
613
            if (undoable && isEditing()) {
614
                commands.startComplex("_selectionSet");
615
            }
616
            if (selection instanceof DefaultFeatureSelection) {
617
                DefaultFeatureSelection defSelection =
618
                    (DefaultFeatureSelection) selection;
619
                defSelection.deselectAll(undoable);
620
                defSelection.select(selection, undoable);
621
            } else {
622
                this.selection.deselectAll();
623
                this.selection.select(selection);
624
            }
625
            if (undoable && isEditing()) {
626
                commands.endComplex();
627
            }
628
        }
629
        this.selection.addObserver(this);
630

    
631
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
632
    }
633

    
634
    public FeatureSelection createFeatureSelection() throws DataException {
635
        return this.provider.createFeatureSelection();
636
    }
637

    
638
    public FeatureSelection getFeatureSelection() throws DataException {
639
        if (selection == null) {
640
            this.selection = createFeatureSelection();
641
            this.selection.addObserver(this);
642
        }
643
        return selection;
644
    }
645

    
646
    //
647
    // ====================================================================
648
    // Gestion de notificaciones
649
    //
650

    
651
    public void notifyChange(String notification) {
652
        if (delegateObservable != null) {
653
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
654
        }
655

    
656
    }
657

    
658
    public void notifyChange(String notification, FeatureProvider data) {
659
        try {
660
            notifyChange(notification, createFeature(data));
661
        } catch (DataException ex) {
662
            LOG.error("Error notifying about the notification: " + notification
663
                + ", with the data: " + data, ex);
664
        }
665
    }
666

    
667
    public void notifyChange(String notification, Feature feature) {
668
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
669
            feature));
670
    }
671

    
672
    public void notifyChange(String notification, Command command) {
673
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
674
            command));
675
    }
676

    
677
    public void notifyChange(String notification, EditableFeatureType type) {
678
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
679
            type));
680
    }
681

    
682
    public void notifyChange(FeatureStoreNotification storeNotification) {
683
        delegateObservable.notifyObservers(storeNotification);
684
    }
685

    
686
    public void notifyChange(String notification, Resource resource) {
687
        notifyChange(new DefaultFeatureStoreNotification(this,
688
            DataStoreNotification.RESOURCE_CHANGED));
689
    }
690

    
691
    //
692
    // ====================================================================
693
    // Gestion de bloqueos
694
    //
695

    
696
    public boolean isLocksSupported() {
697
        return this.provider.isLocksSupported();
698
    }
699

    
700
    public FeatureLocks getLocks() throws DataException {
701
        if (!this.provider.isLocksSupported()) {
702
            LOG.warn("Locks not supported");
703
            return null;
704
        }
705
        if (locks == null) {
706
            this.locks = this.provider.createFeatureLocks();
707
        }
708
        return locks;
709
    }
710

    
711
    //
712
    // ====================================================================
713
    // Interface Observable
714
    //
715

    
716
    public void disableNotifications() {
717
        this.delegateObservable.disableNotifications();
718

    
719
    }
720

    
721
    public void enableNotifications() {
722
        this.delegateObservable.enableNotifications();
723
    }
724

    
725
    public void beginComplexNotification() {
726
        this.delegateObservable.beginComplexNotification();
727

    
728
    }
729

    
730
    public void endComplexNotification() {
731
        this.delegateObservable.endComplexNotification();
732

    
733
    }
734

    
735
    public void addObserver(Observer observer) {
736
        if (delegateObservable != null) {
737
            this.delegateObservable.addObserver(observer);
738
        }
739
    }
740

    
741
    public void deleteObserver(Observer observer) {
742
        if (delegateObservable != null) {
743
            this.delegateObservable.deleteObserver(observer);
744
        }
745
    }
746

    
747
    public void deleteObservers() {
748
        this.delegateObservable.deleteObservers();
749

    
750
    }
751

    
752
    //
753
    // ====================================================================
754
    // Interface Observer
755
    //
756
    // Usado para observar:
757
    // - su seleccion
758
    // - sus bloqueos
759
    // - sus recursos
760
    //
761

    
762
    public void update(Observable observable, Object notification) {
763
        if (observable instanceof FeatureSet) {
764
            if (observable == this.selection) {
765
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
766
            } else
767
                if (observable == this.locks) {
768
                    this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
769
                }
770

    
771
        } else
772
            if (observable instanceof FeatureStoreProvider) {
773
                if (observable == this.provider) {
774

    
775
                }
776

    
777
            }
778
    }
779

    
780
    //
781
    // ====================================================================
782
    // Edicion
783
    //
784

    
785
    private void newVersionOfUpdate() {
786
        this.versionOfUpdate++;
787
    }
788

    
789
    private long currentVersionOfUpdate() {
790
        return this.versionOfUpdate;
791
    }
792

    
793
    private void checkInEditingMode() throws NeedEditingModeException {
794
        if (mode != MODE_FULLEDIT) {
795
            throw new NeedEditingModeException(this.getName());
796
        }
797
    }
798

    
799
    private void checkNotInAppendMode() throws IllegalStateException {
800
        if (mode == MODE_APPEND) {
801
                        throw new IllegalStateException("Error: store "
802
                                        + this.getFullName() + " is in append mode");
803
        }
804
    }
805

    
806
    private void checkIsOwnFeature(Feature feature)
807
        throws IllegalFeatureException {
808
        if (((DefaultFeature) feature).getStore() != this) {
809
            throw new IllegalFeatureException(this.getName());
810
        }
811
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
812
        // fixFeatureType((DefaultFeatureType) feature.getType());
813
    }
814

    
815
    private void exitEditingMode() {
816
        if (commands != null) {
817
            commands.clear();
818
            commands = null;
819
        }
820

    
821
        if (featureTypeManager != null) {
822
            featureTypeManager.dispose();
823
            featureTypeManager = null;
824

    
825
        }
826

    
827
        // TODO implementar un dispose para estos dos
828
        featureManager = null;
829
        spatialManager = null;
830

    
831
        featureCount = null;
832

    
833
        mode = MODE_QUERY;
834
        hasStrongChanges = true; // Lo deja a true por si las moscas
835
        hasInserts = true;
836
    }
837

    
838
    synchronized public void edit() throws DataException {
839
        edit(MODE_FULLEDIT);
840
    }
841

    
842
    synchronized public void edit(int mode) throws DataException {
843
        LOG.debug("Starting editing in mode: {}", new Integer(mode));
844
        try {
845
            if (this.mode != MODE_QUERY) {
846
                throw new AlreadyEditingException(this.getName());
847
            }
848
            if (!this.provider.supportsAppendMode()) {
849
                mode = MODE_FULLEDIT;
850
            }
851
            switch (mode) {
852
            case MODE_QUERY:
853
                throw new IllegalStateException(this.getName());
854

    
855
            case MODE_FULLEDIT:
856
                if (!this.transforms.isEmpty()) {
857
                    throw new IllegalStateException(this.getName());
858
                }
859
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
860
                invalidateIndexes();
861
                featureManager =
862
                    new FeatureManager(new MemoryExpansionAdapter());
863
                featureTypeManager =
864
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
865
                spatialManager =
866
                    new SpatialManager(this, provider.getEnvelope());
867

    
868
                commands =
869
                    new DefaultFeatureCommandsStack(this, featureManager,
870
                        spatialManager, featureTypeManager);
871
                this.mode = MODE_FULLEDIT;
872
                hasStrongChanges = false;
873
                hasInserts = false;
874
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
875
                break;
876
            case MODE_APPEND:
877
                if (!this.transforms.isEmpty()) {
878
                    throw new IllegalStateException(this.getName());
879
                }
880
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
881
                invalidateIndexes();
882
                this.provider.beginAppend();
883
                this.mode = MODE_APPEND;
884
                hasInserts = false;
885
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
886
                break;
887
            }
888
        } catch (Exception e) {
889
            throw new StoreEditException(e, this.getName());
890
        }
891
    }
892

    
893
    private void invalidateIndexes() {
894
        setIndexesValidStatus(false);
895
    }
896

    
897
    private void setIndexesValidStatus(boolean valid) {
898
        FeatureIndexes indexes = getIndexes();
899
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
900
            ? Boolean.TRUE : Boolean.FALSE), indexes);
901
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
902
            FeatureIndex index = (FeatureIndex) iterator.next();
903
            if (index instanceof FeatureIndexProviderServices) {
904
                FeatureIndexProviderServices indexServices =
905
                    (FeatureIndexProviderServices) index;
906
                indexServices.setValid(valid);
907
            }
908
        }
909
    }
910

    
911
    private void updateIndexes() throws FeatureIndexException {
912
        FeatureIndexes indexes = getIndexes();
913
        LOG.debug("Refilling indexes: {}", indexes);
914
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
915
            FeatureIndex index = (FeatureIndex) iterator.next();
916
            if (index instanceof FeatureIndexProviderServices) {
917
                FeatureIndexProviderServices indexServices =
918
                    (FeatureIndexProviderServices) index;
919
                indexServices.fill(true, null);
920
            }
921
        }
922
    }
923

    
924
    private void waitForIndexes() {
925
        FeatureIndexes indexes = getIndexes();
926
        LOG.debug("Waiting for indexes to finish filling: {}", indexes);
927
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
928
            FeatureIndex index = (FeatureIndex) iterator.next();
929
            if (index instanceof FeatureIndexProviderServices) {
930
                FeatureIndexProviderServices indexServices =
931
                    (FeatureIndexProviderServices) index;
932
                indexServices.waitForIndex();
933
            }
934
        }
935
    }
936

    
937
    private void disposeIndexes() {
938
        FeatureIndexes indexes = getIndexes();
939
        LOG.debug("Disposing indexes: {}", indexes);
940
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
941
            FeatureIndex index = (FeatureIndex) iterator.next();
942
            if (index instanceof FeatureIndexProviderServices) {
943
                FeatureIndexProviderServices indexServices =
944
                    (FeatureIndexProviderServices) index;
945
                indexServices.dispose();
946
            }
947
        }
948
    }
949

    
950
    public boolean isEditing() {
951
        return mode == MODE_FULLEDIT;
952
    }
953

    
954
    public boolean isAppending() {
955
        return mode == MODE_APPEND;
956
    }
957

    
958
    synchronized public void update(EditableFeatureType type)
959
        throws DataException {
960
        try {
961
            checkInEditingMode();
962
            if (type == null) {
963
                throw new NullFeatureTypeException(getName());
964
            }
965
            // FIXME: Comprobar que es un featureType aceptable.
966
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
967
            newVersionOfUpdate();
968

    
969
            FeatureType oldt = type.getSource().getCopy();
970
            FeatureType newt = type.getCopy();
971
            commands.update(newt, oldt);
972

    
973
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
974
                hasStrongChanges = true;
975
            }
976
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
977
        } catch (Exception e) {
978
            throw new StoreUpdateFeatureTypeException(e, this.getName());
979
        }
980
    }
981

    
982
    public void delete(Feature feature) throws DataException {
983
        this.commands.delete(feature);
984
    }
985

    
986
    synchronized public void doDelete(Feature feature) throws DataException {
987
        try {
988
            checkInEditingMode();
989
            checkIsOwnFeature(feature);
990
            if (feature instanceof EditableFeature) {
991
                throw new StoreDeleteEditableFeatureException(getName());
992
            }
993
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
994

    
995
            //Update the featureManager and the spatialManager
996
            featureManager.delete(feature.getReference());
997
            spatialManager.deleteFeature(feature);
998

    
999
            newVersionOfUpdate();
1000
            hasStrongChanges = true;
1001
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1002
        } catch (Exception e) {
1003
            throw new StoreDeleteFeatureException(e, this.getName());
1004
        }
1005
    }
1006

    
1007
    private static EditableFeature lastChangedFeature = null;
1008

    
1009
    public synchronized void insert(EditableFeature feature)
1010
        throws DataException {
1011
        LOG.debug("In editing mode {}, insert feature: {}", new Integer(mode),
1012
            feature);
1013
        try {
1014
            switch (mode) {
1015
            case MODE_QUERY:
1016
                throw new NeedEditingModeException(this.getName());
1017

    
1018
            case MODE_APPEND:
1019
                checkIsOwnFeature(feature);
1020
                if (feature.getSource() != null) {
1021
                    throw new NoNewFeatureInsertException(this.getName());
1022
                }
1023
                this.featureCount = null;
1024
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1025
                feature.validate(Feature.UPDATE);
1026
                provider.append(((DefaultEditableFeature) feature).getData());
1027
                hasStrongChanges = true;
1028
                hasInserts = true;
1029
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1030
                break;
1031

    
1032
            case MODE_FULLEDIT:
1033
                if (feature.getSource() != null) {
1034
                    throw new NoNewFeatureInsertException(this.getName());
1035
                }
1036
                commands.insert(feature);
1037
            }
1038
        } catch (Exception e) {
1039
            throw new StoreInsertFeatureException(e, this.getName());
1040
        }
1041
    }
1042

    
1043
    synchronized public void doInsert(EditableFeature feature)
1044
        throws DataException {
1045
        checkIsOwnFeature(feature);
1046

    
1047
        waitForIndexes();
1048

    
1049
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1050
        newVersionOfUpdate();
1051
        if ((lastChangedFeature == null)
1052
            || (lastChangedFeature.getSource() != feature.getSource())) {
1053
            lastChangedFeature = feature;
1054
            feature.validate(Feature.UPDATE);
1055
            lastChangedFeature = null;
1056
        }
1057
        //Update the featureManager and the spatialManager
1058
        ((DefaultEditableFeature) feature).setInserted(true);
1059
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1060

    
1061

    
1062
        featureManager.add(newFeature);
1063
        spatialManager.insertFeature(newFeature);
1064

    
1065
        hasStrongChanges = true;
1066
        hasInserts = true;
1067
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1068
    }
1069

    
1070
    public void update(EditableFeature feature)
1071
    throws DataException {
1072
        if ((feature).getSource() == null) {
1073
            insert(feature);
1074
            return;
1075
        }
1076
        commands.update(feature, feature.getSource());
1077
    }
1078

    
1079
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1080
        throws DataException {
1081
        try {
1082
            checkInEditingMode();
1083
            checkIsOwnFeature(feature);
1084
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1085
            newVersionOfUpdate();
1086
            if ((lastChangedFeature == null)
1087
                || (lastChangedFeature.getSource() != feature.getSource())) {
1088
                lastChangedFeature = feature;
1089
                feature.validate(Feature.UPDATE);
1090
                lastChangedFeature = null;
1091
            }
1092

    
1093
            //Update the featureManager and the spatialManager
1094
            Feature newf = feature.getNotEditableCopy();
1095
            featureManager.update(newf, oldFeature);
1096
            spatialManager.updateFeature(newf, oldFeature);
1097

    
1098
            hasStrongChanges = true;
1099
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1100
        } catch (Exception e) {
1101
            throw new StoreUpdateFeatureException(e, this.getName());
1102
        }
1103
    }
1104

    
1105
    synchronized public void redo() throws RedoException {
1106
        Command redo = commands.getNextRedoCommand();
1107
        try {
1108
            checkInEditingMode();
1109
        } catch (NeedEditingModeException ex) {
1110
            throw new RedoException(redo, ex);
1111
        }
1112
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1113
        newVersionOfUpdate();
1114
        commands.redo();
1115
        hasStrongChanges = true;
1116
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1117
    }
1118

    
1119
    synchronized public void undo() throws UndoException {
1120
        Command undo = commands.getNextUndoCommand();
1121
        try {
1122
            checkInEditingMode();
1123
        } catch (NeedEditingModeException ex) {
1124
            throw new UndoException(undo, ex);
1125
        }
1126
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1127
        newVersionOfUpdate();
1128
        commands.undo();
1129
        hasStrongChanges = true;
1130
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1131
    }
1132

    
1133
    public List getRedoInfos() {
1134
        if (isEditing() && (commands != null)) {
1135
            return commands.getRedoInfos();
1136
        } else {
1137
            return null;
1138
        }
1139
    }
1140

    
1141
    public List getUndoInfos() {
1142
        if (isEditing() && (commands != null)) {
1143
            return commands.getUndoInfos();
1144
        } else {
1145
            return null;
1146
        }
1147
    }
1148

    
1149
    public synchronized FeatureCommandsStack getCommandsStack()
1150
        throws DataException {
1151
        checkInEditingMode();
1152
        return commands;
1153
    }
1154

    
1155
    synchronized public void cancelEditing() throws DataException {
1156
        spatialManager.cancelModifies();
1157
        try {
1158
            checkInEditingMode();
1159

    
1160
            boolean clearSelection = this.hasStrongChanges;
1161
            if (this.selection instanceof FeatureReferenceSelection) {
1162
                clearSelection = this.hasInserts;
1163
            }
1164
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1165
            exitEditingMode();
1166
            if (clearSelection) {
1167
                ((FeatureSelection) this.getSelection()).deselectAll();
1168
            }
1169
            updateIndexes();
1170
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1171
        } catch (Exception e) {
1172
            throw new StoreCancelEditingException(e, this.getName());
1173
        }
1174
    }
1175

    
1176
    synchronized public void finishEditing() throws DataException {
1177
        LOG.debug("finish editing of mode: {}", new Integer(mode));
1178
        try {
1179

    
1180
            /*
1181
             * Selection needs to be cleared when editing stops
1182
             * to prevent conflicts with selection remaining from
1183
             * editing mode.
1184
             */
1185
            ((FeatureSelection) this.getSelection()).deselectAll();
1186

    
1187
            switch (mode) {
1188
            case MODE_QUERY:
1189
                throw new NeedEditingModeException(this.getName());
1190

    
1191
            case MODE_APPEND:
1192
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1193
                provider.endAppend();
1194
                exitEditingMode();
1195
                updateIndexes();
1196
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1197
                break;
1198

    
1199
            case MODE_FULLEDIT:
1200
                if (hasStrongChanges && !this.allowWrite()) {
1201
                    throw new WriteNotAllowedException(getName());
1202
                }
1203
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1204
                if (hasStrongChanges) {
1205
                    validateFeatures(Feature.FINISH_EDITING);
1206

    
1207
                    /*
1208
                     * This will throw a PerformEditingExceptionif the provider
1209
                     * does not accept the changes (for example, an invalid field name)
1210
                     */
1211
                    provider.performChanges(featureManager.getDeleted(),
1212
                        featureManager.getInserted(),
1213
                        featureManager.getUpdated(),
1214
                        featureTypeManager.getFeatureTypesChanged());
1215
                }
1216
                exitEditingMode();
1217
                updateIndexes();
1218
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1219
                break;
1220
            }
1221
        } catch (PerformEditingException pee) {
1222
            throw new WriteException(provider.getSourceId().toString(), pee);
1223
        } catch (Exception e) {
1224
            throw new FinishEditingException(e);
1225
        }
1226
    }
1227

    
1228
    /**
1229
     * Save changes in the provider without leaving the edit mode.
1230
     * Do not call observers to communicate a change of ediding mode.
1231
     * The operation's history is eliminated to prevent inconsistencies
1232
     * in the data.
1233
     *
1234
     * @throws DataException
1235
     */
1236
    synchronized public void commitChanges() throws DataException {
1237
      LOG.debug("commitChanges of mode: {}", new Integer(mode));
1238
      if( !canCommitChanges() ) {
1239
              throw new WriteNotAllowedException(getName());
1240
      }
1241
      try {
1242
        switch (mode) {
1243
        case MODE_QUERY:
1244
          throw new NeedEditingModeException(this.getName());
1245

    
1246
        case MODE_APPEND:
1247
          this.provider.endAppend();
1248
          exitEditingMode();
1249
          invalidateIndexes();
1250
          this.provider.beginAppend();
1251
          hasInserts = false;
1252
          break;
1253

    
1254
        case MODE_FULLEDIT:
1255
          if (hasStrongChanges && !this.allowWrite()) {
1256
            throw new WriteNotAllowedException(getName());
1257
          }
1258
          if (hasStrongChanges) {
1259
            validateFeatures(Feature.FINISH_EDITING);
1260
            provider.performChanges(featureManager.getDeleted(),
1261
              featureManager.getInserted(),
1262
              featureManager.getUpdated(),
1263
              featureTypeManager.getFeatureTypesChanged());
1264
          }
1265
          invalidateIndexes();
1266
          featureManager =
1267
            new FeatureManager(new MemoryExpansionAdapter());
1268
          featureTypeManager =
1269
            new FeatureTypeManager(this, new MemoryExpansionAdapter());
1270
          spatialManager =
1271
            new SpatialManager(this, provider.getEnvelope());
1272

    
1273
          commands =
1274
            new DefaultFeatureCommandsStack(this, featureManager,
1275
              spatialManager, featureTypeManager);
1276
          featureCount = null;
1277
          hasStrongChanges = false;
1278
          hasInserts = false;
1279
          break;
1280
        }
1281
      } catch (Exception e) {
1282
        throw new FinishEditingException(e);
1283
      }
1284
    }
1285

    
1286
    synchronized public boolean canCommitChanges() throws DataException {
1287
        if ( !this.allowWrite()) {
1288
                return false;
1289
        }
1290
            switch (mode) {
1291
            default:
1292
        case MODE_QUERY:
1293
                return false;
1294

    
1295
        case MODE_APPEND:
1296
                return true;
1297

    
1298
        case MODE_FULLEDIT:
1299
            List types = this.getFeatureTypes();
1300
            for( int i=0; i<types.size(); i++ ) {
1301
                    Object type = types.get(i);
1302
                    if( type instanceof DefaultEditableFeatureType ) {
1303
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1304
                                    return false;
1305
                            }
1306
                    }
1307
            }
1308
            return true;
1309
            }
1310
    }
1311

    
1312
    public void beginEditingGroup(String description)
1313
        throws NeedEditingModeException {
1314
        checkInEditingMode();
1315
        commands.startComplex(description);
1316
    }
1317

    
1318
    public void endEditingGroup() throws NeedEditingModeException {
1319
        checkInEditingMode();
1320
        commands.endComplex();
1321
    }
1322

    
1323
    public boolean isAppendModeSupported() {
1324
        return this.provider.supportsAppendMode();
1325
    }
1326

    
1327
    public void export(DataServerExplorer explorer, String provider,
1328
        NewFeatureStoreParameters params) throws DataException {
1329

    
1330
        if (this.getFeatureTypes().size() != 1) {
1331
            throw new NotYetImplemented(
1332
                "export whith more than one type not yet implemented");
1333
        }
1334
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1335
        FeatureStore target = null;
1336
        FeatureSet features = null;
1337
        DisposableIterator iterator = null;
1338
        try {
1339
            FeatureType type = this.getDefaultFeatureType();
1340
            if ((params.getDefaultFeatureType() == null)
1341
                || (params.getDefaultFeatureType().size() == 0)) {
1342
                params.setDefaultFeatureType(type.getEditable());
1343

    
1344
            }
1345
            explorer.add(provider, params, true);
1346

    
1347
            DataManager manager = DALLocator.getDataManager();
1348
            target = (FeatureStore) manager.openStore(provider, params);
1349
            FeatureType targetType = target.getDefaultFeatureType();
1350

    
1351
            target.edit(MODE_APPEND);
1352
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1353
            if (featureSelection.getSize() > 0) {
1354
                features = this.getFeatureSelection();
1355
            } else {
1356
                if ((pk != null) && (pk.length > 0)) {
1357
                    FeatureQuery query = createFeatureQuery();
1358
                    for (int i = 0; i < pk.length; i++) {
1359
                        query.getOrder().add(pk[i].getName(), true);
1360
                    }
1361
                    features = this.getFeatureSet(query);
1362
                } else {
1363
                    features = this.getFeatureSet();
1364
                }
1365
            }
1366
            iterator = features.fastIterator();
1367
            while (iterator.hasNext()) {
1368
                DefaultFeature feature = (DefaultFeature) iterator.next();
1369
                target.insert(target.createNewFeature(targetType, feature));
1370
            }
1371
            target.finishEditing();
1372
            target.dispose();
1373
        } catch (Exception e) {
1374
            throw new DataExportException(e, params.toString());
1375
        } finally {
1376
            dispose(iterator);
1377
            dispose(features);
1378
            dispose(target);
1379
        }
1380
    }
1381

    
1382
    //
1383
    // ====================================================================
1384
    // Obtencion de datos
1385
    // getDataCollection, getFeatureCollection
1386
    //
1387

    
1388
    public DataSet getDataSet() throws DataException {
1389
        checkNotInAppendMode();
1390
        FeatureQuery query =
1391
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1392
        return new DefaultFeatureSet(this, query);
1393
    }
1394

    
1395
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1396
        checkNotInAppendMode();
1397
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1398
    }
1399

    
1400
    public void getDataSet(Observer observer) throws DataException {
1401
        checkNotInAppendMode();
1402
        this.getFeatureSet(null, observer);
1403
    }
1404

    
1405
    public void getDataSet(DataQuery dataQuery, Observer observer)
1406
        throws DataException {
1407
        checkNotInAppendMode();
1408
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1409
    }
1410

    
1411
    public FeatureSet getFeatureSet() throws DataException {
1412
        checkNotInAppendMode();
1413
        FeatureQuery query =
1414
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1415
        return new DefaultFeatureSet(this, query);
1416
    }
1417

    
1418
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1419
        throws DataException {
1420
        checkNotInAppendMode();
1421
        return new DefaultFeatureSet(this, featureQuery);
1422
    }
1423

    
1424
    public void accept(Visitor visitor) throws BaseException {
1425
        FeatureSet set = getFeatureSet();
1426
        try {
1427
            set.accept(visitor);
1428
        } finally {
1429
            set.dispose();
1430
        }
1431
    }
1432

    
1433
    public void accept(Visitor visitor, DataQuery dataQuery)
1434
        throws BaseException {
1435
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1436
        try {
1437
            set.accept(visitor);
1438
        } finally {
1439
            set.dispose();
1440
        }
1441
    }
1442

    
1443
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1444
        throws DataException {
1445
        DefaultFeatureType fType =
1446
            (DefaultFeatureType) this.getFeatureType(featureQuery
1447
                .getFeatureTypeId());
1448
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1449
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1450
        }
1451
        return fType;
1452
    }
1453

    
1454
    public void getFeatureSet(Observer observer) throws DataException {
1455
        checkNotInAppendMode();
1456
        this.getFeatureSet(null, observer);
1457
    }
1458

    
1459
    public void getFeatureSet(FeatureQuery query, Observer observer)
1460
        throws DataException {
1461
        class LoadInBackGround implements Runnable {
1462

    
1463
            private FeatureStore store;
1464
            private FeatureQuery query;
1465
            private Observer observer;
1466

    
1467
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1468
                Observer observer) {
1469
                this.store = store;
1470
                this.query = query;
1471
                this.observer = observer;
1472
            }
1473

    
1474
            void notify(FeatureStoreNotification theNotification) {
1475
                observer.update(store, theNotification);
1476
                return;
1477
            }
1478

    
1479
            public void run() {
1480
                FeatureSet set = null;
1481
                try {
1482
                    set = store.getFeatureSet(query);
1483
                    notify(new DefaultFeatureStoreNotification(store,
1484
                        FeatureStoreNotification.LOAD_FINISHED, set));
1485
                } catch (Exception e) {
1486
                    notify(new DefaultFeatureStoreNotification(store,
1487
                        FeatureStoreNotification.LOAD_FINISHED, e));
1488
                } finally {
1489
                    dispose(set);
1490
                }
1491
            }
1492
        }
1493

    
1494
        checkNotInAppendMode();
1495
        if (query == null) {
1496
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1497
        }
1498
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1499
        Thread thread = new Thread(task, "Load Feature Set in background");
1500
        thread.start();
1501
    }
1502

    
1503
    public Feature getFeatureByReference(FeatureReference reference)
1504
        throws DataException {
1505
        checkNotInAppendMode();
1506
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1507
        FeatureType featureType;
1508
        if (ref.getFeatureTypeId() == null) {
1509
            featureType = this.getDefaultFeatureType();
1510
        } else {
1511
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1512
        }
1513
        return this.getFeatureByReference(reference, featureType);
1514
    }
1515

    
1516
    public Feature getFeatureByReference(FeatureReference reference,
1517
        FeatureType featureType) throws DataException {
1518
        checkNotInAppendMode();
1519
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1520
        if (!this.transforms.isEmpty()) {
1521

    
1522
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1523

    
1524
        }
1525
        // TODO comprobar que el id es de este store
1526

    
1527
        if (this.mode == MODE_FULLEDIT) {
1528
            Feature f = featureManager.get(reference, this, featureType);
1529
            if (f != null) {
1530
                return f;
1531
            }
1532
        }
1533

    
1534

    
1535
        DefaultFeature feature =
1536
            new DefaultFeature(this,
1537
                this.provider.getFeatureProviderByReference(
1538
                    (FeatureReferenceProviderServices) reference, featureType));
1539

    
1540
        if (!this.transforms.isEmpty()) {
1541
            return this.transforms.applyTransform(feature, featureType);
1542
        }
1543
        return feature;
1544
    }
1545

    
1546
    //
1547
    // ====================================================================
1548
    // Gestion de features
1549
    //
1550

    
1551
    private FeatureType fixFeatureType(DefaultFeatureType type)
1552
        throws DataException {
1553
        FeatureType original = this.getDefaultFeatureType();
1554

    
1555
        if ((type == null) || type.equals(original)) {
1556
            return original;
1557
        } else {
1558
            if (!type.isSubtypeOf(original)) {
1559
                Iterator iter = this.getFeatureTypes().iterator();
1560
                FeatureType tmpType;
1561
                boolean found = false;
1562
                while (iter.hasNext()) {
1563
                    tmpType = (FeatureType) iter.next();
1564
                    if (type.equals(tmpType)) {
1565
                        return type;
1566

    
1567
                    } else
1568
                        if (type.isSubtypeOf(tmpType)) {
1569
                            found = true;
1570
                            original = tmpType;
1571
                            break;
1572
                        }
1573

    
1574
                }
1575
                if (!found) {
1576
                    throw new IllegalFeatureTypeException(getName());
1577
                }
1578
            }
1579
        }
1580

    
1581
        // Checks that type has all fields of pk
1582
        // else add the missing attributes at the end.
1583
        if (!original.hasOID()) {
1584
            // Gets original pk attributes
1585
            DefaultEditableFeatureType edOriginal =
1586
                (DefaultEditableFeatureType) original.getEditable();
1587
            FeatureAttributeDescriptor orgAttr;
1588
            Iterator edOriginalIter = edOriginal.iterator();
1589
            while (edOriginalIter.hasNext()) {
1590
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1591
                if (!orgAttr.isPrimaryKey()) {
1592
                    edOriginalIter.remove();
1593
                }
1594
            }
1595

    
1596
            // Checks if all pk attributes are in type
1597
            Iterator typeIterator;
1598
            edOriginalIter = edOriginal.iterator();
1599
            FeatureAttributeDescriptor attr;
1600
            while (edOriginalIter.hasNext()) {
1601
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1602
                typeIterator = type.iterator();
1603
                while (typeIterator.hasNext()) {
1604
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1605
                    if (attr.getName().equals(orgAttr.getName())) {
1606
                        edOriginalIter.remove();
1607
                        break;
1608
                    }
1609
                }
1610
            }
1611

    
1612
            // add missing pk attributes if any
1613
            if (edOriginal.size() > 0) {
1614
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1615
                DefaultEditableFeatureType edType =
1616
                    (DefaultEditableFeatureType) original.getEditable();
1617
                edType.clear();
1618
                edType.addAll(type);
1619
                edType.addAll(edOriginal);
1620
                if (!isEditable) {
1621
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1622
                }
1623
            }
1624

    
1625
        }
1626

    
1627
        return type;
1628
    }
1629

    
1630
    public void validateFeatures(int mode) throws DataException {
1631
        FeatureSet collection = null;
1632
        DisposableIterator iter = null;
1633
        try {
1634
            checkNotInAppendMode();
1635
            collection = this.getFeatureSet();
1636
            iter = collection.fastIterator();
1637
            long previousVersionOfUpdate = currentVersionOfUpdate();
1638
            while (iter.hasNext()) {
1639
                ((DefaultFeature) iter.next()).validate(mode);
1640
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1641
                    throw new ConcurrentDataModificationException(getName());
1642
                }
1643
            }
1644
        } catch (Exception e) {
1645
            throw new ValidateFeaturesException(e, getName());
1646
        } finally {
1647
            dispose(iter);
1648
            dispose(collection);
1649
        }
1650
    }
1651

    
1652
    public FeatureType getDefaultFeatureType() throws DataException {
1653
        try {
1654

    
1655
            if (isEditing()) {
1656
                FeatureType auxFeatureType =
1657
                    featureTypeManager.getType(defaultFeatureType.getId());
1658
                if (auxFeatureType != null) {
1659
                    return avoidEditable(auxFeatureType);
1660
                }
1661
            }
1662
            FeatureType type = this.transforms.getDefaultFeatureType();
1663
            if (type != null) {
1664
                return avoidEditable(type);
1665
            }
1666

    
1667
            return avoidEditable(defaultFeatureType);
1668

    
1669
        } catch (Exception e) {
1670
            throw new GetFeatureTypeException(e, getName());
1671
        }
1672
    }
1673

    
1674
    private FeatureType avoidEditable(FeatureType ft) {
1675
        if (ft instanceof EditableFeatureType) {
1676
            return ((EditableFeatureType) ft).getNotEditableCopy();
1677
        } else {
1678
            return ft;
1679
        }
1680
    }
1681

    
1682
    public FeatureType getFeatureType(String featureTypeId)
1683
        throws DataException {
1684
        if (featureTypeId == null) {
1685
            return this.getDefaultFeatureType();
1686
        }
1687
        try {
1688
            if (isEditing()) {
1689
                FeatureType auxFeatureType =
1690
                    featureTypeManager.getType(featureTypeId);
1691
                if (auxFeatureType != null) {
1692
                    return auxFeatureType;
1693
                }
1694
            }
1695
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1696
            if (type != null) {
1697
                return type;
1698
            }
1699
            Iterator iter = this.featureTypes.iterator();
1700
            while (iter.hasNext()) {
1701
                type = (FeatureType) iter.next();
1702
                if (type.getId().equals(featureTypeId)) {
1703
                    return type;
1704
                }
1705
            }
1706
            return null;
1707
        } catch (Exception e) {
1708
            throw new GetFeatureTypeException(e, getName());
1709
        }
1710
    }
1711

    
1712
    public FeatureType getProviderDefaultFeatureType() {
1713
        return defaultFeatureType;
1714
    }
1715

    
1716
    public List getFeatureTypes() throws DataException {
1717
        try {
1718
            List types;
1719
            if (isEditing()) {
1720
                types = new ArrayList();
1721
                Iterator it = featureTypes.iterator();
1722
                while (it.hasNext()) {
1723
                    FeatureType type = (FeatureType) it.next();
1724
                    FeatureType typeaux =
1725
                        featureTypeManager.getType(type.getId());
1726
                    if (typeaux != null) {
1727
                        types.add(typeaux);
1728
                    } else {
1729
                        types.add(type);
1730
                    }
1731
                }
1732
                it = featureTypeManager.newsIterator();
1733
                while (it.hasNext()) {
1734
                    FeatureType type = (FeatureType) it.next();
1735
                    types.add(type);
1736
                }
1737
            } else {
1738
                types = this.transforms.getFeatureTypes();
1739
                if (types == null) {
1740
                    types = featureTypes;
1741
                }
1742
            }
1743
            return Collections.unmodifiableList(types);
1744
        } catch (Exception e) {
1745
            throw new GetFeatureTypeException(e, getName());
1746
        }
1747
    }
1748

    
1749
    public List getProviderFeatureTypes() throws DataException {
1750
        return Collections.unmodifiableList(this.featureTypes);
1751
    }
1752

    
1753
    public Feature createFeature(FeatureProvider data) throws DataException {
1754
        DefaultFeature feature = new DefaultFeature(this, data);
1755
        return feature;
1756
    }
1757

    
1758
    public Feature createFeature(FeatureProvider data, FeatureType type)
1759
        throws DataException {
1760
        // FIXME: falta por implementar
1761
        // Comprobar si es un subtipo del feature de data
1762
        // y construir un feature usando el subtipo.
1763
        // Probablemente requiera generar una copia del data.
1764
        throw new NotYetImplemented();
1765
    }
1766

    
1767
    public EditableFeature createNewFeature(FeatureType type,
1768
        Feature defaultValues) throws DataException {
1769
        try {
1770
            FeatureProvider data = createNewFeatureProvider(type);
1771
            DefaultEditableFeature feature =
1772
                new DefaultEditableFeature(this, data);
1773
            feature.initializeValues(defaultValues);
1774
            data.setNew(true);
1775

    
1776
            return feature;
1777
        } catch (Exception e) {
1778
            throw new CreateFeatureException(e, getName());
1779
        }
1780
    }
1781

    
1782
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1783
        throws DataException {
1784
        type = this.fixFeatureType((DefaultFeatureType) type);
1785
        FeatureProvider data = this.provider.createFeatureProvider(type);
1786
        data.setNew(true);
1787
        if (type.hasOID() && (data.getOID() == null)) {
1788
            data.setOID(this.provider.createNewOID());
1789
        } else {
1790
            data.setOID(this.getTemporalOID());
1791
        }
1792
        return data;
1793

    
1794
    }
1795

    
1796
    public EditableFeature createNewFeature(FeatureType type,
1797
        boolean defaultValues) throws DataException {
1798
        try {
1799
            FeatureProvider data = createNewFeatureProvider(type);
1800
            DefaultEditableFeature feature =
1801
                new DefaultEditableFeature(this, data);
1802
            if (defaultValues) {
1803
                feature.initializeValues();
1804
            }
1805
            return feature;
1806
        } catch (Exception e) {
1807
            throw new CreateFeatureException(e, getName());
1808
        }
1809
    }
1810

    
1811
    public EditableFeature createNewFeature(boolean defaultValues)
1812
        throws DataException {
1813
        return this.createNewFeature(this.getDefaultFeatureType(),
1814
            defaultValues);
1815
    }
1816

    
1817
    public EditableFeature createNewFeature() throws DataException {
1818
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1819
    }
1820

    
1821
    public EditableFeatureType createFeatureType() {
1822
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1823
        return ftype;
1824
    }
1825

    
1826
    public EditableFeatureType createFeatureType(String id) {
1827
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1828
        return ftype;
1829
    }
1830

    
1831
    //
1832
    // ====================================================================
1833
    // Index related methods
1834
    //
1835

    
1836
    public FeatureIndexes getIndexes() {
1837
        return this.indexes;
1838
    }
1839

    
1840
    public FeatureIndex createIndex(FeatureType featureType,
1841
        String attributeName, String indexName) throws DataException {
1842
        return createIndex(null, featureType, attributeName, indexName);
1843
    }
1844

    
1845
    public FeatureIndex createIndex(String indexTypeName,
1846
        FeatureType featureType, String attributeName, String indexName)
1847
        throws DataException {
1848

    
1849
        return createIndex(indexTypeName, featureType, attributeName,
1850
            indexName, false, null);
1851
    }
1852

    
1853
    public FeatureIndex createIndex(FeatureType featureType,
1854
        String attributeName, String indexName, Observer observer)
1855
        throws DataException {
1856
        return createIndex(null, featureType, attributeName, indexName,
1857
            observer);
1858
    }
1859

    
1860
    public FeatureIndex createIndex(String indexTypeName,
1861
        FeatureType featureType, String attributeName, String indexName,
1862
        final Observer observer) throws DataException {
1863

    
1864
        return createIndex(indexTypeName, featureType, attributeName,
1865
            indexName, true, observer);
1866
    }
1867

    
1868
    private FeatureIndex createIndex(String indexTypeName,
1869
        FeatureType featureType, String attributeName, String indexName,
1870
        boolean background, final Observer observer) throws DataException {
1871

    
1872
        checkNotInAppendMode();
1873
        FeatureIndexProviderServices index = null;
1874
        index =
1875
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1876
                featureType, indexName,
1877
                featureType.getAttributeDescriptor(attributeName));
1878

    
1879
        try {
1880
            index.fill(background, observer);
1881
        } catch (FeatureIndexException e) {
1882
            throw new InitializeException(index.getName(), e);
1883
        }
1884

    
1885
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1886
        return index;
1887
    }
1888

    
1889
    //
1890
    // ====================================================================
1891
    // Transforms related methods
1892
    //
1893

    
1894
    public FeatureStoreTransforms getTransforms() {
1895
        return this.transforms;
1896
    }
1897

    
1898
    public FeatureQuery createFeatureQuery() {
1899
        return new DefaultFeatureQuery();
1900
    }
1901

    
1902
    public DataQuery createQuery() {
1903
        return createFeatureQuery();
1904
    }
1905

    
1906
    //
1907
    // ====================================================================
1908
    // UndoRedo related methods
1909
    //
1910

    
1911
    public boolean canRedo() {
1912
        return commands.canRedo();
1913
    }
1914

    
1915
    public boolean canUndo() {
1916
        return commands.canUndo();
1917
    }
1918

    
1919
    public void redo(int num) throws RedoException {
1920
        for (int i = 0; i < num; i++) {
1921
            redo();
1922
        }
1923
    }
1924

    
1925
    public void undo(int num) throws UndoException {
1926
        for (int i = 0; i < num; i++) {
1927
            undo();
1928
        }
1929
    }
1930

    
1931
    //
1932
    // ====================================================================
1933
    // Metadata related methods
1934
    //
1935

    
1936
    public Object getMetadataID() {
1937
        return this.provider.getSourceId();
1938
    }
1939

    
1940
    public void delegate(DynObject dynObject) {
1941
        this.metadata.delegate(dynObject);
1942
    }
1943

    
1944
    public DynClass getDynClass() {
1945
        return this.metadata.getDynClass();
1946
    }
1947

    
1948
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1949
                if( this.transforms.hasDynValue(name) ) {
1950
                        return this.transforms.getDynValue(name);
1951
                }
1952
                if (this.metadata.hasDynValue(name)) {
1953
                        return this.metadata.getDynValue(name);
1954
                }
1955
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1956
                        return this.provider.getProviderName();
1957
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1958
                        return this.provider.getSourceId();
1959
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1960
                        try {
1961
                                return this.getDefaultFeatureType();
1962
                        } catch (DataException e) {
1963
                                return null;
1964
                        }
1965
                }
1966
                return this.metadata.getDynValue(name);
1967
        }
1968

    
1969
    public boolean hasDynValue(String name) {
1970
                if( this.transforms.hasDynValue(name) ) {
1971
                        return true;
1972
                }
1973
        return this.metadata.hasDynValue(name);
1974
    }
1975

    
1976
    public void implement(DynClass dynClass) {
1977
        this.metadata.implement(dynClass);
1978
    }
1979

    
1980
    public Object invokeDynMethod(String name, DynObject context)
1981
        throws DynMethodException {
1982
        return this.metadata.invokeDynMethod(this, name, context);
1983
    }
1984

    
1985
    public Object invokeDynMethod(int code, DynObject context)
1986
        throws DynMethodException {
1987
        return this.metadata.invokeDynMethod(this, code, context);
1988
    }
1989

    
1990
    public void setDynValue(String name, Object value)
1991
        throws DynFieldNotFoundException {
1992
                if( this.transforms.hasDynValue(name) ) {
1993
                        this.transforms.setDynValue(name, value);
1994
                        return;
1995
                }
1996
        this.metadata.setDynValue(name, value);
1997

    
1998
    }
1999

    
2000
    /*
2001
     * (non-Javadoc)
2002
     *
2003
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2004
     */
2005
    public Set getMetadataChildren() {
2006
        return this.metadataChildren;
2007
    }
2008

    
2009
    /*
2010
     * (non-Javadoc)
2011
     *
2012
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2013
     */
2014
    public String getMetadataName() {
2015
        return this.provider.getProviderName();
2016
    }
2017

    
2018
    public FeatureTypeManager getFeatureTypeManager() {
2019
        return this.featureTypeManager;
2020
    }
2021

    
2022
    public long getFeatureCount() throws DataException {
2023
        if (featureCount == null) {
2024
            featureCount = new Long(this.provider.getFeatureCount());
2025
        }
2026
        if (this.isEditing() && !this.isAppending()) {
2027
            return featureCount.longValue()
2028
                - this.featureManager.getDeltaSize();
2029
        }
2030
        return featureCount.longValue();
2031
    }
2032

    
2033
    private Long getTemporalOID() {
2034
        return new Long(this.temporalOid++);
2035
    }
2036

    
2037
    public FeatureType getProviderFeatureType(String featureTypeId) {
2038
        if (featureTypeId == null) {
2039
            return this.defaultFeatureType;
2040
        }
2041
        FeatureType type;
2042
        Iterator iter = this.featureTypes.iterator();
2043
        while (iter.hasNext()) {
2044
            type = (FeatureType) iter.next();
2045
            if (type.getId().equals(featureTypeId)) {
2046
                return type;
2047
            }
2048
        }
2049
        return null;
2050
    }
2051

    
2052
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2053
        return ((DefaultFeature) feature).getData();
2054
    }
2055

    
2056
    public DataStore getStore() {
2057
        return this;
2058
    }
2059

    
2060
    public FeatureStore getFeatureStore() {
2061
        return this;
2062
    }
2063

    
2064
    public void createCache(String name, DynObject parameters)
2065
        throws DataException {
2066
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2067
        if (cache == null) {
2068
            throw new CreateException("FeaureCacheProvider", null);
2069
        }
2070
        cache.apply(this, provider);
2071
        provider = cache;
2072

    
2073
        featureCount = null;
2074
    }
2075

    
2076
    public FeatureCache getCache() {
2077
        return cache;
2078
    }
2079

    
2080
    public void clear() {
2081
        if (metadata != null) {
2082
            metadata.clear();
2083
        }
2084
    }
2085

    
2086
    public String getName() {
2087
        return this.provider.getName();
2088
    }
2089

    
2090
    public String getFullName() {
2091
        return this.provider.getFullName();
2092
    }
2093

    
2094
    public String getProviderName() {
2095
        return this.provider.getProviderName();
2096
    }
2097

    
2098
    public boolean isKnownEnvelope() {
2099
        return this.provider.isKnownEnvelope();
2100
    }
2101

    
2102
    public boolean hasRetrievedFeaturesLimit() {
2103
        return this.provider.hasRetrievedFeaturesLimit();
2104
    }
2105

    
2106
    public int getRetrievedFeaturesLimit() {
2107
        return this.provider.getRetrievedFeaturesLimit();
2108
    }
2109

    
2110
    public Interval getInterval() {
2111
        return this.provider.getInterval();
2112
    }
2113

    
2114
    public Collection getTimes() {
2115
        return this.provider.getTimes();
2116
    }
2117

    
2118
    public Collection getTimes(Interval interval) {
2119
        return this.provider.getTimes(interval);
2120
    }
2121

    
2122
    /* (non-Javadoc)
2123
     * @see java.lang.Object#clone()
2124
     */
2125
    public Object clone() throws CloneNotSupportedException {
2126

    
2127
        DataStoreParameters dsp = getParameters();
2128

    
2129
        DefaultFeatureStore cloned_store = null;
2130

    
2131
        try {
2132
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2133
                openStore(this.getProviderName(), dsp);
2134
            if (transforms != null) {
2135
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2136
                cloned_store.transforms.setStoreForClone(cloned_store);
2137
            }
2138
        } catch (Exception e) {
2139
            throw new CloneException(e);
2140
        }
2141
        return cloned_store;
2142

    
2143
    }
2144

    
2145
    public Feature getFeature(DynObject dynobject) {
2146
        if (dynobject instanceof DynObjectFeatureFacade){
2147
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2148
            return f;
2149
        }
2150
        return null;
2151
    }
2152
}