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

History | View | Annotate | Download (72.2 KB)

1
/* 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
package org.gvsig.fmap.dal.feature.impl;
29

    
30
import java.util.ArrayList;
31
import java.util.Collection;
32
import java.util.Collections;
33
import java.util.HashMap;
34
import java.util.HashSet;
35
import java.util.Iterator;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Map.Entry;
39
import java.util.Set;
40

    
41
import org.cresques.cts.IProjection;
42
import org.slf4j.Logger;
43
import org.slf4j.LoggerFactory;
44

    
45
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.CloneException;
54
import org.gvsig.fmap.dal.exception.CloseException;
55
import org.gvsig.fmap.dal.exception.CreateException;
56
import org.gvsig.fmap.dal.exception.DataException;
57
import org.gvsig.fmap.dal.exception.InitializeException;
58
import org.gvsig.fmap.dal.exception.OpenException;
59
import org.gvsig.fmap.dal.exception.ReadException;
60
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
61
import org.gvsig.fmap.dal.feature.EditableFeature;
62
import org.gvsig.fmap.dal.feature.EditableFeatureType;
63
import org.gvsig.fmap.dal.feature.Feature;
64
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
65
import org.gvsig.fmap.dal.feature.FeatureCache;
66
import org.gvsig.fmap.dal.feature.FeatureIndex;
67
import org.gvsig.fmap.dal.feature.FeatureIndexes;
68
import org.gvsig.fmap.dal.feature.FeatureLocks;
69
import org.gvsig.fmap.dal.feature.FeatureQuery;
70
import org.gvsig.fmap.dal.feature.FeatureReference;
71
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
72
import org.gvsig.fmap.dal.feature.FeatureSelection;
73
import org.gvsig.fmap.dal.feature.FeatureSet;
74
import org.gvsig.fmap.dal.feature.FeatureStore;
75
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
76
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
77
import org.gvsig.fmap.dal.feature.FeatureType;
78
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
79
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
80
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
81
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
82
import org.gvsig.fmap.dal.feature.exception.DataExportException;
83
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
84
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
85
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
86
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
87
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
88
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
89
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
90
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
91
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindDefaultFeatureTypeException;
92
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindFeatureTypeException;
93
import org.gvsig.fmap.dal.feature.exception.PersistenceStoreAlreadyLoadedException;
94
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
95
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
96
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
97
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
98
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
99
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
100
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
101
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
102
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
103
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
104
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
105
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
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.observer.Observable;
137
import org.gvsig.tools.observer.Observer;
138
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
139
import org.gvsig.tools.persistence.PersistenceManager;
140
import org.gvsig.tools.persistence.Persistent;
141
import org.gvsig.tools.persistence.PersistentState;
142
import org.gvsig.tools.persistence.exception.PersistenceException;
143
import org.gvsig.tools.undo.RedoException;
144
import org.gvsig.tools.undo.UndoException;
145
import org.gvsig.tools.undo.command.Command;
146
import org.gvsig.tools.visitor.Visitor;
147

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

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

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

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

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

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

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

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

    
176
    private DefaultDataManager dataManager = null;
177

    
178
    private FeatureStoreProvider provider = null;
179

    
180
    private DefaultFeatureIndexes indexes;
181

    
182
    private DefaultFeatureStoreTransforms transforms;
183

    
184
    DelegatedDynObject metadata;
185
    
186
    private Set metadataChildren;
187

    
188
    private Long featureCount = null;
189

    
190
    private long temporalOid = 0;
191

    
192
    private FeatureCacheProvider cache;
193

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

    
203
    public DefaultFeatureStore() {
204

    
205
    }
206

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

    
210
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
211

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

    
216
        this.dataManager = (DefaultDataManager) dataManager;
217

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

    
226
    }
227

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
320
    public boolean allowWrite() {
321
        return this.provider.allowWrite();
322
    }
323

    
324
    public boolean canWriteGeometry(int geometryType) throws DataException {
325
        return this.provider.canWriteGeometry(geometryType, 0);
326
    }
327

    
328
    public DataServerExplorer getExplorer() throws ReadException,
329
        ValidateDataParametersException {
330
        return this.provider.getExplorer();
331
    }
332

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

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

    
358
    /**
359
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
360
     */
361
    public IProjection getSRSDefaultGeometry() throws DataException {
362
        return this.getDefaultFeatureType().getDefaultSRS();
363
    }
364

    
365
    public FeatureSelection createDefaultFeatureSelection()
366
        throws DataException {
367
        return new DefaultFeatureSelection(this);
368
    }
369

    
370
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
371
        throws DataException {
372
        if (type.hasOID()) {
373
            return new DefaultFeatureProvider(type,
374
                this.provider.createNewOID());
375
        }
376
        return new DefaultFeatureProvider(type);
377
    }
378

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

    
413
        }
414

    
415
        if (evaluatedAttr.isEmpty()) {
416
            evaluatedAttr = null;
417
        }
418

    
419
        state.set("evaluatedAttributes", evaluatedAttr);
420
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
421

    
422
    }
423

    
424
    public void loadFromState(PersistentState state)
425
        throws PersistenceException {
426
        if (this.provider != null) {
427
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
428
        }
429
        if (this.getManager() == null) {
430
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
431
        }
432

    
433
        DataStoreParameters params =
434
            (DataStoreParameters) state.get("parameters");
435

    
436
        try {
437

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

    
477
                }
478

    
479
            }
480

    
481
            String defFTypeid = state.getString("defaultFeatureTypeId");
482
            FeatureType ftype = null;
483
            
484
            if (this.defaultFeatureType == null ||
485
                this.defaultFeatureType.getId() == null ||
486
                !this.defaultFeatureType.getId().equals(
487
                state.getString("defaultFeatureTypeId"))) {
488

    
489
                ftype = getFeatureType(defFTypeid);
490
                if (ftype == null) {
491
                    throw new PersistenceCantFindDefaultFeatureTypeException(
492
                        this.getName(), defFTypeid);
493
                }
494
                this.defaultFeatureType = ftype;
495
            }
496

    
497
        } catch (InitializeException e) {
498
            throw new PersistenceException(e);
499
        } catch (DataException e) {
500
            throw new PersistenceException(e);
501
        }
502

    
503
    }
