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

History | View | Annotate | Download (72.6 KB)

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

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

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

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

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

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

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

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

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

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

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

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

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

    
175
    private DefaultDataManager dataManager = null;
176

    
177
    private FeatureStoreProvider provider = null;
178

    
179
    private DefaultFeatureIndexes indexes;
180

    
181
    private DefaultFeatureStoreTransforms transforms;
182

    
183
    DelegatedDynObject metadata;
184
    
185
    private Set metadataChildren;
186

    
187
    private Long featureCount = null;
188

    
189
    private long temporalOid = 0;
190

    
191
    private FeatureCacheProvider cache;
192

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

    
202
    public DefaultFeatureStore() {
203

    
204
    }
205

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

    
209
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
210

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

    
215
        this.dataManager = (DefaultDataManager) dataManager;
216

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

    
225
    }
226

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
412
        }
413

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

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

    
421
    }
422

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

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

    
435
        try {
436

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

    
476
                }
477

    
478
            }
479

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

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

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

    
502
    }
503

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
650
    }
651

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

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

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

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

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

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

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

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

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

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

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

    
713
    }
714

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

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

    
722
    }
723

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

    
727
    }
728

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

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

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

    
744
    }
745

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

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

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

    
769
                }
770

    
771
            }
772
    }
773

    
774
    //
775
    // ====================================================================
776
    // Edicion
777
    //
778

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

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

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

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

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

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

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

    
819
        }
820

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

    
825
        featureCount = null;
826

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1001
    private static EditableFeature lastChangedFeature = null;
1002

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1193
            case MODE_FULLEDIT:
1194
                if (hasStrongChanges && !this.allowWrite()) {
1195
                    throw new WriteNotAllowedException(getName());
1196
                }
1197
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1198
                if (hasStrongChanges) {
1199
                    validateFeatures(Feature.FINISH_EDITING);
1200
                    
1201
                    /*
1202
                     * This will throw a PerformEditingExceptionif the provider
1203
                     * does not accept the changes (for example, an invalid field name)
1204
                     */
1205
                    provider.performChanges(featureManager.getDeleted(),
1206
                        featureManager.getInserted(),
1207
                        featureManager.getUpdated(),
1208
                        featureTypeManager.getFeatureTypesChanged());
1209
                }
1210
                exitEditingMode();
1211
                updateIndexes();
1212
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1213
                break;
1214
            }
1215
        } catch (PerformEditingException pee) {
1216
            throw new WriteException(provider.getProviderName(), pee);
1217
        } catch (Exception e) {
1218
            throw new FinishEditingException(e);
1219
        }
1220
    }
1221

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

    
1240
        case MODE_APPEND:
1241
          this.provider.endAppend();
1242
          exitEditingMode();
1243
          invalidateIndexes();
1244
          this.provider.beginAppend();
1245
          hasInserts = false;
1246
          break;
1247

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

    
1267
          commands =
1268
            new DefaultFeatureCommandsStack(this, featureManager,
1269
              spatialManager, featureTypeManager);
1270
          featureCount = null;
1271
          hasStrongChanges = false;
1272
          hasInserts = false;
1273
          break;
1274
        }
1275
      } catch (Exception e) {
1276
        throw new FinishEditingException(e);
1277
      }
1278
    }
1279

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

    
1312
    public void endEditingGroup() throws NeedEditingModeException {
1313
        checkInEditingMode();
1314
        commands.endComplex();
1315
    }
1316

    
1317
    public boolean isAppendModeSupported() {
1318
        return this.provider.supportsAppendMode();
1319
    }
1320

    
1321
    public void export(DataServerExplorer explorer, String provider,
1322
        NewFeatureStoreParameters params) throws DataException {
1323

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

    
1338
            }
1339
            explorer.add(provider, params, true);
1340

    
1341
            DataManager manager = DALLocator.getDataManager();
1342
            target = (FeatureStore) manager.openStore(provider, params);
1343
            FeatureType targetType = target.getDefaultFeatureType();
1344

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

    
1376
    //
1377
    // ====================================================================
1378
    // Obtencion de datos
1379
    // getDataCollection, getFeatureCollection
1380
    //
1381

    
1382
    public DataSet getDataSet() throws DataException {
1383
        checkNotInAppendMode();
1384
        FeatureQuery query =
1385
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1386
        return new DefaultFeatureSet(this, query);
1387
    }
1388

    
1389
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1390
        checkNotInAppendMode();
1391
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1392
    }
1393

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

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

    
1405
    public FeatureSet getFeatureSet() throws DataException {
1406
        checkNotInAppendMode();
1407
        FeatureQuery query =
1408
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1409
        return new DefaultFeatureSet(this, query);
1410
    }
