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

History | View | Annotate | Download (72.1 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.fmap.dal.feature.impl;
26

    
27
import java.util.ArrayList;
28
import java.util.Collection;
29
import java.util.Collections;
30
import java.util.HashMap;
31
import java.util.HashSet;
32
import java.util.Iterator;
33
import java.util.List;
34
import java.util.Map;
35
import java.util.Map.Entry;
36
import java.util.Set;
37

    
38
import org.cresques.cts.IProjection;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

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

    
145
public final class DefaultFeatureStore extends AbstractDisposable implements
146
    DataStoreInitializer, FeatureStoreProviderServices, FeatureStore, Observer {
147

    
148
    private static final Logger LOG = LoggerFactory
149
        .getLogger(DefaultFeatureStore.class);
150

    
151
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
152

    
153
    private DataStoreParameters parameters = null;
154
    private FeatureSelection selection;
155
    private FeatureLocks locks;
156

    
157
    private DelegateWeakReferencingObservable delegateObservable =
158
        new DelegateWeakReferencingObservable(this);
159

    
160
    private FeatureCommandsStack commands;
161
    private FeatureTypeManager featureTypeManager;
162
    private FeatureManager featureManager;
163
    private SpatialManager spatialManager;
164

    
165
    private FeatureType defaultFeatureType = null;
166
    private List featureTypes = new ArrayList();
167

    
168
    private int mode = MODE_QUERY;
169
    private long versionOfUpdate = 0;
170
    private boolean hasStrongChanges = true;
171
    private boolean hasInserts = true;
172

    
173
    private DefaultDataManager dataManager = null;
174

    
175
    private FeatureStoreProvider provider = null;
176

    
177
    private DefaultFeatureIndexes indexes;
178

    
179
    private DefaultFeatureStoreTransforms transforms;
180

    
181
    DelegatedDynObject metadata;
182
    
183
    private Set metadataChildren;
184

    
185
    private Long featureCount = null;
186

    
187
    private long temporalOid = 0;
188

    
189
    private FeatureCacheProvider cache;
190

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

    
200
    public DefaultFeatureStore() {
201

    
202
    }
203

    
204
    public void intializePhase1(DataManager dataManager,
205
        DataStoreParameters parameters) throws InitializeException {
206

    
207
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
208

    
209
        this.metadata =
210
            (DelegatedDynObject) dynManager.createDynObject(
211
                METADATA_DEFINITION_NAME, MetadataManager.METADATA_NAMESPACE);
212

    
213
        this.dataManager = (DefaultDataManager) dataManager;
214

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

    
223
    }
224

    
225
    public void intializePhase2(DataStoreProvider provider) {
226
        this.provider = (FeatureStoreProvider) provider;
227
        this.delegate(provider);
228
        this.metadataChildren = new HashSet();
229
        this.metadataChildren.add(provider);
230
    }
231

    
232
    public DataStoreParameters getParameters() {
233
        return parameters;
234
    }
235

    
236
    public int getMode() {
237
        return this.mode;
238
    }
239

    
240
    public DataManager getManager() {
241
        return this.dataManager;
242
    }
243

    
244
    public Iterator getChildren() {
245
        return this.provider.getChilds();
246
    }
247

    
248
    public FeatureStoreProvider getProvider() {
249
        return this.provider;
250
    }
251

    
252
    public FeatureManager getFeatureManager() {
253
        return this.featureManager;
254
    }
255

    
256
    public void setFeatureTypes(List types, FeatureType defaultType) {
257
        this.featureTypes = types;
258
        this.defaultFeatureType = defaultType;
259
    }
260

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

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

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

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

    
301
        if (this.featureTypeManager != null) {
302
            this.featureTypeManager.dispose();
303
            this.featureTypeManager = null;
304
        }
305

    
306
        this.featureManager = null;
307
        this.spatialManager = null;
308

    
309
        this.parameters = null;
310
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
311
        if (delegateObservable != null) {
312
            this.delegateObservable.deleteObservers();
313
            this.delegateObservable = null;
314
        }
315
    }
316

    
317
    public boolean allowWrite() {
318
        return this.provider.allowWrite();
319
    }
320

    
321
    public boolean canWriteGeometry(int geometryType) throws DataException {
322
        return this.provider.canWriteGeometry(geometryType, 0);
323
    }
324

    
325
    public DataServerExplorer getExplorer() throws ReadException,
326
        ValidateDataParametersException {
327
        return this.provider.getExplorer();
328
    }
329

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

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

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

    
362
    public FeatureSelection createDefaultFeatureSelection()
363
        throws DataException {
364
        return new DefaultFeatureSelection(this);
365
    }
366

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

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

    
410
        }