504

    
505
    public static void registerPersistenceDefinition() {
506
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
507
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
508
            DynStruct definition =
509
                manager.addDefinition(DefaultFeatureStore.class,
510
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
511
                        + " Persistent definition", null, null);
512
            definition.addDynFieldString("dataStoreName").setMandatory(true)
513
                .setPersistent(true);
514

    
515
            definition.addDynFieldObject("parameters")
516
                .setClassOfValue(DynObject.class).setMandatory(true)
517
                .setPersistent(true);
518

    
519
            definition.addDynFieldObject("selection")
520
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
521
                .setPersistent(true);
522

    
523
            definition.addDynFieldObject("transforms")
524
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
525
                .setMandatory(true).setPersistent(true);
526

    
527
            definition.addDynFieldMap("evaluatedAttributes")
528
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
529
                .setMandatory(false).setPersistent(true);
530

    
531
            definition.addDynFieldString("defaultFeatureTypeId")
532
                .setMandatory(true).setPersistent(true);
533
        }
534
    }
535

    
536
    public static void registerMetadataDefinition() throws MetadataException {
537
        MetadataManager manager = MetadataLocator.getMetadataManager();
538
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
539
            DynStruct metadataDefinition =
540
                manager.addDefinition(METADATA_DEFINITION_NAME, null);
541
            metadataDefinition.extend(manager
542
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
543
        }
544
    }
545

    
546
    //
547
    // ====================================================================
548
    // Gestion de la seleccion
549
    //
550

    
551
    public void setSelection(DataSet selection) throws DataException {
552
        this.setSelection((FeatureSet) selection);
553
    }
554

    
555
    public DataSet createSelection() throws DataException {
556
        return createFeatureSelection();
557
    }
558

    
559
    public DataSet getSelection() throws DataException {
560
        return this.getFeatureSelection();
561
    }
562

    
563
    public void setSelection(FeatureSet selection) throws DataException {
564
        setSelection(selection, true);
565
    }
566

    
567
    /**
568
     * @see #setSelection(FeatureSet)
569
     * @param undoable
570
     *            if the action must be undoable
571
     */
572
    public void setSelection(FeatureSet selection, boolean undoable)
573
        throws DataException {
574
        if (selection == null) {
575
            if (undoable) {
576
                throw new SelectionNotAllowedException(getName());
577
            }
578

    
579
        } else {
580
            if (selection.equals(this.selection)) {
581
                return;
582
            }
583
            if (!selection.isFromStore(this)) {
584
                throw new SelectionNotAllowedException(getName());
585
            }
586
        }
587

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

    
626
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
627
    }
628

    
629
    public FeatureSelection createFeatureSelection() throws DataException {
630
        return this.provider.createFeatureSelection();
631
    }
632

    
633
    public FeatureSelection getFeatureSelection() throws DataException {
634
        if (selection == null) {
635
            this.selection = createFeatureSelection();
636
            this.selection.addObserver(this);
637
        }
638
        return selection;
639
    }
640

    
641
    //
642
    // ====================================================================
643
    // Gestion de notificaciones
644
    //
645

    
646
    public void notifyChange(String notification) {
647
        if (delegateObservable != null) {
648
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
649
        }
650

    
651
    }
652

    
653
    public void notifyChange(String notification, FeatureProvider data) {
654
        try {
655
            notifyChange(notification, createFeature(data));
656
        } catch (DataException ex) {
657
            LOG.error("Error notifying about the notification: " + notification
658
                + ", with the data: " + data, ex);
659
        }
660
    }
661

    
662
    public void notifyChange(String notification, Feature feature) {
663
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
664
            feature));
665
    }
666

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

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

    
677
    public void notifyChange(FeatureStoreNotification storeNotification) {
678
        delegateObservable.notifyObservers(storeNotification);
679
    }
680

    
681
    public void notifyChange(String notification, Resource resource) {
682
        notifyChange(new DefaultFeatureStoreNotification(this,
683
            DataStoreNotification.RESOURCE_CHANGED));
684
    }
685

    
686
    //
687
    // ====================================================================
688
    // Gestion de bloqueos
689
    //
690

    
691
    public boolean isLocksSupported() {
692
        return this.provider.isLocksSupported();
693
    }
694

    
695
    public FeatureLocks getLocks() throws DataException {
696
        if (!this.provider.isLocksSupported()) {
697
            LOG.warn("Locks not supported");
698
            return null;
699
        }
700
        if (locks == null) {
701
            this.locks = this.provider.createFeatureLocks();
702
        }
703
        return locks;
704
    }
705

    
706
    //
707
    // ====================================================================
708
    // Interface Observable
709
    //
710

    
711
    public void disableNotifications() {
712
        this.delegateObservable.disableNotifications();
713

    
714
    }
715

    
716
    public void enableNotifications() {
717
        this.delegateObservable.enableNotifications();
718
    }
719

    
720
    public void beginComplexNotification() {
721
        this.delegateObservable.beginComplexNotification();
722

    
723
    }
724

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

    
728
    }
729

    
730
    public void addObserver(Observer observer) {
731
        if (delegateObservable != null) {
732
            this.delegateObservable.addObserver(observer);
733
        }
734
    }
735

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

    
742
    public void deleteObservers() {
743
        this.delegateObservable.deleteObservers();
744

    
745
    }
746

    
747
    //
748
    // ====================================================================
749
    // Interface Observer
750
    //
751
    // Usado para observar:
752
    // - su seleccion
753
    // - sus bloqueos
754
    // - sus recursos
755
    //
756

    
757
    public void update(Observable observable, Object notification) {
758
        if (observable instanceof FeatureSet) {
759
            if (observable == this.selection) {
760
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
761
            } else
762
                if (observable == this.locks) {
763
                    this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
764
                }
765

    
766
        } else
767
            if (observable instanceof FeatureStoreProvider) {
768
                if (observable == this.provider) {
769

    
770
                }
771

    
772
            }
773
    }
774

    
775
    //
776
    // ====================================================================
777
    // Edicion
778
    //
779

    
780
    private void newVersionOfUpdate() {
781
        this.versionOfUpdate++;
782
    }
783

    
784
    private long currentVersionOfUpdate() {
785
        return this.versionOfUpdate;
786
    }
787

    
788
    private void checkInEditingMode() throws NeedEditingModeException {
789
        if (mode != MODE_FULLEDIT) {
790
            throw new NeedEditingModeException(this.getName());
791
        }
792
    }
