Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2059 / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 39309

History | View | Annotate | Download (68.3 KB)

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

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27

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

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

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

    
45
import org.gvsig.fmap.dal.DALLocator;
46
import org.gvsig.fmap.dal.DataManager;
47
import org.gvsig.fmap.dal.DataQuery;
48
import org.gvsig.fmap.dal.DataServerExplorer;
49
import org.gvsig.fmap.dal.DataSet;
50
import org.gvsig.fmap.dal.DataStore;
51
import org.gvsig.fmap.dal.DataStoreNotification;
52
import org.gvsig.fmap.dal.DataStoreParameters;
53
import org.gvsig.fmap.dal.exception.CloseException;
54
import org.gvsig.fmap.dal.exception.CreateException;
55
import org.gvsig.fmap.dal.exception.DataException;
56
import org.gvsig.fmap.dal.exception.InitializeException;
57
import org.gvsig.fmap.dal.exception.OpenException;
58
import org.gvsig.fmap.dal.exception.ReadException;
59
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
60
import org.gvsig.fmap.dal.feature.EditableFeature;
61
import org.gvsig.fmap.dal.feature.EditableFeatureType;
62
import org.gvsig.fmap.dal.feature.Feature;
63
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
64
import org.gvsig.fmap.dal.feature.FeatureCache;
65
import org.gvsig.fmap.dal.feature.FeatureIndex;
66
import org.gvsig.fmap.dal.feature.FeatureIndexes;
67
import org.gvsig.fmap.dal.feature.FeatureLocks;
68
import org.gvsig.fmap.dal.feature.FeatureQuery;
69
import org.gvsig.fmap.dal.feature.FeatureReference;
70
import org.gvsig.fmap.dal.feature.FeatureReferenceSelection;
71
import org.gvsig.fmap.dal.feature.FeatureSelection;
72
import org.gvsig.fmap.dal.feature.FeatureSet;
73
import org.gvsig.fmap.dal.feature.FeatureStore;
74
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
75
import org.gvsig.fmap.dal.feature.FeatureStoreTransforms;
76
import org.gvsig.fmap.dal.feature.FeatureType;
77
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
78
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
79
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
80
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
81
import org.gvsig.fmap.dal.feature.exception.DataExportException;
82
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
83
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
84
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
85
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
86
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
87
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
88
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
89
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
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
            if (!this.defaultFeatureType.getId().equals(
483
                state.getString("defaultFeatureTypeId"))) {
484

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

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

    
499
    }
500

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
647
    }
648

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

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

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

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

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

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

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

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

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

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

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

    
710
    }
711

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

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

    
719
    }
720

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

    
724
    }
725

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

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

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

    
741
    }
742

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

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

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

    
766
                }
767

    
768
            }
769
    }
770

    
771
    //
772
    // ====================================================================
773
    // Edicion
774
    //
775

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

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

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

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

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

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

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

    
816
        }
817

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

    
822
        featureCount = null;
823

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
998
    private static EditableFeature lastChangedFeature = null;
999

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1212
    public void beginEditingGroup(String description)
1213
        throws NeedEditingModeException {
1214
        checkInEditingMode();
1215
        commands.startComplex(description);
1216
    }
1217

    
1218
    public void endEditingGroup() throws NeedEditingModeException {
1219
        checkInEditingMode();
1220
        commands.endComplex();
1221
    }
1222

    
1223
    public boolean isAppendModeSupported() {
1224
        return this.provider.supportsAppendMode();
1225
    }