1411

    
1412
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1413
        throws DataException {
1414
        checkNotInAppendMode();
1415
        return new DefaultFeatureSet(this, featureQuery);
1416
    }
1417

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

    
1427
    public void accept(Visitor visitor, DataQuery dataQuery)
1428
        throws BaseException {
1429
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1430
        try {
1431
            set.accept(visitor);
1432
        } finally {
1433
            set.dispose();
1434
        }
1435
    }
1436

    
1437
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1438
        throws DataException {
1439
        DefaultFeatureType fType =
1440
            (DefaultFeatureType) this.getFeatureType(featureQuery
1441
                .getFeatureTypeId());
1442
        if ((featureQuery.getAttributeNames() != null)
1443
            && (featureQuery.getAttributeNames().length > 0)) {
1444
            return fType.getSubtype(featureQuery.getAttributeNames());
1445
        }
1446
        return fType;
1447
    }
1448

    
1449
    public void getFeatureSet(Observer observer) throws DataException {
1450
        checkNotInAppendMode();
1451
        this.getFeatureSet(null, observer);
1452
    }
1453

    
1454
    public void getFeatureSet(FeatureQuery query, Observer observer)
1455
        throws DataException {
1456
        class LoadInBackGround implements Runnable {
1457

    
1458
            private FeatureStore store;
1459
            private FeatureQuery query;
1460
            private Observer observer;
1461

    
1462
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1463
                Observer observer) {
1464
                this.store = store;
1465
                this.query = query;
1466
                this.observer = observer;
1467
            }
1468

    
1469
            void notify(FeatureStoreNotification theNotification) {
1470
                observer.update(store, theNotification);
1471
                return;
1472
            }
1473

    
1474
            public void run() {
1475
                FeatureSet set = null;
1476
                try {
1477
                    set = store.getFeatureSet(query);
1478
                    notify(new DefaultFeatureStoreNotification(store,
1479
                        FeatureStoreNotification.LOAD_FINISHED, set));
1480
                } catch (Exception e) {
1481
                    notify(new DefaultFeatureStoreNotification(store,
1482
                        FeatureStoreNotification.LOAD_FINISHED, e));
1483
                } finally {
1484
                    dispose(set);
1485
                }
1486
            }
1487
        }
1488

    
1489
        checkNotInAppendMode();
1490
        if (query == null) {
1491
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1492
        }
1493
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1494
        Thread thread = new Thread(task, "Load Feature Set in background");
1495
        thread.start();
1496
    }
1497

    
1498
    public Feature getFeatureByReference(FeatureReference reference)
1499
        throws DataException {
1500
        checkNotInAppendMode();
1501
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1502
        FeatureType featureType;
1503
        if (ref.getFeatureTypeId() == null) {
1504
            featureType = this.getDefaultFeatureType();
1505
        } else {
1506
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1507
        }
1508
        return this.getFeatureByReference(reference, featureType);
1509
    }
1510

    
1511
    public Feature getFeatureByReference(FeatureReference reference,
1512
        FeatureType featureType) throws DataException {
1513
        checkNotInAppendMode();
1514
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1515
        if (!this.transforms.isEmpty()) {
1516

    
1517
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1518

    
1519
        }
1520
        // TODO comprobar que el id es de este store
1521

    
1522
        if (this.mode == MODE_FULLEDIT) {
1523
            Feature f = featureManager.get(reference, this, featureType);
1524
            if (f != null) {
1525
                return f;
1526
            }
1527
        }
1528
    
1529
        
1530
        DefaultFeature feature =
1531
            new DefaultFeature(this,
1532
                this.provider.getFeatureProviderByReference(
1533
                    (FeatureReferenceProviderServices) reference, featureType));
1534

    
1535
        if (!this.transforms.isEmpty()) {
1536
            return this.transforms.applyTransform(feature, featureType);
1537
        }
1538
        return feature;
1539
    }
1540

    
1541
    //
1542
    // ====================================================================
1543
    // Gestion de features
1544
    //
1545

    
1546
    private FeatureType fixFeatureType(DefaultFeatureType type)