793

    
794
    private void checkNotInAppendMode() throws IllegalStateException {
795
        if (mode == MODE_APPEND) {
796
                        throw new IllegalStateException("Error: store "
797
                                        + this.getFullName() + " is in append mode");
798
        }
799
    }
800

    
801
    private void checkIsOwnFeature(Feature feature)
802
        throws IllegalFeatureException {
803
        if (((DefaultFeature) feature).getStore() != this) {
804
            throw new IllegalFeatureException(this.getName());
805
        }
806
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
807
        // fixFeatureType((DefaultFeatureType) feature.getType());
808
    }
809

    
810
    private void exitEditingMode() {
811
        if (commands != null) {
812
            commands.clear();
813
            commands = null;
814
        }
815

    
816
        if (featureTypeManager != null) {
817
            featureTypeManager.dispose();
818
            featureTypeManager = null;
819

    
820
        }
821

    
822
        // TODO implementar un dispose para estos dos
823
        featureManager = null;
824
        spatialManager = null;
825

    
826
        featureCount = null;
827

    
828
        mode = MODE_QUERY;
829
        hasStrongChanges = true; // Lo deja a true por si las moscas
830
        hasInserts = true;
831
    }
832

    
833
    synchronized public void edit() throws DataException {
834
        edit(MODE_FULLEDIT);
835
    }
836

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

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

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

    
888
    private void invalidateIndexes() {
889
        setIndexesValidStatus(false);
890
    }
891

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

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

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

    
932
    private void disposeIndexes() {
933
        FeatureIndexes indexes = getIndexes();
934
        LOG.debug("Disposing indexes: {}", indexes);
935
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
936
            FeatureIndex index = (FeatureIndex) iterator.next();
937
            if (index instanceof FeatureIndexProviderServices) {
938
                FeatureIndexProviderServices indexServices =
939
                    (FeatureIndexProviderServices) index;
940
                indexServices.dispose();
941
            }
942
        }
943
    }
944

    
945
    public boolean isEditing() {
946
        return mode == MODE_FULLEDIT;
947
    }
948

    
949
    public boolean isAppending() {
950
        return mode == MODE_APPEND;
951
    }
952

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

    
964
            FeatureType oldt = type.getSource().getCopy();
965
            FeatureType newt = type.getCopy();
966
            commands.update(newt, oldt);
967

    
968
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
969
                hasStrongChanges = true;
970
            }
971
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
972
        } catch (Exception e) {
973
            throw new StoreUpdateFeatureTypeException(e, this.getName());
974
        }
975
    }
976

    
977
    public void delete(Feature feature) throws DataException {       
978
        this.commands.delete(feature);
979
    }
980
    
981
    synchronized public void doDelete(Feature feature) throws DataException {
982
        try {
983
            checkInEditingMode();
984
            checkIsOwnFeature(feature);
985
            if (feature instanceof EditableFeature) {
986
                throw new StoreDeleteEditableFeatureException(getName());
987
            }
988
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);            
989
            
990
            //Update the featureManager and the spatialManager
991
            featureManager.delete(feature.getReference());
992
            spatialManager.deleteFeature(feature);
993
            
994
            newVersionOfUpdate();
995
            hasStrongChanges = true;
996
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
997
        } catch (Exception e) {
998
            throw new StoreDeleteFeatureException(e, this.getName());
999
        }
1000
    }
1001

    
1002
    private static EditableFeature lastChangedFeature = null;
1003

    
1004
    public synchronized void insert(EditableFeature feature) 
1005
        throws DataException {
1006
        LOG.debug("In editing mode {}, insert feature: {}", new Integer(mode),
1007
            feature);
1008
        try {
1009
            switch (mode) {
1010
            case MODE_QUERY:
1011
                throw new NeedEditingModeException(this.getName());
1012

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

    
1027
            case MODE_FULLEDIT: 
1028
                if (feature.getSource() != null) {
1029
                    throw new NoNewFeatureInsertException(this.getName());
1030
                }
1031
                commands.insert(feature);               
1032
            }
1033
        } catch (Exception e) {
1034
            throw new StoreInsertFeatureException(e, this.getName());
1035
        }
1036
    }
1037
    
1038
    synchronized public void doInsert(EditableFeature feature)
1039
        throws DataException {
1040
        checkIsOwnFeature(feature);
1041
   
1042
        waitForIndexes();
1043

    
1044
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1045
        newVersionOfUpdate();
1046
        if ((lastChangedFeature == null)
1047
            || (lastChangedFeature.getSource() != feature.getSource())) {
1048
            lastChangedFeature = feature;
1049
            feature.validate(Feature.UPDATE);
1050
            lastChangedFeature = null;
1051
        }
1052
        //Update the featureManager and the spatialManager
1053
        ((DefaultEditableFeature) feature).setInserted(true);
1054
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1055
        
1056
        
1057
        featureManager.add(newFeature);
1058
        spatialManager.insertFeature(newFeature);
1059
        
1060
        hasStrongChanges = true;
1061
        hasInserts = true;
1062
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);       
1063
    }
1064
    
1065
    public void update(EditableFeature feature)
1066
    throws DataException {        
1067
        if ((feature).getSource() == null) {
1068
            insert(feature);
1069
            return;
1070
        }
1071
        commands.update(feature, feature.getSource());
1072
    }
1073

    
1074
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1075
        throws DataException {
1076
        try {          
1077
            checkInEditingMode();
1078
            checkIsOwnFeature(feature);
1079
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1080
            newVersionOfUpdate();
1081
            if ((lastChangedFeature == null)
1082
                || (lastChangedFeature.getSource() != feature.getSource())) {
1083
                lastChangedFeature = feature;
1084
                feature.validate(Feature.UPDATE);
1085
                lastChangedFeature = null;
1086
            }
1087
            
1088
            //Update the featureManager and the spatialManager
1089
            Feature newf = feature.getNotEditableCopy();
1090
            featureManager.update(newf, oldFeature);
1091
            spatialManager.updateFeature(newf, oldFeature);
1092
   
1093
            hasStrongChanges = true;
1094
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1095
        } catch (Exception e) {
1096
            throw new StoreUpdateFeatureException(e, this.getName());
1097
        }
1098
    }
1099

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

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

    
1128
    public List getRedoInfos() {
1129
        if (isEditing() && (commands != null)) {
1130
            return commands.getRedoInfos();
1131
        } else {
1132
            return null;
1133
        }
1134
    }