1226

    
1227
    public void export(DataServerExplorer explorer, String provider,
1228
        NewFeatureStoreParameters params) throws DataException {
1229

    
1230
        if (this.getFeatureTypes().size() != 1) {
1231
            throw new NotYetImplemented(
1232
                "export whith more than one type not yet implemented");
1233
        }
1234
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1235
        FeatureStore target = null;
1236
        FeatureSet features = null;
1237
        DisposableIterator iterator = null;
1238
        try {
1239
            FeatureType type = this.getDefaultFeatureType();
1240
            if ((params.getDefaultFeatureType() == null)
1241
                || (params.getDefaultFeatureType().size() == 0)) {
1242
                params.setDefaultFeatureType(type.getEditable());
1243

    
1244
            }
1245
            explorer.add(provider, params, true);
1246

    
1247
            DataManager manager = DALLocator.getDataManager();
1248
            target = (FeatureStore) manager.openStore(provider, params);
1249
            FeatureType targetType = target.getDefaultFeatureType();
1250

    
1251
            target.edit(MODE_APPEND);
1252
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1253
            if (featureSelection.getSize() > 0) {
1254
                features = this.getFeatureSelection();
1255
            } else {
1256
                if ((pk != null) && (pk.length > 0)) {
1257
                    FeatureQuery query = createFeatureQuery();
1258
                    for (int i = 0; i < pk.length; i++) {
1259
                        query.getOrder().add(pk[i].getName(), true);
1260
                    }
1261
                    features = this.getFeatureSet(query);
1262
                } else {
1263
                    features = this.getFeatureSet();
1264
                }
1265
            }
1266
            iterator = features.fastIterator();
1267
            while (iterator.hasNext()) {
1268
                DefaultFeature feature = (DefaultFeature) iterator.next();
1269
                target.insert(target.createNewFeature(targetType, feature));
1270
            }
1271
            target.finishEditing();
1272
            target.dispose();
1273
        } catch (Exception e) {
1274
            throw new DataExportException(e, params.toString());
1275
        } finally {
1276
            dispose(iterator);
1277
            dispose(features);
1278
            dispose(target);
1279
        }
1280
    }
1281

    
1282
    //
1283
    // ====================================================================
1284
    // Obtencion de datos
1285
    // getDataCollection, getFeatureCollection
1286
    //
1287

    
1288
    public DataSet getDataSet() throws DataException {
1289
        checkNotInAppendMode();
1290
        FeatureQuery query =
1291
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1292
        return new DefaultFeatureSet(this, query);
1293
    }
1294

    
1295
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1296
        checkNotInAppendMode();
1297
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1298
    }
1299

    
1300
    public void getDataSet(Observer observer) throws DataException {
1301
        checkNotInAppendMode();
1302
        this.getFeatureSet(null, observer);
1303
    }
1304

    
1305
    public void getDataSet(DataQuery dataQuery, Observer observer)
1306
        throws DataException {
1307
        checkNotInAppendMode();
1308
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1309
    }
1310

    
1311
    public FeatureSet getFeatureSet() throws DataException {
1312
        checkNotInAppendMode();
1313
        FeatureQuery query =
1314
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1315
        return new DefaultFeatureSet(this, query);
1316
    }
1317

    
1318
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1319
        throws DataException {
1320
        checkNotInAppendMode();
1321
        return new DefaultFeatureSet(this, featureQuery);
1322
    }
1323

    
1324
    public void accept(Visitor visitor) throws BaseException {
1325
        FeatureSet set = getFeatureSet();
1326
        try {
1327
            set.accept(visitor);
1328
        } finally {
1329
            set.dispose();
1330
        }
1331
    }
1332

    
1333
    public void accept(Visitor visitor, DataQuery dataQuery)
1334
        throws BaseException {
1335
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1336
        try {
1337
            set.accept(visitor);
1338
        } finally {
1339
            set.dispose();
1340
        }
1341
    }
1342

    
1343
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1344
        throws DataException {
1345
        DefaultFeatureType fType =
1346
            (DefaultFeatureType) this.getFeatureType(featureQuery
1347
                .getFeatureTypeId());
1348
        if ((featureQuery.getAttributeNames() != null)
1349
            && (featureQuery.getAttributeNames().length > 0)) {
1350
            return fType.getSubtype(featureQuery.getAttributeNames());
1351
        }
1352
        return fType;
1353
    }
1354

    
1355
    public void getFeatureSet(Observer observer) throws DataException {
1356
        checkNotInAppendMode();
1357
        this.getFeatureSet(null, observer);
1358
    }
1359

    
1360
    public void getFeatureSet(FeatureQuery query, Observer observer)