411

    
412
        if (evaluatedAttr.isEmpty()) {
413
            evaluatedAttr = null;
414
        }
415

    
416
        state.set("evaluatedAttributes", evaluatedAttr);
417
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
418

    
419
    }
420

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

    
430
        DataStoreParameters params =
431
            (DataStoreParameters) state.get("parameters");
432

    
433
        try {
434

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

    
474
                }
475

    
476
            }
477

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

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

    
494
        } catch (InitializeException e) {
495
            throw new PersistenceException(e);
496
        } catch (DataException e) {
497
            throw new PersistenceException(e);
498
        }
499

    
500
    }
501

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

    
512
            definition.addDynFieldObject("parameters")
513
                .setClassOfValue(DynObject.class).setMandatory(true)
514
                .setPersistent(true);
515

    
516
            definition.addDynFieldObject("selection")
517
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
518
                .setPersistent(true);
519

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

    
524
            definition.addDynFieldMap("evaluatedAttributes")
525
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
526
                .setMandatory(false).setPersistent(true);
527

    
528
            definition.addDynFieldString("defaultFeatureTypeId")
529
                .setMandatory(true).setPersistent(true);
530
        }
531
    }
532

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

    
543
    //
544
    // ====================================================================
545
    // Gestion de la seleccion
546
    //
547

    
548
    public void setSelection(DataSet selection) throws DataException {
549
        this.setSelection((FeatureSet) selection);
550
    }
551

    
552
    public DataSet createSelection() throws DataException {
553
        return createFeatureSelection();
554
    }
555

    
556
    public DataSet getSelection() throws DataException {
557
        return this.getFeatureSelection();
558
    }
559

    
560
    public void setSelection(FeatureSet selection) throws DataException {
561
        setSelection(selection, true);
562
    }
563

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

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

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

    
623
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
624
    }
625

    
626
    public FeatureSelection createFeatureSelection() throws DataException {
627
        return this.provider.createFeatureSelection();
628
    }
629

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

    
638
    //
639
    // ====================================================================
640
    // Gestion de notificaciones
641
    //
642

    
643
    public void notifyChange(String notification) {
644
        if (delegateObservable != null) {
645
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
646
        }
647

    
648
    }
649

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

    
659
    public void notifyChange(String notification, Feature feature) {
660
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
661
            feature));
662
    }
663

    
664
    public void notifyChange(String notification, Command command) {
665
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
666
            command));
667
    }
668

    
669
    public void notifyChange(String notification, EditableFeatureType type) {
670
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
671
            type));
672
    }
673

    
674
    public void notifyChange(FeatureStoreNotification storeNotification) {
675
        delegateObservable.notifyObservers(storeNotification);
676
    }
677

    
678
    public void notifyChange(String notification, Resource resource) {
679
        notifyChange(new DefaultFeatureStoreNotification(this,
680
            DataStoreNotification.RESOURCE_CHANGED));
681
    }
682

    
683
    //
684
    // ====================================================================
685
    // Gestion de bloqueos
686
    //
687

    
688
    public boolean isLocksSupported() {
689
        return this.provider.isLocksSupported();
690
    }
691

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

    
703
    //
704
    // ====================================================================
705
    // Interface Observable
706
    //
707

    
708
    public void disableNotifications() {
709
        this.delegateObservable.disableNotifications();
710

    
711
    }
712

    
713
    public void enableNotifications() {
714
        this.delegateObservable.enableNotifications();
715
    }
716

    
717
    public void beginComplexNotification() {
718
        this.delegateObservable.beginComplexNotification();
719

    
720
    }
721

    
722
    public void endComplexNotification() {
723
        this.delegateObservable.endComplexNotification();
724

    
725
    }
726

    
727
    public void addObserver(Observer observer) {
728
        if (delegateObservable != null) {
729
            this.delegateObservable.addObserver(observer);
730
        }
731
    }
732

    
733
    public void deleteObserver(Observer observer) {
734
        if (delegateObservable != null) {
735
            this.delegateObservable.deleteObserver(observer);
736
        }
737
    }
738

    
739
    public void deleteObservers() {
740
        this.delegateObservable.deleteObservers();
741

    
742
    }