1135

    
1136
    public List getUndoInfos() {
1137
        if (isEditing() && (commands != null)) {
1138
            return commands.getUndoInfos();
1139
        } else {
1140
            return null;
1141
        }
1142
    }
1143

    
1144
    public synchronized FeatureCommandsStack getCommandsStack()
1145
        throws DataException {
1146
        checkInEditingMode();
1147
        return commands;
1148
    }
1149

    
1150
    synchronized public void cancelEditing() throws DataException {
1151
        spatialManager.cancelModifies();
1152
        try {
1153
            checkInEditingMode();
1154

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

    
1171
    synchronized public void finishEditing() throws DataException {
1172
        LOG.debug("finish editing of mode: {}", new Integer(mode));
1173
        try {
1174
            
1175
            /*
1176
             * Selection needs to be cleared when editing stops
1177
             * to prevent conflicts with selection remaining from
1178
             * editing mode.
1179
             */
1180
            ((FeatureSelection) this.getSelection()).deselectAll();
1181
            
1182
            switch (mode) {
1183
            case MODE_QUERY:
1184
                throw new NeedEditingModeException(this.getName());
1185

    
1186
            case MODE_APPEND:
1187
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1188
                provider.endAppend();
1189
                exitEditingMode();
1190
                updateIndexes();
1191
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1192
                break;
1193

    
1194
            case MODE_FULLEDIT:
1195
                if (hasStrongChanges && !this.allowWrite()) {
1196
                    throw new WriteNotAllowedException(getName());
1197
                }
1198
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1199
                if (hasStrongChanges) {
1200
                    validateFeatures(Feature.FINISH_EDITING);
1201
                    provider.performChanges(featureManager.getDeleted(),
1202
                        featureManager.getInserted(),
1203
                        featureManager.getUpdated(),
1204
                        featureTypeManager.getFeatureTypesChanged());
1205
                }
1206
                exitEditingMode();
1207
                updateIndexes();
1208
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1209
                break;
1210
            }
1211
        } catch (Exception e) {
1212
            throw new FinishEditingException(e);
1213
        }
1214
    }
1215

    
1216
    /**
1217
     * Save changes in the provider without leaving the edit mode.
1218
     * Do not call observers to communicate a change of ediding mode.
1219
     * The operation's history is eliminated to prevent inconsistencies
1220
     * in the data.
1221
     *
1222
     * @throws DataException
1223
     */
1224
    synchronized public void commitChanges() throws DataException {
1225
      LOG.debug("commitChanges of mode: {}", new Integer(mode));
1226
      if( !canCommitChanges() ) {
1227
              throw new WriteNotAllowedException(getName());
1228
      }
1229
      try {
1230
        switch (mode) {
1231
        case MODE_QUERY:
1232
          throw new NeedEditingModeException(this.getName());
1233

    
1234
        case MODE_APPEND:
1235
          this.provider.endAppend();
1236
          exitEditingMode();
1237
          invalidateIndexes();
1238
          this.provider.beginAppend();
1239
          hasInserts = false;
1240
          break;
1241

    
1242
        case MODE_FULLEDIT:
1243
          if (hasStrongChanges && !this.allowWrite()) {
1244
            throw new WriteNotAllowedException(getName());
1245
          }
1246
          if (hasStrongChanges) {
1247
            validateFeatures(Feature.FINISH_EDITING);
1248
            provider.performChanges(featureManager.getDeleted(),
1249
              featureManager.getInserted(),
1250
              featureManager.getUpdated(),
1251
              featureTypeManager.getFeatureTypesChanged());
1252
          }
1253
          invalidateIndexes();
1254
          featureManager =
1255
            new FeatureManager(new MemoryExpansionAdapter());
1256
          featureTypeManager =
1257
            new FeatureTypeManager(this, new MemoryExpansionAdapter());
1258
          spatialManager =
1259
            new SpatialManager(this, provider.getEnvelope());
1260

    
1261
          commands =
1262
            new DefaultFeatureCommandsStack(this, featureManager,
1263
              spatialManager, featureTypeManager);
1264
          featureCount = null;
1265
          hasStrongChanges = false;
1266
          hasInserts = false;
1267
          break;
1268
        }
1269
      } catch (Exception e) {
1270
        throw new FinishEditingException(e);
1271
      }
1272
    }
1273

    
1274
    synchronized public boolean canCommitChanges() throws DataException {
1275
        if ( !this.allowWrite()) {
1276
                return false;
1277
        }
1278
            switch (mode) {
1279
            default:
1280
        case MODE_QUERY:
1281
                return false;
1282
                
1283
        case MODE_APPEND:
1284
                return true;
1285
        
1286
        case MODE_FULLEDIT:
1287
            List types = this.getFeatureTypes();
1288
            for( int i=0; i<types.size(); i++ ) {
1289
                    Object type = types.get(i);
1290
                    if( type instanceof DefaultEditableFeatureType ) {
1291
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1292
                                    return false;
1293
                            }
1294
                    }
1295
            }
1296
            return true;
1297
            }
1298
    }
1299
    
1300
    public void beginEditingGroup(String description)
1301
        throws NeedEditingModeException {
1302
        checkInEditingMode();
1303
        commands.startComplex(description);
1304
    }
1305

    
1306
    public void endEditingGroup() throws NeedEditingModeException {
1307
        checkInEditingMode();
1308
        commands.endComplex();
1309
    }
1310

    
1311
    public boolean isAppendModeSupported() {
1312
        return this.provider.supportsAppendMode();
1313
    }
1314

    
1315
    public void export(DataServerExplorer explorer, String provider,
1316
        NewFeatureStoreParameters params) throws DataException {
1317

    
1318
        if (this.getFeatureTypes().size() != 1) {
1319
            throw new NotYetImplemented(
1320
                "export whith more than one type not yet implemented");
1321
        }
1322
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1323
        FeatureStore target = null;
1324
        FeatureSet features = null;
1325
        DisposableIterator iterator = null;
1326
        try {
1327
            FeatureType type = this.getDefaultFeatureType();
1328
            if ((params.getDefaultFeatureType() == null)
1329
                || (params.getDefaultFeatureType().size() == 0)) {
1330
                params.setDefaultFeatureType(type.getEditable());
1331

    
1332
            }
1333
            explorer.add(provider, params, true);
1334

    
1335
            DataManager manager = DALLocator.getDataManager();
1336
            target = (FeatureStore) manager.openStore(provider, params);
1337
            FeatureType targetType = target.getDefaultFeatureType();
1338

    
1339
            target.edit(MODE_APPEND);
1340
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1341
            if (featureSelection.getSize() > 0) {
1342
                features = this.getFeatureSelection();
1343
            } else {
1344
                if ((pk != null) && (pk.length > 0)) {
1345
                    FeatureQuery query = createFeatureQuery();
1346
                    for (int i = 0; i < pk.length; i++) {
1347
                        query.getOrder().add(pk[i].getName(), true);
1348
                    }
1349
                    features = this.getFeatureSet(query);
1350
                } else {
1351
                    features = this.getFeatureSet();
1352
                }
1353
            }
1354
            iterator = features.fastIterator();
1355
            while (iterator.hasNext()) {
1356
                DefaultFeature feature = (DefaultFeature) iterator.next();
1357
                target.insert(target.createNewFeature(targetType, feature));
1358
            }
1359
            target.finishEditing();
1360
            target.dispose();
1361
        } catch (Exception e) {
1362
            throw new DataExportException(e, params.toString());
1363
        } finally {
1364
            dispose(iterator);
1365
            dispose(features);
1366
            dispose(target);
1367
        }
1368
    }
1369

    
1370
    //
1371
    // ====================================================================
1372
    // Obtencion de datos
1373
    // getDataCollection, getFeatureCollection
1374
    //
1375

    
1376
    public DataSet getDataSet() throws DataException {
1377
        checkNotInAppendMode();
1378
        FeatureQuery query =
1379
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1380
        return new DefaultFeatureSet(this, query);
1381
    }
1382

    
1383
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1384
        checkNotInAppendMode();
1385
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1386
    }