1361
        throws DataException {
1362
        class LoadInBackGround implements Runnable {
1363

    
1364
            private FeatureStore store;
1365
            private FeatureQuery query;
1366
            private Observer observer;
1367

    
1368
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1369
                Observer observer) {
1370
                this.store = store;
1371
                this.query = query;
1372
                this.observer = observer;
1373
            }
1374

    
1375
            void notify(FeatureStoreNotification theNotification) {
1376
                observer.update(store, theNotification);
1377
                return;
1378
            }
1379

    
1380
            public void run() {
1381
                FeatureSet set = null;
1382
                try {
1383
                    set = store.getFeatureSet(query);
1384
                    notify(new DefaultFeatureStoreNotification(store,
1385
                        FeatureStoreNotification.LOAD_FINISHED, set));
1386
                } catch (Exception e) {
1387
                    notify(new DefaultFeatureStoreNotification(store,
1388
                        FeatureStoreNotification.LOAD_FINISHED, e));
1389
                } finally {
1390
                    dispose(set);
1391
                }
1392
            }
1393
        }
1394

    
1395
        checkNotInAppendMode();
1396
        if (query == null) {
1397
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1398
        }
1399
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1400
        Thread thread = new Thread(task, "Load Feature Set in background");
1401
        thread.start();
1402
    }
1403

    
1404
    public Feature getFeatureByReference(FeatureReference reference)
1405
        throws DataException {
1406
        checkNotInAppendMode();
1407
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1408
        FeatureType featureType;
1409
        if (ref.getFeatureTypeId() == null) {
1410
            featureType = this.getDefaultFeatureType();
1411
        } else {
1412
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1413
        }
1414
        return this.getFeatureByReference(reference, featureType);
1415
    }
1416

    
1417
    public Feature getFeatureByReference(FeatureReference reference,
1418
        FeatureType featureType) throws DataException {
1419
        checkNotInAppendMode();
1420
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1421
        if (!this.transforms.isEmpty()) {
1422

    
1423
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1424

    
1425
        }
1426
        // TODO comprobar que el id es de este store
1427

    
1428
        if (this.mode == MODE_FULLEDIT) {
1429
            Feature f = featureManager.get(reference, this, featureType);
1430
            if (f != null) {
1431
                return f;
1432
            }
1433
        }
1434
    
1435
        
1436
        DefaultFeature feature =
1437
            new DefaultFeature(this,
1438
                this.provider.getFeatureProviderByReference(
1439
                    (FeatureReferenceProviderServices) reference, featureType));
1440

    
1441
        if (!this.transforms.isEmpty()) {
1442
            return this.transforms.applyTransform(feature, featureType);
1443
        }
1444
        return feature;
1445
    }
1446

    
1447
    //
1448
    // ====================================================================
1449
    // Gestion de features
1450
    //
1451

    
1452
    private FeatureType fixFeatureType(DefaultFeatureType type)
1453
        throws DataException {
1454
        FeatureType original = this.getDefaultFeatureType();
1455

    
1456
        if ((type == null) || type.equals(original)) {
1457
            return original;
1458
        } else {
1459
            if (!type.isSubtypeOf(original)) {
1460
                Iterator iter = this.getFeatureTypes().iterator();
1461
                FeatureType tmpType;
1462
                boolean found = false;
1463
                while (iter.hasNext()) {
1464
                    tmpType = (FeatureType) iter.next();
1465
                    if (type.equals(tmpType)) {
1466
                        return type;
1467

    
1468
                    } else
1469
                        if (type.isSubtypeOf(tmpType)) {
1470
                            found = true;
1471
                            original = tmpType;
1472
                            break;
1473
                        }
1474

    
1475
                }
1476
                if (!found) {
1477
                    throw new IllegalFeatureTypeException(getName());
1478
                }
1479
            }
1480
        }
1481

    
1482
        // Checks that type has all fields of pk
1483
        // else add the missing attributes at the end.
1484
        if (!original.hasOID()) {
1485
            // Gets original pk attributes
1486
            DefaultEditableFeatureType edOriginal =
1487
                (DefaultEditableFeatureType) original.getEditable();
1488
            FeatureAttributeDescriptor orgAttr;
1489
            Iterator edOriginalIter = edOriginal.iterator();
1490
            while (edOriginalIter.hasNext()) {
1491
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1492
                if (!orgAttr.isPrimaryKey()) {
1493
                    edOriginalIter.remove();
1494
                }
1495
            }
1496

    
1497
            // Checks if all pk attributes are in type
1498
            Iterator typeIterator;
1499
            edOriginalIter = edOriginal.iterator();
1500
            FeatureAttributeDescriptor attr;
1501
            while (edOriginalIter.hasNext()) {
1502
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1503
                typeIterator = type.iterator();
1504
                while (typeIterator.hasNext()) {
1505
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1506
                    if (attr.getName().equals(orgAttr.getName())) {
1507
                        edOriginalIter.remove();
1508
                        break;
1509
                    }
1510
                }
1511
            }
1512

    
1513
            // add missing pk attributes if any
1514
            if (edOriginal.size() > 0) {
1515
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1516
                DefaultEditableFeatureType edType =
1517
                    (DefaultEditableFeatureType) original.getEditable();
1518
                edType.clear();
1519
                edType.addAll(type);
1520
                edType.addAll(edOriginal);
1521
                if (!isEditable) {
1522
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1523
                }
1524
            }
1525

    
1526
        }
1527

    
1528
        return type;
1529
    }