743

    
744
    //
745
    // ====================================================================
746
    // Interface Observer
747
    //
748
    // Usado para observar:
749
    // - su seleccion
750
    // - sus bloqueos
751
    // - sus recursos
752
    //
753

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

    
763
        } else
764
            if (observable instanceof FeatureStoreProvider) {
765
                if (observable == this.provider) {
766

    
767
                }
768

    
769
            }
770
    }
771

    
772
    //
773
    // ====================================================================
774
    // Edicion
775
    //
776

    
777
    private void newVersionOfUpdate() {
778
        this.versionOfUpdate++;
779
    }
780

    
781
    private long currentVersionOfUpdate() {
782
        return this.versionOfUpdate;
783
    }
784

    
785
    private void checkInEditingMode() throws NeedEditingModeException {
786
        if (mode != MODE_FULLEDIT) {
787
            throw new NeedEditingModeException(this.getName());
788
        }
789
    }
790

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

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

    
807
    private void exitEditingMode() {
808
        if (commands != null) {
809
            commands.clear();
810
            commands = null;
811
        }
812

    
813
        if (featureTypeManager != null) {
814
            featureTypeManager.dispose();
815
            featureTypeManager = null;
816

    
817
        }
818

    
819
        // TODO implementar un dispose para estos dos
820
        featureManager = null;
821
        spatialManager = null;
822

    
823
        featureCount = null;
824

    
825
        mode = MODE_QUERY;
826
        hasStrongChanges = true; // Lo deja a true por si las moscas
827
        hasInserts = true;
828
    }
829

    
830
    synchronized public void edit() throws DataException {
831
        edit(MODE_FULLEDIT);
832
    }
833

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

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

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

    
885
    private void invalidateIndexes() {
886
        setIndexesValidStatus(false);
887
    }
888

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

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

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

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

    
942
    public boolean isEditing() {
943
        return mode == MODE_FULLEDIT;
944
    }
945

    
946
    public boolean isAppending() {
947
        return mode == MODE_APPEND;
948
    }
949

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

    
961
            FeatureType oldt = type.getSource().getCopy();
962
            FeatureType newt = type.getCopy();
963
            commands.update(newt, oldt);
964

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

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

    
999
    private static EditableFeature lastChangedFeature = null;
1000

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

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

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

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

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

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

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

    
1125
    public List getRedoInfos() {
1126
        if (isEditing() && (commands != null)) {
1127
            return commands.getRedoInfos();
1128
        } else {
1129
            return null;
1130
        }
1131
    }
1132

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

    
1141
    public synchronized FeatureCommandsStack getCommandsStack()
1142
        throws DataException {
1143
        checkInEditingMode();
1144
        return commands;
1145
    }
1146

    
1147
    synchronized public void cancelEditing() throws DataException {
1148
        spatialManager.cancelModifies();
1149
        try {
1150
            checkInEditingMode();
1151

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

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

    
1183
            case MODE_APPEND:
1184
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1185
                provider.endAppend();
1186
                exitEditingMode();
1187
                updateIndexes();
1188
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1189
                break;
1190

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

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

    
1231
        case MODE_APPEND:
1232
          this.provider.endAppend();
1233
          exitEditingMode();
1234
          invalidateIndexes();
1235
          this.provider.beginAppend();
1236
          hasInserts = false;
1237
          break;
1238

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

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

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

    
1303
    public void endEditingGroup() throws NeedEditingModeException {
1304
        checkInEditingMode();
1305
        commands.endComplex();
1306
    }
1307

    
1308
    public boolean isAppendModeSupported() {
1309
        return this.provider.supportsAppendMode();
1310
    }
1311

    
1312
    public void export(DataServerExplorer explorer, String provider,
1313
        NewFeatureStoreParameters params) throws DataException {
1314

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

    
1329
            }
1330
            explorer.add(provider, params, true);
1331

    
1332
            DataManager manager = DALLocator.getDataManager();
1333
            target = (FeatureStore) manager.openStore(provider, params);
1334
            FeatureType targetType = target.getDefaultFeatureType();
1335

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

    
1367
    //
1368
    // ====================================================================
1369
    // Obtencion de datos
1370
    // getDataCollection, getFeatureCollection
1371
    //
1372

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

    
1380
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1381
        checkNotInAppendMode();
1382
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1383
    }
1384

    
1385
    public void getDataSet(Observer observer) throws DataException {
1386
        checkNotInAppendMode();
1387
        this.getFeatureSet(null, observer);
1388
    }
1389

    
1390
    public void getDataSet(DataQuery dataQuery, Observer observer)
1391
        throws DataException {
1392
        checkNotInAppendMode();
1393
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1394
    }
1395

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

    
1403
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1404
        throws DataException {
1405
        checkNotInAppendMode();
1406
        return new DefaultFeatureSet(this, featureQuery);
1407
    }
1408

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

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

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

    
1440
    public void getFeatureSet(Observer observer) throws DataException {
1441
        checkNotInAppendMode();
1442
        this.getFeatureSet(null, observer);
1443
    }
1444

    
1445
    public void getFeatureSet(FeatureQuery query, Observer observer)
1446
        throws DataException {
1447
        class LoadInBackGround implements Runnable {
1448

    
1449
            private FeatureStore store;
1450
            private FeatureQuery query;
1451
            private Observer observer;
1452

    
1453
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1454
                Observer observer) {
1455
                this.store = store;
1456
                this.query = query;
1457
                this.observer = observer;
1458
            }
1459

    
1460
            void notify(FeatureStoreNotification theNotification) {
1461
                observer.update(store, theNotification);
1462
                return;
1463
            }
1464

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

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

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

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

    
1508
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1509

    
1510
        }
1511
        // TODO comprobar que el id es de este store
1512

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

    
1526
        if (!this.transforms.isEmpty()) {
1527
            return this.transforms.applyTransform(feature, featureType);
1528
        }
1529
        return feature;
1530
    }