1387

    
1388
    public void getDataSet(Observer observer) throws DataException {
1389
        checkNotInAppendMode();
1390
        this.getFeatureSet(null, observer);
1391
    }
1392

    
1393
    public void getDataSet(DataQuery dataQuery, Observer observer)
1394
        throws DataException {
1395
        checkNotInAppendMode();
1396
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1397
    }
1398

    
1399
    public FeatureSet getFeatureSet() throws DataException {
1400
        checkNotInAppendMode();
1401
        FeatureQuery query =
1402
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1403
        return new DefaultFeatureSet(this, query);
1404
    }
1405

    
1406
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1407
        throws DataException {
1408
        checkNotInAppendMode();
1409
        return new DefaultFeatureSet(this, featureQuery);
1410
    }
1411

    
1412
    public void accept(Visitor visitor) throws BaseException {
1413
        FeatureSet set = getFeatureSet();
1414
        try {
1415
            set.accept(visitor);
1416
        } finally {
1417
            set.dispose();
1418
        }
1419
    }
1420

    
1421
    public void accept(Visitor visitor, DataQuery dataQuery)
1422
        throws BaseException {
1423
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1424
        try {
1425
            set.accept(visitor);
1426
        } finally {
1427
            set.dispose();
1428
        }
1429
    }
1430

    
1431
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1432
        throws DataException {
1433
        DefaultFeatureType fType =
1434
            (DefaultFeatureType) this.getFeatureType(featureQuery
1435
                .getFeatureTypeId());
1436
        if ((featureQuery.getAttributeNames() != null)
1437
            && (featureQuery.getAttributeNames().length > 0)) {
1438
            return fType.getSubtype(featureQuery.getAttributeNames());
1439
        }
1440
        return fType;
1441
    }
1442

    
1443
    public void getFeatureSet(Observer observer) throws DataException {
1444
        checkNotInAppendMode();
1445
        this.getFeatureSet(null, observer);
1446
    }
1447

    
1448
    public void getFeatureSet(FeatureQuery query, Observer observer)
1449
        throws DataException {
1450
        class LoadInBackGround implements Runnable {
1451

    
1452
            private FeatureStore store;
1453
            private FeatureQuery query;
1454
            private Observer observer;
1455

    
1456
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1457
                Observer observer) {
1458
                this.store = store;
1459
                this.query = query;
1460
                this.observer = observer;
1461
            }
1462

    
1463
            void notify(FeatureStoreNotification theNotification) {
1464
                observer.update(store, theNotification);
1465
                return;
1466
            }
1467

    
1468
            public void run() {
1469
                FeatureSet set = null;
1470
                try {
1471
                    set = store.getFeatureSet(query);
1472
                    notify(new DefaultFeatureStoreNotification(store,
1473
                        FeatureStoreNotification.LOAD_FINISHED, set));
1474
                } catch (Exception e) {
1475
                    notify(new DefaultFeatureStoreNotification(store,
1476
                        FeatureStoreNotification.LOAD_FINISHED, e));
1477
                } finally {
1478
                    dispose(set);
1479
                }
1480
            }
1481
        }
1482

    
1483
        checkNotInAppendMode();
1484
        if (query == null) {
1485
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1486
        }
1487
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1488
        Thread thread = new Thread(task, "Load Feature Set in background");
1489
        thread.start();
1490
    }
1491

    
1492
    public Feature getFeatureByReference(FeatureReference reference)
1493
        throws DataException {
1494
        checkNotInAppendMode();
1495
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1496
        FeatureType featureType;
1497
        if (ref.getFeatureTypeId() == null) {
1498
            featureType = this.getDefaultFeatureType();
1499
        } else {
1500
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1501
        }
1502
        return this.getFeatureByReference(reference, featureType);
1503
    }
1504

    
1505
    public Feature getFeatureByReference(FeatureReference reference,
1506
        FeatureType featureType) throws DataException {
1507
        checkNotInAppendMode();
1508
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1509
        if (!this.transforms.isEmpty()) {
1510

    
1511
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1512

    
1513
        }
1514
        // TODO comprobar que el id es de este store
1515

    
1516
        if (this.mode == MODE_FULLEDIT) {
1517
            Feature f = featureManager.get(reference, this, featureType);
1518
            if (f != null) {
1519
                return f;
1520
            }
1521
        }
1522
    
1523
        
1524
        DefaultFeature feature =
1525
            new DefaultFeature(this,
1526
                this.provider.getFeatureProviderByReference(
1527
                    (FeatureReferenceProviderServices) reference, featureType));
1528

    
1529
        if (!this.transforms.isEmpty()) {
1530
            return this.transforms.applyTransform(feature, featureType);
1531
        }
1532
        return feature;
1533
    }