1530

    
1531
    public void validateFeatures(int mode) throws DataException {
1532
        FeatureSet collection = null;
1533
        DisposableIterator iter = null;
1534
        try {
1535
            checkNotInAppendMode();
1536
            collection = this.getFeatureSet();
1537
            iter = collection.fastIterator();
1538
            long previousVersionOfUpdate = currentVersionOfUpdate();
1539
            while (iter.hasNext()) {
1540
                ((DefaultFeature) iter.next()).validate(mode);
1541
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1542
                    throw new ConcurrentDataModificationException(getName());
1543
                }
1544
            }
1545
        } catch (Exception e) {
1546
            throw new ValidateFeaturesException(e, getName());
1547
        } finally {
1548
            dispose(iter);
1549
            dispose(collection);
1550
        }
1551
    }
1552

    
1553
    public FeatureType getDefaultFeatureType() throws DataException {
1554
        try {
1555
            if (isEditing()) {
1556
                FeatureType auxFeatureType =
1557
                    featureTypeManager.getType(defaultFeatureType.getId());
1558
                if (auxFeatureType != null) {
1559
                    return auxFeatureType;
1560
                }
1561
            }
1562
            FeatureType type = this.transforms.getDefaultFeatureType();
1563
            if (type != null) {
1564
                return type;
1565
            }
1566
            return defaultFeatureType;
1567
        } catch (Exception e) {
1568
            throw new GetFeatureTypeException(e, getName());
1569
        }
1570
    }
1571

    
1572
    public FeatureType getFeatureType(String featureTypeId)
1573
        throws DataException {
1574
        if (featureTypeId == null) {
1575
            return this.getDefaultFeatureType();
1576
        }
1577
        try {
1578
            if (isEditing()) {
1579
                FeatureType auxFeatureType =
1580
                    featureTypeManager.getType(featureTypeId);
1581
                if (auxFeatureType != null) {
1582
                    return auxFeatureType;
1583
                }
1584
            }
1585
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1586
            if (type != null) {
1587
                return type;
1588
            }
1589
            Iterator iter = this.featureTypes.iterator();
1590
            while (iter.hasNext()) {
1591
                type = (FeatureType) iter.next();
1592
                if (type.getId().equals(featureTypeId)) {
1593
                    return type;
1594
                }
1595
            }
1596
            return null;
1597
        } catch (Exception e) {
1598
            throw new GetFeatureTypeException(e, getName());
1599
        }
1600
    }
1601

    
1602
    public FeatureType getProviderDefaultFeatureType() {
1603
        return defaultFeatureType;
1604
    }