1531

    
1532
    //
1533
    // ====================================================================
1534
    // Gestion de features
1535
    //
1536

    
1537
    private FeatureType fixFeatureType(DefaultFeatureType type)
1538
        throws DataException {
1539
        FeatureType original = this.getDefaultFeatureType();
1540

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

    
1553
                    } else
1554
                        if (type.isSubtypeOf(tmpType)) {
1555
                            found = true;
1556
                            original = tmpType;
1557
                            break;
1558
                        }
1559

    
1560
                }
1561
                if (!found) {
1562
                    throw new IllegalFeatureTypeException(getName());
1563
                }
1564
            }
1565
        }
1566

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

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

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

    
1611
        }
1612

    
1613
        return type;
1614
    }
1615

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

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

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

    
1698
    public FeatureType getProviderDefaultFeatureType() {
1699
        return defaultFeatureType;
1700
    }
1701

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

    
1735
    public List getProviderFeatureTypes() throws DataException {
1736
        return Collections.unmodifiableList(this.featureTypes);
1737
    }
1738

    
1739
    public Feature createFeature(FeatureProvider data) throws DataException {
1740
        DefaultFeature feature = new DefaultFeature(this, data);
1741
        return feature;
1742
    }
1743

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

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

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

    
1780
    }
1781

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

    
1797
    public EditableFeature createNewFeature(boolean defaultValues)
1798
        throws DataException {
1799
        return this.createNewFeature(this.getDefaultFeatureType(),
1800
            defaultValues);
1801
    }
1802

    
1803
    public EditableFeature createNewFeature() throws DataException {
1804
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1805
    }
1806

    
1807
    public EditableFeatureType createFeatureType() {
1808
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1809
        return ftype;
1810
    }
1811

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

    
1817
    //
1818
    // ====================================================================
1819
    // Index related methods
1820
    //
1821

    
1822
    public FeatureIndexes getIndexes() {
1823
        return this.indexes;
1824
    }
1825

    
1826
    public FeatureIndex createIndex(FeatureType featureType,
1827
        String attributeName, String indexName) throws DataException {
1828
        return createIndex(null, featureType, attributeName, indexName);
1829
    }
1830

    
1831
    public FeatureIndex createIndex(String indexTypeName,
1832
        FeatureType featureType, String attributeName, String indexName)
1833
        throws DataException {
1834

    
1835
        return createIndex(indexTypeName, featureType, attributeName,
1836
            indexName, false, null);
1837
    }
1838

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

    
1846
    public FeatureIndex createIndex(String indexTypeName,
1847
        FeatureType featureType, String attributeName, String indexName,
1848
        final Observer observer) throws DataException {
1849

    
1850
        return createIndex(indexTypeName, featureType, attributeName,
1851
            indexName, true, observer);
1852
    }