1547
        throws DataException {
1548
        FeatureType original = this.getDefaultFeatureType();
1549

    
1550
        if ((type == null) || type.equals(original)) {
1551
            return original;
1552
        } else {
1553
            if (!type.isSubtypeOf(original)) {
1554
                Iterator iter = this.getFeatureTypes().iterator();
1555
                FeatureType tmpType;
1556
                boolean found = false;
1557
                while (iter.hasNext()) {
1558
                    tmpType = (FeatureType) iter.next();
1559
                    if (type.equals(tmpType)) {
1560
                        return type;
1561

    
1562
                    } else
1563
                        if (type.isSubtypeOf(tmpType)) {
1564
                            found = true;
1565
                            original = tmpType;
1566
                            break;
1567
                        }
1568

    
1569
                }
1570
                if (!found) {
1571
                    throw new IllegalFeatureTypeException(getName());
1572
                }
1573
            }
1574
        }
1575

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

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

    
1607
            // add missing pk attributes if any
1608
            if (edOriginal.size() > 0) {
1609
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1610
                DefaultEditableFeatureType edType =
1611
                    (DefaultEditableFeatureType) original.getEditable();
1612
                edType.clear();
1613
                edType.addAll(type);
1614
                edType.addAll(edOriginal);
1615
                if (!isEditable) {
1616
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1617
                }
1618
            }
1619

    
1620
        }
1621

    
1622
        return type;
1623
    }
1624

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

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

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

    
1707
    public FeatureType getProviderDefaultFeatureType() {
1708
        return defaultFeatureType;
1709
    }
1710

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

    
1744
    public List getProviderFeatureTypes() throws DataException {
1745
        return Collections.unmodifiableList(this.featureTypes);
1746
    }
1747

    
1748
    public Feature createFeature(FeatureProvider data) throws DataException {
1749
        DefaultFeature feature = new DefaultFeature(this, data);
1750
        return feature;
1751
    }
1752

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

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

    
1777
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1778
        throws DataException {
1779
        type = this.fixFeatureType((DefaultFeatureType) type);
1780
        FeatureProvider data = this.provider.createFeatureProvider(type);
1781
        data.setNew(true);
1782
        if (type.hasOID() && (data.getOID() == null)) {
1783
            data.setOID(this.provider.createNewOID());
1784
        } else {
1785
            data.setOID(this.getTemporalOID());
1786
        }
1787
        return data;
1788

    
1789
    }
1790

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

    
1806
    public EditableFeature createNewFeature(boolean defaultValues)
1807
        throws DataException {
1808
        return this.createNewFeature(this.getDefaultFeatureType(),
1809
            defaultValues);
1810
    }
1811

    
1812
    public EditableFeature createNewFeature() throws DataException {
1813
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1814
    }
1815

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

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

    
1826
    //
1827
    // ====================================================================
1828
    // Index related methods
1829
    //
1830

    
1831
    public FeatureIndexes getIndexes() {
1832
        return this.indexes;
1833
    }
1834

    
1835
    public FeatureIndex createIndex(FeatureType featureType,
1836
        String attributeName, String indexName) throws DataException {
1837
        return createIndex(null, featureType, attributeName, indexName);
1838
    }
1839

    
1840
    public FeatureIndex createIndex(String indexTypeName,
1841
        FeatureType featureType, String attributeName, String indexName)
1842
        throws DataException {
1843

    
1844
        return createIndex(indexTypeName, featureType, attributeName,
1845
            indexName, false, null);
1846
    }
1847

    
1848
    public FeatureIndex createIndex(FeatureType featureType,
1849
        String attributeName, String indexName, Observer observer)
1850
        throws DataException {
1851
        return createIndex(null, featureType, attributeName, indexName,
1852
            observer);
1853
    }
1854

    
1855
    public FeatureIndex createIndex(String indexTypeName,
1856
        FeatureType featureType, String attributeName, String indexName,
1857
        final Observer observer) throws DataException {
1858

    
1859
        return createIndex(indexTypeName, featureType, attributeName,
1860
            indexName, true, observer);
1861
    }
1862

    
1863
    private FeatureIndex createIndex(String indexTypeName,
1864
        FeatureType featureType, String attributeName, String indexName,
1865
        boolean background, final Observer observer) throws DataException {
1866

    
1867
        checkNotInAppendMode();
1868
        FeatureIndexProviderServices index = null;
1869
        index =
1870
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1871
                featureType, indexName,
1872
                featureType.getAttributeDescriptor(attributeName));
1873

    
1874
        try {
1875
            index.fill(background, observer);
1876
        } catch (FeatureIndexException e) {
1877
            throw new InitializeException(index.getName(), e);
1878
        }
1879

    
1880
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1881
        return index;
1882
    }
1883

    
1884
    //
1885
    // ====================================================================
1886
    // Transforms related methods
1887
    //
1888

    
1889
    public FeatureStoreTransforms getTransforms() {
1890
        return this.transforms;
1891
    }
1892

    
1893
    public FeatureQuery createFeatureQuery() {
1894
        return new DefaultFeatureQuery();
1895
    }
1896

    
1897
    public DataQuery createQuery() {
1898
        return createFeatureQuery();
1899
    }
1900

    
1901
    //
1902
    // ====================================================================
1903
    // UndoRedo related methods
1904
    //