1605

    
1606
    public List getFeatureTypes() throws DataException {
1607
        try {
1608
            List types;
1609
            if (isEditing()) {
1610
                types = new ArrayList();
1611
                Iterator it = featureTypes.iterator();
1612
                while (it.hasNext()) {
1613
                    FeatureType type = (FeatureType) it.next();
1614
                    FeatureType typeaux =
1615
                        featureTypeManager.getType(type.getId());
1616
                    if (typeaux != null) {
1617
                        types.add(typeaux);
1618
                    } else {
1619
                        types.add(type);
1620
                    }
1621
                }
1622
                it = featureTypeManager.newsIterator();
1623
                while (it.hasNext()) {
1624
                    FeatureType type = (FeatureType) it.next();
1625
                    types.add(type);
1626
                }
1627
            } else {
1628
                types = this.transforms.getFeatureTypes();
1629
                if (types == null) {
1630
                    types = featureTypes;
1631
                }
1632
            }
1633
            return Collections.unmodifiableList(types);
1634
        } catch (Exception e) {
1635
            throw new GetFeatureTypeException(e, getName());
1636
        }
1637
    }
1638

    
1639
    public List getProviderFeatureTypes() throws DataException {
1640
        return Collections.unmodifiableList(this.featureTypes);
1641
    }
1642

    
1643
    public Feature createFeature(FeatureProvider data) throws DataException {
1644
        DefaultFeature feature = new DefaultFeature(this, data);
1645
        return feature;
1646
    }
1647

    
1648
    public Feature createFeature(FeatureProvider data, FeatureType type)
1649
        throws DataException {
1650
        // FIXME: falta por implementar
1651
        // Comprobar si es un subtipo del feature de data
1652
        // y construir un feature usando el subtipo.
1653
        // Probablemente requiera generar una copia del data.
1654
        throw new NotYetImplemented();
1655
    }
1656

    
1657
    public EditableFeature createNewFeature(FeatureType type,
1658
        Feature defaultValues) throws DataException {
1659
        try {
1660
            FeatureProvider data = createNewFeatureProvider(type);
1661
            DefaultEditableFeature feature =
1662
                new DefaultEditableFeature(this, data);
1663
            feature.initializeValues(defaultValues);
1664
            data.setNew(true);
1665
            
1666
            return feature;
1667
        } catch (Exception e) {
1668
            throw new CreateFeatureException(e, getName());
1669
        }
1670
    }
1671

    
1672
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1673
        throws DataException {
1674
        type = this.fixFeatureType((DefaultFeatureType) type);
1675
        FeatureProvider data = this.provider.createFeatureProvider(type);
1676
        data.setNew(true);
1677
        if (type.hasOID() && (data.getOID() == null)) {
1678
            data.setOID(this.provider.createNewOID());
1679
        } else {
1680
            data.setOID(this.getTemporalOID());
1681
        }
1682
        return data;
1683

    
1684
    }
1685

    
1686
    public EditableFeature createNewFeature(FeatureType type,
1687
        boolean defaultValues) throws DataException {
1688
        try {
1689
            FeatureProvider data = createNewFeatureProvider(type);
1690
            DefaultEditableFeature feature =
1691
                new DefaultEditableFeature(this, data);
1692
            if (defaultValues) {
1693
                feature.initializeValues();
1694
            }
1695
            return feature;
1696
        } catch (Exception e) {
1697
            throw new CreateFeatureException(e, getName());
1698
        }
1699
    }
1700

    
1701
    public EditableFeature createNewFeature(boolean defaultValues)
1702
        throws DataException {
1703
        return this.createNewFeature(this.getDefaultFeatureType(),
1704
            defaultValues);
1705
    }
1706

    
1707
    public EditableFeature createNewFeature() throws DataException {
1708
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1709
    }
1710

    
1711
    public EditableFeatureType createFeatureType() {
1712
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1713
        return ftype;
1714
    }
1715

    
1716
    public EditableFeatureType createFeatureType(String id) {
1717
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1718
        return ftype;
1719
    }
1720

    
1721
    //
1722
    // ====================================================================
1723
    // Index related methods
1724
    //
1725

    
1726
    public FeatureIndexes getIndexes() {
1727
        return this.indexes;
1728
    }
1729

    
1730
    public FeatureIndex createIndex(FeatureType featureType,
1731
        String attributeName, String indexName) throws DataException {
1732
        return createIndex(null, featureType, attributeName, indexName);
1733
    }