1534

    
1535
    //
1536
    // ====================================================================
1537
    // Gestion de features
1538
    //
1539

    
1540
    private FeatureType fixFeatureType(DefaultFeatureType type)
1541
        throws DataException {
1542
        FeatureType original = this.getDefaultFeatureType();
1543

    
1544
        if ((type == null) || type.equals(original)) {
1545
            return original;
1546
        } else {
1547
            if (!type.isSubtypeOf(original)) {
1548
                Iterator iter = this.getFeatureTypes().iterator();
1549
                FeatureType tmpType;
1550
                boolean found = false;
1551
                while (iter.hasNext()) {
1552
                    tmpType = (FeatureType) iter.next();
1553
                    if (type.equals(tmpType)) {
1554
                        return type;
1555

    
1556
                    } else
1557
                        if (type.isSubtypeOf(tmpType)) {
1558
                            found = true;
1559
                            original = tmpType;
1560
                            break;
1561
                        }
1562

    
1563
                }
1564
                if (!found) {
1565
                    throw new IllegalFeatureTypeException(getName());
1566
                }
1567
            }
1568
        }
1569

    
1570
        // Checks that type has all fields of pk
1571
        // else add the missing attributes at the end.
1572
        if (!original.hasOID()) {
1573
            // Gets original pk attributes
1574
            DefaultEditableFeatureType edOriginal =
1575
                (DefaultEditableFeatureType) original.getEditable();
1576
            FeatureAttributeDescriptor orgAttr;
1577
            Iterator edOriginalIter = edOriginal.iterator();
1578
            while (edOriginalIter.hasNext()) {
1579
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1580
                if (!orgAttr.isPrimaryKey()) {
1581
                    edOriginalIter.remove();
1582
                }
1583
            }
1584

    
1585
            // Checks if all pk attributes are in type
1586
            Iterator typeIterator;
1587
            edOriginalIter = edOriginal.iterator();
1588
            FeatureAttributeDescriptor attr;
1589
            while (edOriginalIter.hasNext()) {
1590
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1591
                typeIterator = type.iterator();
1592
                while (typeIterator.hasNext()) {
1593
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1594
                    if (attr.getName().equals(orgAttr.getName())) {
1595
                        edOriginalIter.remove();
1596
                        break;
1597
                    }
1598
                }
1599
            }
1600

    
1601
            // add missing pk attributes if any
1602
            if (edOriginal.size() > 0) {
1603
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1604
                DefaultEditableFeatureType edType =
1605
                    (DefaultEditableFeatureType) original.getEditable();
1606
                edType.clear();
1607
                edType.addAll(type);
1608
                edType.addAll(edOriginal);
1609
                if (!isEditable) {
1610
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1611
                }
1612
            }
1613

    
1614
        }
1615

    
1616
        return type;
1617
    }
1618

    
1619
    public void validateFeatures(int mode) throws DataException {
1620
        FeatureSet collection = null;
1621
        DisposableIterator iter = null;
1622
        try {
1623
            checkNotInAppendMode();
1624
            collection = this.getFeatureSet();
1625
            iter = collection.fastIterator();
1626
            long previousVersionOfUpdate = currentVersionOfUpdate();
1627
            while (iter.hasNext()) {
1628
                ((DefaultFeature) iter.next()).validate(mode);
1629
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1630
                    throw new ConcurrentDataModificationException(getName());
1631
                }
1632
            }
1633
        } catch (Exception e) {
1634
            throw new ValidateFeaturesException(e, getName());
1635
        } finally {
1636
            dispose(iter);
1637
            dispose(collection);
1638
        }
1639
    }
1640

    
1641
    public FeatureType getDefaultFeatureType() throws DataException {
1642
        try {
1643
            
1644
            if (isEditing()) {
1645
                FeatureType auxFeatureType =
1646
                    featureTypeManager.getType(defaultFeatureType.getId());
1647
                if (auxFeatureType != null) {
1648
                    return avoidEditable(auxFeatureType);
1649
                }
1650
            }
1651
            FeatureType type = this.transforms.getDefaultFeatureType();
1652
            if (type != null) {
1653
                return avoidEditable(type);
1654
            }
1655
            
1656
            return avoidEditable(defaultFeatureType);
1657
            
1658
        } catch (Exception e) {
1659
            throw new GetFeatureTypeException(e, getName());
1660
        }
1661
    }
1662
    
1663
    private FeatureType avoidEditable(FeatureType ft) {
1664
        if (ft instanceof EditableFeatureType) {
1665
            return ((EditableFeatureType) ft).getNotEditableCopy();
1666
        } else {
1667
            return ft;
1668
        }
1669
    }
1670

    
1671
    public FeatureType getFeatureType(String featureTypeId)
1672
        throws DataException {
1673
        if (featureTypeId == null) {
1674
            return this.getDefaultFeatureType();
1675
        }
1676
        try {
1677
            if (isEditing()) {
1678
                FeatureType auxFeatureType =
1679
                    featureTypeManager.getType(featureTypeId);
1680
                if (auxFeatureType != null) {
1681
                    return auxFeatureType;
1682
                }
1683
            }
1684
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1685
            if (type != null) {
1686
                return type;
1687
            }
1688
            Iterator iter = this.featureTypes.iterator();
1689
            while (iter.hasNext()) {
1690
                type = (FeatureType) iter.next();
1691
                if (type.getId().equals(featureTypeId)) {
1692
                    return type;
1693
                }
1694
            }
1695
            return null;
1696
        } catch (Exception e) {
1697
            throw new GetFeatureTypeException(e, getName());
1698
        }
1699
    }
1700

    
1701
    public FeatureType getProviderDefaultFeatureType() {
1702
        return defaultFeatureType;
1703
    }
1704

    
1705
    public List getFeatureTypes() throws DataException {
1706
        try {
1707
            List types;
1708
            if (isEditing()) {
1709
                types = new ArrayList();
1710
                Iterator it = featureTypes.iterator();
1711
                while (it.hasNext()) {
1712
                    FeatureType type = (FeatureType) it.next();
1713
                    FeatureType typeaux =
1714
                        featureTypeManager.getType(type.getId());
1715
                    if (typeaux != null) {
1716
                        types.add(typeaux);
1717
                    } else {
1718
                        types.add(type);
1719
                    }
1720
                }
1721
                it = featureTypeManager.newsIterator();
1722
                while (it.hasNext()) {
1723
                    FeatureType type = (FeatureType) it.next();
1724
                    types.add(type);
1725
                }
1726
            } else {
1727
                types = this.transforms.getFeatureTypes();
1728
                if (types == null) {
1729
                    types = featureTypes;
1730
                }
1731
            }
1732
            return Collections.unmodifiableList(types);
1733
        } catch (Exception e) {
1734
            throw new GetFeatureTypeException(e, getName());
1735
        }
1736
    }
