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

History | View | Annotate | Download (72.2 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
 * AUTHORS (In addition to CIT):
26
 * 2008 IVER T.I. S.A.   {{Task}}
27
 */
28

    
29
package org.gvsig.fmap.dal.feature.impl;
30

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

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

    
46
import org.gvsig.fmap.dal.DALLocator;
47
import org.gvsig.fmap.dal.DataManager;
48
import org.gvsig.fmap.dal.DataQuery;
49
import org.gvsig.fmap.dal.DataServerExplorer;
50
import org.gvsig.fmap.dal.DataSet;
51
import org.gvsig.fmap.dal.DataStore;
52
import org.gvsig.fmap.dal.DataStoreNotification;
53
import org.gvsig.fmap.dal.DataStoreParameters;
54
import org.gvsig.fmap.dal.exception.CloneException;
55
import org.gvsig.fmap.dal.exception.CloseException;
56
import org.gvsig.fmap.dal.exception.CreateException;
57
import org.gvsig.fmap.dal.exception.DataException;
58
import org.gvsig.fmap.dal.exception.InitializeException;
59
import org.gvsig.fmap.dal.exception.OpenException;
60
import org.gvsig.fmap.dal.exception.ReadException;
61
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
62
import org.gvsig.fmap.dal.feature.EditableFeature;
63
import org.gvsig.fmap.dal.feature.EditableFeatureType;
64
import org.gvsig.fmap.dal.feature.Feature;
65
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
66
import org.gvsig.fmap.dal.feature.FeatureCache;
67
import org.gvsig.fmap.dal.feature.FeatureIndex;
68
import org.gvsig.fmap.dal.feature.FeatureIndexes;
69
import org.gvsig.fmap.dal.feature.FeatureLocks;
70
import org.gvsig.fmap.dal.feature.FeatureQuery;
71
import org.gvsig.fmap.dal.feature.FeatureReference;
72
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
73
import org.gvsig.fmap.dal.feature.FeatureSelection;
74
import org.gvsig.fmap.dal.feature.FeatureSet;
75
import org.gvsig.fmap.dal.feature.FeatureStore;
76
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
77
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
78
import org.gvsig.fmap.dal.feature.FeatureType;
79
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
80
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
81
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
82
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
83
import org.gvsig.fmap.dal.feature.exception.DataExportException;
84
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
85
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
86
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
87
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
88
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
89
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
90
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
91
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
92
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindDefaultFeatureTypeException;
93
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindFeatureTypeException;
94
import org.gvsig.fmap.dal.feature.exception.PersistenceStoreAlreadyLoadedException;
95
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
96
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
97
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
98
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
99
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
100
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
101
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
102
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
103
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
104
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
105
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
106
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
107
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
108
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
109
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
110
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
111
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
112
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
113
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
114
import org.gvsig.fmap.dal.feature.spi.cache.FeatureCacheProvider;
115
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
116
import org.gvsig.fmap.dal.impl.DefaultDataManager;
117
import org.gvsig.fmap.dal.resource.Resource;
118
import org.gvsig.fmap.dal.spi.DataStoreInitializer;
119
import org.gvsig.fmap.dal.spi.DataStoreProvider;
120
import org.gvsig.fmap.geom.primitive.Envelope;
121
import org.gvsig.metadata.MetadataLocator;
122
import org.gvsig.metadata.MetadataManager;
123
import org.gvsig.metadata.exceptions.MetadataException;
124
import org.gvsig.timesupport.Interval;
125
import org.gvsig.tools.ToolsLocator;
126
import org.gvsig.tools.dispose.DisposableIterator;
127
import org.gvsig.tools.dispose.impl.AbstractDisposable;
128
import org.gvsig.tools.dynobject.DelegatedDynObject;
129
import org.gvsig.tools.dynobject.DynClass;
130
import org.gvsig.tools.dynobject.DynObject;
131
import org.gvsig.tools.dynobject.DynObjectManager;
132
import org.gvsig.tools.dynobject.DynStruct;
133
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
134
import org.gvsig.tools.dynobject.exception.DynMethodException;
135
import org.gvsig.tools.exception.BaseException;
136
import org.gvsig.tools.exception.NotYetImplemented;
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 final 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
        return this.provider.allowWrite();
323
    }
324

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

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

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

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

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

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

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

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

    
414
        }
415

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

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

    
423
    }
424

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

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

    
437
        try {
438

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

    
478
                }
479

    
480
            }
481

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

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

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

    
504
    }
505

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
652
    }
653

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

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

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

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

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

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

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

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

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

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

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

    
715
    }
716

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

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

    
724
    }
725

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

    
729
    }
730

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

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

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

    
746
    }
747

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

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

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

    
771
                }
772

    
773
            }
774
    }
775

    
776
    //
777
    // ====================================================================
778
    // Edicion
779
    //
780

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

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

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

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

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

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

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

    
821
        }
822

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

    
827
        featureCount = null;
828

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1003
    private static EditableFeature lastChangedFeature = null;
1004

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1615
        }
1616

    
1617
        return type;
1618
    }
1619

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

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

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

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

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

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

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

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

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

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

    
1784
    }
1785

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1988
    }
1989

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

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

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

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

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

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

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

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

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

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

    
2063
        featureCount = null;
2064
    }
2065

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

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

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

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

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

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

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

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

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

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

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