1734

    
1735
    public FeatureIndex createIndex(String indexTypeName,
1736
        FeatureType featureType, String attributeName, String indexName)
1737
        throws DataException {
1738

    
1739
        return createIndex(indexTypeName, featureType, attributeName,
1740
            indexName, false, null);
1741
    }
1742

    
1743
    public FeatureIndex createIndex(FeatureType featureType,
1744
        String attributeName, String indexName, Observer observer)
1745
        throws DataException {
1746
        return createIndex(null, featureType, attributeName, indexName,
1747
            observer);
1748
    }
1749

    
1750
    public FeatureIndex createIndex(String indexTypeName,
1751
        FeatureType featureType, String attributeName, String indexName,
1752
        final Observer observer) throws DataException {
1753

    
1754
        return createIndex(indexTypeName, featureType, attributeName,
1755
            indexName, true, observer);
1756
    }
1757

    
1758
    private FeatureIndex createIndex(String indexTypeName,
1759
        FeatureType featureType, String attributeName, String indexName,
1760
        boolean background, final Observer observer) throws DataException {
1761

    
1762
        checkNotInAppendMode();
1763
        FeatureIndexProviderServices index = null;
1764
        index =
1765
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1766
                featureType, indexName,
1767
                featureType.getAttributeDescriptor(attributeName));
1768

    
1769
        try {
1770
            index.fill(background, observer);
1771
        } catch (FeatureIndexException e) {
1772
            throw new InitializeException(index.getName(), e);
1773
        }
1774

    
1775
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1776
        return index;
1777
    }
1778

    
1779
    //
1780
    // ====================================================================
1781
    // Transforms related methods
1782
    //
1783

    
1784
    public FeatureStoreTransforms getTransforms() {
1785
        return this.transforms;
1786
    }
1787

    
1788
    public FeatureQuery createFeatureQuery() {
1789
        return new DefaultFeatureQuery();
1790
    }
1791

    
1792
    public DataQuery createQuery() {
1793
        return createFeatureQuery();
1794
    }
1795

    
1796
    //
1797
    // ====================================================================
1798
    // UndoRedo related methods
1799
    //
1800

    
1801
    public boolean canRedo() {
1802
        return commands.canRedo();
1803
    }
1804

    
1805
    public boolean canUndo() {
1806
        return commands.canUndo();
1807
    }
1808

    
1809
    public void redo(int num) throws RedoException {
1810
        for (int i = 0; i < num; i++) {
1811
            redo();
1812
        }
1813
    }
1814

    
1815
    public void undo(int num) throws UndoException {
1816
        for (int i = 0; i < num; i++) {
1817
            undo();
1818
        }
1819
    }
1820

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

    
1826
    public Object getMetadataID() {
1827
        return this.provider.getSourceId();
1828
    }
1829

    
1830
    public void delegate(DynObject dynObject) {
1831
        this.metadata.delegate(dynObject);
1832
    }
1833

    
1834
    public DynClass getDynClass() {
1835
        return this.metadata.getDynClass();
1836
    }
1837

    
1838
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1839
                if( this.transforms.hasDynValue(name) ) {
1840
                        return this.transforms.getDynValue(name);
1841
                }
1842
                if (this.metadata.hasDynValue(name)) {
1843
                        return this.metadata.getDynValue(name);
1844
                }
1845
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1846
                        return this.provider.getProviderName();
1847
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1848
                        return this.provider.getSourceId();
1849
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1850
                        try {
1851
                                return this.getDefaultFeatureType();
1852
                        } catch (DataException e) {
1853
                                return null;
1854
                        }
1855
                }
1856
                return this.metadata.getDynValue(name);
1857
        }
1858

    
1859
    public boolean hasDynValue(String name) {
1860
                if( this.transforms.hasDynValue(name) ) {
1861
                        return true;
1862
                }
1863
        return this.metadata.hasDynValue(name);
1864
    }
1865

    
1866
    public void implement(DynClass dynClass) {
1867
        this.metadata.implement(dynClass);
1868
    }
1869

    
1870
    public Object invokeDynMethod(String name, DynObject context)
1871
        throws DynMethodException {
1872
        return this.metadata.invokeDynMethod(this, name, context);
1873
    }