1905

    
1906
    public boolean canRedo() {
1907
        return commands.canRedo();
1908
    }
1909

    
1910
    public boolean canUndo() {
1911
        return commands.canUndo();
1912
    }
1913

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

    
1920
    public void undo(int num) throws UndoException {
1921
        for (int i = 0; i < num; i++) {
1922
            undo();
1923
        }
1924
    }
1925

    
1926
    //
1927
    // ====================================================================
1928
    // Metadata related methods
1929
    //
1930

    
1931
    public Object getMetadataID() {
1932
        return this.provider.getSourceId();
1933
    }
1934

    
1935
    public void delegate(DynObject dynObject) {
1936
        this.metadata.delegate(dynObject);
1937
    }
1938

    
1939
    public DynClass getDynClass() {
1940
        return this.metadata.getDynClass();
1941
    }
1942

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

    
1964
    public boolean hasDynValue(String name) {
1965
                if( this.transforms.hasDynValue(name) ) {
1966
                        return true;
1967
                }
1968
        return this.metadata.hasDynValue(name);
1969
    }
1970

    
1971
    public void implement(DynClass dynClass) {
1972
        this.metadata.implement(dynClass);
1973
    }
1974

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

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

    
1985
    public void setDynValue(String name, Object value)
1986
        throws DynFieldNotFoundException {
1987
                if( this.transforms.hasDynValue(name) ) {
1988
                        this.transforms.setDynValue(name, value);
1989
                        return;
1990
                }
1991
        this.metadata.setDynValue(name, value);
1992

    
1993
    }
1994

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

    
2004
    /*
2005
     * (non-Javadoc)
2006
     * 
2007
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2008
     */
2009
    public String getMetadataName() {
2010
        return this.provider.getProviderName();
2011
    }
2012

    
2013
    public FeatureTypeManager getFeatureTypeManager() {
2014
        return this.featureTypeManager;
2015
    }
2016

    
2017
    public long getFeatureCount() throws DataException {
2018
        if (featureCount == null) {
2019
            featureCount = new Long(this.provider.getFeatureCount());
2020
        }
2021
        if (this.isEditing() && !this.isAppending()) {
2022
            return featureCount.longValue()
2023
                - this.featureManager.getDeltaSize();
2024
        }
2025
        return featureCount.longValue();
2026
    }
2027

    
2028
    private Long getTemporalOID() {
2029
        return new Long(this.temporalOid++);
2030
    }
2031

    
2032
    public FeatureType getProviderFeatureType(String featureTypeId) {
2033
        if (featureTypeId == null) {
2034
            return this.defaultFeatureType;
2035
        }
2036
        FeatureType type;
2037
        Iterator iter = this.featureTypes.iterator();
2038
        while (iter.hasNext()) {
2039
            type = (FeatureType) iter.next();
2040
            if (type.getId().equals(featureTypeId)) {
2041
                return type;
2042
            }
2043
        }
2044
        return null;
2045
    }
2046

    
2047
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2048
        return ((DefaultFeature) feature).getData();
2049
    }
2050

    
2051
    public DataStore getStore() {
2052
        return this;
2053
    }
2054

    
2055
    public FeatureStore getFeatureStore() {
2056
        return this;
2057
    }
2058

    
2059
    public void createCache(String name, DynObject parameters)
2060
        throws DataException {
2061
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2062
        if (cache == null) {
2063
            throw new CreateException("FeaureCacheProvider", null);
2064
        }
2065
        cache.apply(this, provider);
2066
        provider = cache;
2067

    
2068
        featureCount = null;
2069
    }
2070

    
2071
    public FeatureCache getCache() {
2072
        return cache;
2073
    }
2074

    
2075
    public void clear() {
2076
        if (metadata != null) {
2077
            metadata.clear();
2078
        }
2079
    }
2080

    
2081
    public String getName() {
2082
        return this.provider.getName();
2083
    }
2084

    
2085
    public String getFullName() {
2086
        return this.provider.getFullName();
2087
    }
2088

    
2089
    public String getProviderName() {
2090
        return this.provider.getProviderName();
2091
    }
2092

    
2093
    public boolean isKnownEnvelope() {
2094
        return this.provider.isKnownEnvelope();
2095
    }
2096

    
2097
    public boolean hasRetrievedFeaturesLimit() {
2098
        return this.provider.hasRetrievedFeaturesLimit();
2099
    }
2100

    
2101
    public int getRetrievedFeaturesLimit() {
2102
        return this.provider.getRetrievedFeaturesLimit();
2103
    }
2104

    
2105
    public Interval getInterval() {  
2106
        return this.provider.getInterval();
2107
    }
2108

    
2109
    public Collection getTimes() {      
2110
        return this.provider.getTimes();
2111
    }
2112

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