1737

    
1738
    public List getProviderFeatureTypes() throws DataException {
1739
        return Collections.unmodifiableList(this.featureTypes);
1740
    }
1741

    
1742
    public Feature createFeature(FeatureProvider data) throws DataException {
1743
        DefaultFeature feature = new DefaultFeature(this, data);
1744
        return feature;
1745
    }
1746

    
1747
    public Feature createFeature(FeatureProvider data, FeatureType type)
1748
        throws DataException {
1749
        // FIXME: falta por implementar
1750
        // Comprobar si es un subtipo del feature de data
1751
        // y construir un feature usando el subtipo.
1752
        // Probablemente requiera generar una copia del data.
1753
        throw new NotYetImplemented();
1754
    }
1755

    
1756
    public EditableFeature createNewFeature(FeatureType type,
1757
        Feature defaultValues) throws DataException {
1758
        try {
1759
            FeatureProvider data = createNewFeatureProvider(type);
1760
            DefaultEditableFeature feature =
1761
                new DefaultEditableFeature(this, data);
1762
            feature.initializeValues(defaultValues);
1763
            data.setNew(true);
1764
            
1765
            return feature;
1766
        } catch (Exception e) {
1767
            throw new CreateFeatureException(e, getName());
1768
        }
1769
    }
1770

    
1771
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1772
        throws DataException {
1773
        type = this.fixFeatureType((DefaultFeatureType) type);
1774
        FeatureProvider data = this.provider.createFeatureProvider(type);
1775
        data.setNew(true);
1776
        if (type.hasOID() && (data.getOID() == null)) {
1777
            data.setOID(this.provider.createNewOID());
1778
        } else {
1779
            data.setOID(this.getTemporalOID());
1780
        }
1781
        return data;
1782

    
1783
    }
1784

    
1785
    public EditableFeature createNewFeature(FeatureType type,
1786
        boolean defaultValues) throws DataException {
1787
        try {
1788
            FeatureProvider data = createNewFeatureProvider(type);
1789
            DefaultEditableFeature feature =
1790
                new DefaultEditableFeature(this, data);
1791
            if (defaultValues) {
1792
                feature.initializeValues();
1793
            }
1794
            return feature;
1795
        } catch (Exception e) {
1796
            throw new CreateFeatureException(e, getName());
1797
        }
1798
    }
1799

    
1800
    public EditableFeature createNewFeature(boolean defaultValues)
1801
        throws DataException {
1802
        return this.createNewFeature(this.getDefaultFeatureType(),
1803
            defaultValues);
1804
    }
1805

    
1806
    public EditableFeature createNewFeature() throws DataException {
1807
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1808
    }
1809

    
1810
    public EditableFeatureType createFeatureType() {
1811
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1812
        return ftype;
1813
    }
1814

    
1815
    public EditableFeatureType createFeatureType(String id) {
1816
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1817
        return ftype;
1818
    }
1819

    
1820
    //
1821
    // ====================================================================
1822
    // Index related methods
1823
    //
1824

    
1825
    public FeatureIndexes getIndexes() {
1826
        return this.indexes;
1827
    }
1828

    
1829
    public FeatureIndex createIndex(FeatureType featureType,
1830
        String attributeName, String indexName) throws DataException {
1831
        return createIndex(null, featureType, attributeName, indexName);
1832
    }
1833

    
1834
    public FeatureIndex createIndex(String indexTypeName,
1835
        FeatureType featureType, String attributeName, String indexName)
1836
        throws DataException {
1837

    
1838
        return createIndex(indexTypeName, featureType, attributeName,
1839
            indexName, false, null);
1840
    }
1841

    
1842
    public FeatureIndex createIndex(FeatureType featureType,
1843
        String attributeName, String indexName, Observer observer)
1844
        throws DataException {
1845
        return createIndex(null, featureType, attributeName, indexName,
1846
            observer);
1847
    }
1848

    
1849
    public FeatureIndex createIndex(String indexTypeName,
1850
        FeatureType featureType, String attributeName, String indexName,
1851
        final Observer observer) throws DataException {
1852

    
1853
        return createIndex(indexTypeName, featureType, attributeName,
1854
            indexName, true, observer);
1855
    }
1856

    
1857
    private FeatureIndex createIndex(String indexTypeName,
1858
        FeatureType featureType, String attributeName, String indexName,
1859
        boolean background, final Observer observer) throws DataException {
1860

    
1861
        checkNotInAppendMode();
1862
        FeatureIndexProviderServices index = null;
1863
        index =
1864
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1865
                featureType, indexName,
1866
                featureType.getAttributeDescriptor(attributeName));
1867

    
1868
        try {
1869
            index.fill(background, observer);
1870
        } catch (FeatureIndexException e) {
1871
            throw new InitializeException(index.getName(), e);
1872
        }
1873

    
1874
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1875
        return index;
1876
    }
1877

    
1878
    //
1879
    // ====================================================================
1880
    // Transforms related methods
1881
    //
1882

    
1883
    public FeatureStoreTransforms getTransforms() {
1884
        return this.transforms;
1885
    }
1886

    
1887
    public FeatureQuery createFeatureQuery() {
1888
        return new DefaultFeatureQuery();
1889
    }
1890

    
1891
    public DataQuery createQuery() {
1892
        return createFeatureQuery();
1893
    }
1894

    
1895
    //
1896
    // ====================================================================
1897
    // UndoRedo related methods
1898
    //
1899

    
1900
    public boolean canRedo() {
1901
        return commands.canRedo();
1902
    }
1903

    
1904
    public boolean canUndo() {
1905
        return commands.canUndo();
1906
    }
1907

    
1908
    public void redo(int num) throws RedoException {
1909
        for (int i = 0; i < num; i++) {
1910
            redo();
1911
        }
1912
    }
1913

    
1914
    public void undo(int num) throws UndoException {
1915
        for (int i = 0; i < num; i++) {
1916
            undo();
1917
        }
1918
    }