1874

    
1875
    public Object invokeDynMethod(int code, DynObject context)
1876
        throws DynMethodException {
1877
        return this.metadata.invokeDynMethod(this, code, context);
1878
    }
1879

    
1880
    public void setDynValue(String name, Object value)
1881
        throws DynFieldNotFoundException {
1882
                if( this.transforms.hasDynValue(name) ) {
1883
                        this.transforms.setDynValue(name, value);
1884
                        return;
1885
                }
1886
        this.metadata.setDynValue(name, value);
1887

    
1888
    }
1889

    
1890
    /*
1891
     * (non-Javadoc)
1892
     * 
1893
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1894
     */
1895
    public Set getMetadataChildren() {
1896
        return this.metadataChildren;
1897
    }
1898

    
1899
    /*
1900
     * (non-Javadoc)
1901
     * 
1902
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1903
     */
1904
    public String getMetadataName() {
1905
        return this.provider.getProviderName();
1906
    }
1907

    
1908
    public FeatureTypeManager getFeatureTypeManager() {
1909
        return this.featureTypeManager;
1910
    }
1911

    
1912
    public long getFeatureCount() throws DataException {
1913
        if (featureCount == null) {
1914
            featureCount = new Long(this.provider.getFeatureCount());
1915
        }
1916
        if (this.isEditing() && !this.isAppending()) {
1917
            return featureCount.longValue()
1918
                - this.featureManager.getDeltaSize();
1919
        }
1920
        return featureCount.longValue();
1921
    }
1922

    
1923
    private Long getTemporalOID() {
1924
        return new Long(this.temporalOid++);
1925
    }
1926

    
1927
    public FeatureType getProviderFeatureType(String featureTypeId) {
1928
        if (featureTypeId == null) {
1929
            return this.defaultFeatureType;
1930
        }
1931
        FeatureType type;
1932
        Iterator iter = this.featureTypes.iterator();
1933
        while (iter.hasNext()) {
1934
            type = (FeatureType) iter.next();
1935
            if (type.getId().equals(featureTypeId)) {
1936
                return type;
1937
            }
1938
        }
1939
        return null;
1940
    }
1941

    
1942
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1943
        return ((DefaultFeature) feature).getData();
1944
    }
1945

    
1946
    public DataStore getStore() {
1947
        return this;
1948
    }
1949

    
1950
    public FeatureStore getFeatureStore() {
1951
        return this;
1952
    }
1953

    
1954
    public void createCache(String name, DynObject parameters)
1955
        throws DataException {
1956
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1957
        if (cache == null) {
1958
            throw new CreateException("FeaureCacheProvider", null);
1959
        }
1960
        cache.apply(this, provider);
1961
        provider = cache;
1962

    
1963
        featureCount = null;
1964
    }
1965

    
1966
    public FeatureCache getCache() {
1967
        return cache;
1968
    }
1969

    
1970
    public void clear() {
1971
        if (metadata != null) {
1972
            metadata.clear();
1973
        }
1974
    }
1975

    
1976
    public String getName() {
1977
        return this.provider.getName();
1978
    }
1979

    
1980
    public String getFullName() {
1981
        return this.provider.getFullName();
1982
    }
1983

    
1984
    public String getProviderName() {
1985
        return this.provider.getProviderName();
1986
    }
1987

    
1988
    public boolean isKnownEnvelope() {
1989
        return this.provider.isKnownEnvelope();
1990
    }
1991

    
1992
    public boolean hasRetrievedFeaturesLimit() {
1993
        return this.provider.hasRetrievedFeaturesLimit();
1994
    }
1995

    
1996
    public int getRetrievedFeaturesLimit() {
1997
        return this.provider.getRetrievedFeaturesLimit();
1998
    }
1999

    
2000
    public Interval getInterval() {  
2001
        return this.provider.getInterval();
2002
    }
2003

    
2004
    public Collection getTimes() {      
2005
        return this.provider.getTimes();
2006
    }
2007

    
2008
    public Collection getTimes(Interval interval) {       
2009
        return this.provider.getTimes(interval);
2010
    }
2011
}