1853

    
1854
    private FeatureIndex createIndex(String indexTypeName,
1855
        FeatureType featureType, String attributeName, String indexName,
1856
        boolean background, final Observer observer) throws DataException {
1857

    
1858
        checkNotInAppendMode();
1859
        FeatureIndexProviderServices index = null;
1860
        index =
1861
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1862
                featureType, indexName,
1863
                featureType.getAttributeDescriptor(attributeName));
1864

    
1865
        try {
1866
            index.fill(background, observer);
1867
        } catch (FeatureIndexException e) {
1868
            throw new InitializeException(index.getName(), e);
1869
        }
1870

    
1871
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1872
        return index;
1873
    }
1874

    
1875
    //
1876
    // ====================================================================
1877
    // Transforms related methods
1878
    //
1879

    
1880
    public FeatureStoreTransforms getTransforms() {
1881
        return this.transforms;
1882
    }
1883

    
1884
    public FeatureQuery createFeatureQuery() {
1885
        return new DefaultFeatureQuery();
1886
    }
1887

    
1888
    public DataQuery createQuery() {
1889
        return createFeatureQuery();
1890
    }
1891

    
1892
    //
1893
    // ====================================================================
1894
    // UndoRedo related methods
1895
    //
1896

    
1897
    public boolean canRedo() {
1898
        return commands.canRedo();
1899
    }
1900

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

    
1905
    public void redo(int num) throws RedoException {
1906
        for (int i = 0; i < num; i++) {
1907
            redo();
1908
        }
1909
    }
1910

    
1911
    public void undo(int num) throws UndoException {
1912
        for (int i = 0; i < num; i++) {
1913
            undo();
1914
        }
1915
    }
1916

    
1917
    //
1918
    // ====================================================================
1919
    // Metadata related methods
1920
    //
1921

    
1922
    public Object getMetadataID() {
1923
        return this.provider.getSourceId();
1924
    }
1925

    
1926
    public void delegate(DynObject dynObject) {
1927
        this.metadata.delegate(dynObject);
1928
    }
1929

    
1930
    public DynClass getDynClass() {
1931
        return this.metadata.getDynClass();
1932
    }
1933

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

    
1955
    public boolean hasDynValue(String name) {
1956
                if( this.transforms.hasDynValue(name) ) {
1957
                        return true;
1958
                }
1959
        return this.metadata.hasDynValue(name);
1960
    }
1961

    
1962
    public void implement(DynClass dynClass) {
1963
        this.metadata.implement(dynClass);
1964
    }
1965

    
1966
    public Object invokeDynMethod(String name, DynObject context)
1967
        throws DynMethodException {
1968
        return this.metadata.invokeDynMethod(this, name, context);
1969
    }
1970

    
1971
    public Object invokeDynMethod(int code, DynObject context)
1972
        throws DynMethodException {
1973
        return this.metadata.invokeDynMethod(this, code, context);
1974
    }
1975

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

    
1984
    }
1985

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

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

    
2004
    public FeatureTypeManager getFeatureTypeManager() {
2005
        return this.featureTypeManager;
2006
    }
2007

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

    
2019
    private Long getTemporalOID() {
2020
        return new Long(this.temporalOid++);
2021
    }
2022

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

    
2038
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2039
        return ((DefaultFeature) feature).getData();
2040
    }
2041

    
2042
    public DataStore getStore() {
2043
        return this;
2044
    }
2045

    
2046
    public FeatureStore getFeatureStore() {
2047
        return this;
2048
    }
2049

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

    
2059
        featureCount = null;
2060
    }
2061

    
2062
    public FeatureCache getCache() {
2063
        return cache;
2064
    }
2065

    
2066
    public void clear() {
2067
        if (metadata != null) {
2068
            metadata.clear();
2069
        }
2070
    }
2071

    
2072
    public String getName() {
2073
        return this.provider.getName();
2074
    }
2075

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

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

    
2084
    public boolean isKnownEnvelope() {
2085
        return this.provider.isKnownEnvelope();
2086
    }
2087

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

    
2092
    public int getRetrievedFeaturesLimit() {
2093
        return this.provider.getRetrievedFeaturesLimit();
2094
    }
2095

    
2096
    public Interval getInterval() {  
2097
        return this.provider.getInterval();
2098
    }
2099

    
2100
    public Collection getTimes() {      
2101
        return this.provider.getTimes();
2102
    }
2103

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