1919

    
1920
    //
1921
    // ====================================================================
1922
    // Metadata related methods
1923
    //
1924

    
1925
    public Object getMetadataID() {
1926
        return this.provider.getSourceId();
1927
    }
1928

    
1929
    public void delegate(DynObject dynObject) {
1930
        this.metadata.delegate(dynObject);
1931
    }
1932

    
1933
    public DynClass getDynClass() {
1934
        return this.metadata.getDynClass();
1935
    }
1936

    
1937
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1938
                if( this.transforms.hasDynValue(name) ) {
1939
                        return this.transforms.getDynValue(name);
1940
                }
1941
                if (this.metadata.hasDynValue(name)) {
1942
                        return this.metadata.getDynValue(name);
1943
                }
1944
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1945
                        return this.provider.getProviderName();
1946
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1947
                        return this.provider.getSourceId();
1948
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1949
                        try {
1950
                                return this.getDefaultFeatureType();
1951
                        } catch (DataException e) {
1952
                                return null;
1953
                        }
1954
                }
1955
                return this.metadata.getDynValue(name);
1956
        }
1957

    
1958
    public boolean hasDynValue(String name) {
1959
                if( this.transforms.hasDynValue(name) ) {
1960
                        return true;
1961
                }
1962
        return this.metadata.hasDynValue(name);
1963
    }
1964

    
1965
    public void implement(DynClass dynClass) {
1966
        this.metadata.implement(dynClass);
1967
    }
1968

    
1969
    public Object invokeDynMethod(String name, DynObject context)
1970
        throws DynMethodException {
1971
        return this.metadata.invokeDynMethod(this, name, context);
1972
    }
1973

    
1974
    public Object invokeDynMethod(int code, DynObject context)
1975
        throws DynMethodException {
1976
        return this.metadata.invokeDynMethod(this, code, context);
1977
    }
1978

    
1979
    public void setDynValue(String name, Object value)
1980
        throws DynFieldNotFoundException {
1981
                if( this.transforms.hasDynValue(name) ) {
1982
                        this.transforms.setDynValue(name, value);
1983
                        return;
1984
                }
1985
        this.metadata.setDynValue(name, value);
1986

    
1987
    }
1988

    
1989
    /*
1990
     * (non-Javadoc)
1991
     * 
1992
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1993
     */
1994
    public Set getMetadataChildren() {
1995
        return this.metadataChildren;
1996
    }
1997

    
1998
    /*
1999
     * (non-Javadoc)
2000
     * 
2001
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2002
     */
2003
    public String getMetadataName() {
2004
        return this.provider.getProviderName();
2005
    }
2006

    
2007
    public FeatureTypeManager getFeatureTypeManager() {
2008
        return this.featureTypeManager;
2009
    }
2010

    
2011
    public long getFeatureCount() throws DataException {
2012
        if (featureCount == null) {
2013
            featureCount = new Long(this.provider.getFeatureCount());
2014
        }
2015
        if (this.isEditing() && !this.isAppending()) {
2016
            return featureCount.longValue()
2017
                - this.featureManager.getDeltaSize();
2018
        }
2019
        return featureCount.longValue();
2020
    }
2021

    
2022
    private Long getTemporalOID() {
2023
        return new Long(this.temporalOid++);
2024
    }
2025

    
2026
    public FeatureType getProviderFeatureType(String featureTypeId) {
2027
        if (featureTypeId == null) {
2028
            return this.defaultFeatureType;
2029
        }
2030
        FeatureType type;
2031
        Iterator iter = this.featureTypes.iterator();
2032
        while (iter.hasNext()) {
2033
            type = (FeatureType) iter.next();
2034
            if (type.getId().equals(featureTypeId)) {
2035
                return type;
2036
            }
2037
        }
2038
        return null;
2039
    }
2040

    
2041
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2042
        return ((DefaultFeature) feature).getData();
2043
    }
2044

    
2045
    public DataStore getStore() {
2046
        return this;
2047
    }
2048

    
2049
    public FeatureStore getFeatureStore() {
2050
        return this;
2051
    }
2052

    
2053
    public void createCache(String name, DynObject parameters)
2054
        throws DataException {
2055
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2056
        if (cache == null) {
2057
            throw new CreateException("FeaureCacheProvider", null);
2058
        }
2059
        cache.apply(this, provider);
2060
        provider = cache;
2061

    
2062
        featureCount = null;
2063
    }
2064

    
2065
    public FeatureCache getCache() {
2066
        return cache;
2067
    }
2068

    
2069
    public void clear() {
2070
        if (metadata != null) {
2071
            metadata.clear();
2072
        }
2073
    }
2074

    
2075
    public String getName() {
2076
        return this.provider.getName();
2077
    }
2078

    
2079
    public String getFullName() {
2080
        return this.provider.getFullName();
2081
    }
2082

    
2083
    public String getProviderName() {
2084
        return this.provider.getProviderName();
2085
    }
2086

    
2087
    public boolean isKnownEnvelope() {
2088
        return this.provider.isKnownEnvelope();
2089
    }
2090

    
2091
    public boolean hasRetrievedFeaturesLimit() {
2092
        return this.provider.hasRetrievedFeaturesLimit();
2093
    }
2094

    
2095
    public int getRetrievedFeaturesLimit() {
2096
        return this.provider.getRetrievedFeaturesLimit();
2097
    }
2098

    
2099
    public Interval getInterval() {  
2100
        return this.provider.getInterval();
2101
    }
2102

    
2103
    public Collection getTimes() {      
2104
        return this.provider.getTimes();
2105
    }
2106

    
2107
    public Collection getTimes(Interval interval) {       
2108
        return this.provider.getTimes(interval);
2109
    }
2110
    
2111
    /* (non-Javadoc)
2112
     * @see java.lang.Object#clone()
2113
     */
2114
    public Object clone() throws CloneNotSupportedException {
2115
        
2116
        DataStoreParameters dsp = getParameters();
2117
        
2118
        DefaultFeatureStore cloned_store = null;
2119
        
2120
        try {
2121
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2122
                openStore(this.getProviderName(), dsp);
2123
            if (transforms != null) {
2124
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2125
                cloned_store.transforms.setStoreForClone(this);
2126
            }
2127
        } catch (Exception e) {
2128
            throw new CloneException(e);
2129
        }   
2130
        return cloned_store;
2131
        
2132
    }
2133
}