Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 37496

History | View | Annotate | Download (66.8 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.Set;
39
import java.util.Map.Entry;
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
            return this.spatialManager.getEnvelope();
347
        }
348
        return this.provider.getEnvelope();
349
    }
350

    
351
    /**
352
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
353
     */
354
    public IProjection getSRSDefaultGeometry() throws DataException {
355
        return this.getDefaultFeatureType().getDefaultSRS();
356
    }
357

    
358
    public FeatureSelection createDefaultFeatureSelection()
359
        throws DataException {
360
        return new DefaultFeatureSelection(this);
361
    }
362

    
363
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
364
        throws DataException {
365
        if (type.hasOID()) {
366
            return new DefaultFeatureProvider(type,
367
                this.provider.createNewOID());
368
        }
369
        return new DefaultFeatureProvider(type);
370
    }
371

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

    
406
        }
407

    
408
        if (evaluatedAttr.isEmpty()) {
409
            evaluatedAttr = null;
410
        }
411

    
412
        state.set("evaluatedAttributes", evaluatedAttr);
413
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
414

    
415
    }
416

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

    
426
        DataStoreParameters params =
427
            (DataStoreParameters) state.get("parameters");
428

    
429
        try {
430

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

    
470
                }
471

    
472
            }
473

    
474
            String defFTypeid = state.getString("defaultFeatureTypeId");
475
            FeatureType ftype = null;
476
            if (!this.defaultFeatureType.getId().equals(
477
                state.getString("defaultFeatureTypeId"))) {
478

    
479
                ftype = getFeatureType(defFTypeid);
480
                if (ftype == null) {
481
                    throw new PersistenceCantFindDefaultFeatureTypeException(
482
                        this.getName(), defFTypeid);
483
                }
484
                this.defaultFeatureType = ftype;
485
            }
486

    
487
        } catch (InitializeException e) {
488
            throw new PersistenceException(e);
489
        } catch (DataException e) {
490
            throw new PersistenceException(e);
491
        }
492

    
493
    }
494

    
495
    public static void registerPersistenceDefinition() {
496
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
497
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
498
            DynStruct definition =
499
                manager.addDefinition(DefaultFeatureStore.class,
500
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
501
                        + " Persistent definition", null, null);
502
            definition.addDynFieldString("dataStoreName").setMandatory(true)
503
                .setPersistent(true);
504

    
505
            definition.addDynFieldObject("parameters")
506
                .setClassOfValue(DynObject.class).setMandatory(true)
507
                .setPersistent(true);
508

    
509
            definition.addDynFieldObject("selection")
510
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
511
                .setPersistent(true);
512

    
513
            definition.addDynFieldObject("transforms")
514
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
515
                .setMandatory(true).setPersistent(true);
516

    
517
            definition.addDynFieldMap("evaluatedAttributes")
518
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
519
                .setMandatory(false).setPersistent(true);
520

    
521
            definition.addDynFieldString("defaultFeatureTypeId")
522
                .setMandatory(true).setPersistent(true);
523
        }
524
    }
525

    
526
    public static void registerMetadataDefinition() throws MetadataException {
527
        MetadataManager manager = MetadataLocator.getMetadataManager();
528
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
529
            DynStruct metadataDefinition =
530
                manager.addDefinition(METADATA_DEFINITION_NAME, null);
531
            metadataDefinition.extend(manager
532
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
533
        }
534
    }
535

    
536
    //
537
    // ====================================================================
538
    // Gestion de la seleccion
539
    //
540

    
541
    public void setSelection(DataSet selection) throws DataException {
542
        this.setSelection((FeatureSet) selection);
543
    }
544

    
545
    public DataSet createSelection() throws DataException {
546
        return createFeatureSelection();
547
    }
548

    
549
    public DataSet getSelection() throws DataException {
550
        return this.getFeatureSelection();
551
    }
552

    
553
    public void setSelection(FeatureSet selection) throws DataException {
554
        setSelection(selection, true);
555
    }
556

    
557
    /**
558
     * @see #setSelection(FeatureSet)
559
     * @param undoable
560
     *            if the action must be undoable
561
     */
562
    public void setSelection(FeatureSet selection, boolean undoable)
563
        throws DataException {
564
        if (selection == null) {
565
            if (undoable) {
566
                throw new SelectionNotAllowedException(getName());
567
            }
568

    
569
        } else {
570
            if (selection.equals(this.selection)) {
571
                return;
572
            }
573
            if (!selection.isFromStore(this)) {
574
                throw new SelectionNotAllowedException(getName());
575
            }
576
        }
577

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

    
616
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
617
    }
618

    
619
    public FeatureSelection createFeatureSelection() throws DataException {
620
        return this.provider.createFeatureSelection();
621
    }
622

    
623
    public FeatureSelection getFeatureSelection() throws DataException {
624
        if (selection == null) {
625
            this.selection = createFeatureSelection();
626
            this.selection.addObserver(this);
627
        }
628
        return selection;
629
    }
630

    
631
    //
632
    // ====================================================================
633
    // Gestion de notificaciones
634
    //
635

    
636
    public void notifyChange(String notification) {
637
        if (delegateObservable != null) {
638
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
639
        }
640

    
641
    }
642

    
643
    public void notifyChange(String notification, FeatureProvider data) {
644
        try {
645
            notifyChange(notification, createFeature(data));
646
        } catch (DataException ex) {
647
            LOG.error("Error notifying about the notification: " + notification
648
                + ", with the data: " + data, ex);
649
        }
650
    }
651

    
652
    public void notifyChange(String notification, Feature feature) {
653
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
654
            feature));
655
    }
656

    
657
    public void notifyChange(String notification, Command command) {
658
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
659
            command));
660
    }
661

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

    
667
    public void notifyChange(FeatureStoreNotification storeNotification) {
668
        delegateObservable.notifyObservers(storeNotification);
669
    }
670

    
671
    public void notifyChange(String notification, Resource resource) {
672
        notifyChange(new DefaultFeatureStoreNotification(this,
673
            DataStoreNotification.RESOURCE_CHANGED));
674
    }
675

    
676
    //
677
    // ====================================================================
678
    // Gestion de bloqueos
679
    //
680

    
681
    public boolean isLocksSupported() {
682
        return this.provider.isLocksSupported();
683
    }
684

    
685
    public FeatureLocks getLocks() throws DataException {
686
        if (!this.provider.isLocksSupported()) {
687
            LOG.warn("Locks not supporteds");
688
            return null;
689
        }
690
        if (locks == null) {
691
            this.locks = this.provider.createFeatureLocks();
692
        }
693
        return locks;
694
    }
695

    
696
    //
697
    // ====================================================================
698
    // Interface Observable
699
    //
700

    
701
    public void disableNotifications() {
702
        this.delegateObservable.disableNotifications();
703

    
704
    }
705

    
706
    public void enableNotifications() {
707
        this.delegateObservable.enableNotifications();
708
    }
709

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

    
713
    }
714

    
715
    public void endComplexNotification() {
716
        this.delegateObservable.endComplexNotification();
717

    
718
    }
719

    
720
    public void addObserver(Observer observer) {
721
        if (delegateObservable != null) {
722
            this.delegateObservable.addObserver(observer);
723
        }
724
    }
725

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

    
732
    public void deleteObservers() {
733
        this.delegateObservable.deleteObservers();
734

    
735
    }
736

    
737
    //
738
    // ====================================================================
739
    // Interface Observer
740
    //
741
    // Usado para observar:
742
    // - su seleccion
743
    // - sus bloqueos
744
    // - sus recursos
745
    //
746

    
747
    public void update(Observable observable, Object notification) {
748
        if (observable instanceof FeatureSet) {
749
            if (observable == this.selection) {
750
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
751
            } else
752
                if (observable == this.locks) {
753
                    this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
754
                }
755

    
756
        } else
757
            if (observable instanceof FeatureStoreProvider) {
758
                if (observable == this.provider) {
759

    
760
                }
761

    
762
            }
763
    }
764

    
765
    //
766
    // ====================================================================
767
    // Edicion
768
    //
769

    
770
    private void newVersionOfUpdate() {
771
        this.versionOfUpdate++;
772
    }
773

    
774
    private long currentVersionOfUpdate() {
775
        return this.versionOfUpdate;
776
    }
777

    
778
    private void checkInEditingMode() throws NeedEditingModeException {
779
        if (mode != MODE_FULLEDIT) {
780
            throw new NeedEditingModeException(this.getName());
781
        }
782
    }
783

    
784
    private void checkNotInAppendMode() throws IllegalStateException {
785
        if (mode == MODE_APPEND) {
786
            throw new IllegalStateException(this.getName());
787
        }
788
    }
789

    
790
    private void checkIsOwnFeature(Feature feature)
791
        throws IllegalFeatureException {
792
        if (((DefaultFeature) feature).getStore() != this) {
793
            throw new IllegalFeatureException(this.getName());
794
        }
795
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
796
        // fixFeatureType((DefaultFeatureType) feature.getType());
797
    }
798

    
799
    private void exitEditingMode() {
800
        if (commands != null) {
801
            commands.clear();
802
            commands = null;
803
        }
804

    
805
        if (featureTypeManager != null) {
806
            featureTypeManager.dispose();
807
            featureTypeManager = null;
808

    
809
        }
810

    
811
        // TODO implementar un dispose para estos dos
812
        featureManager = null;
813
        spatialManager = null;
814

    
815
        featureCount = null;
816

    
817
        mode = MODE_QUERY;
818
        hasStrongChanges = true; // Lo deja a true por si las moscas
819
        hasInserts = true;
820
    }
821

    
822
    synchronized public void edit() throws DataException {
823
        edit(MODE_FULLEDIT);
824
    }
825

    
826
    synchronized public void edit(int mode) throws DataException {
827
        LOG.debug("Starting editing in mode: {}", new Integer(mode));
828
        try {
829
            if (this.mode != MODE_QUERY) {
830
                throw new AlreadyEditingException(this.getName());
831
            }
832
            if (!this.provider.supportsAppendMode()) {
833
                mode = MODE_FULLEDIT;
834
            }
835
            switch (mode) {
836
            case MODE_QUERY:
837
                throw new IllegalStateException(this.getName());
838

    
839
            case MODE_FULLEDIT:
840
                if (!this.transforms.isEmpty()) {
841
                    throw new IllegalStateException(this.getName());
842
                }
843
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
844
                invalidateIndexes();
845
                featureManager =
846
                    new FeatureManager(new MemoryExpansionAdapter());
847
                featureTypeManager =
848
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
849
                spatialManager =
850
                    new SpatialManager(this, provider.getEnvelope());
851

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

    
877
    private void invalidateIndexes() {
878
        setIndexesValidStatus(false);
879
    }
880

    
881
    private void setIndexesValidStatus(boolean valid) {
882
        FeatureIndexes indexes = getIndexes();
883
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
884
            ? Boolean.TRUE : Boolean.FALSE), indexes);
885
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
886
            FeatureIndex index = (FeatureIndex) iterator.next();
887
            if (index instanceof FeatureIndexProviderServices) {
888
                FeatureIndexProviderServices indexServices =
889
                    (FeatureIndexProviderServices) index;
890
                indexServices.setValid(valid);
891
            }
892
        }
893
    }
894

    
895
    private void updateIndexes() throws FeatureIndexException {
896
        FeatureIndexes indexes = getIndexes();
897
        LOG.debug("Refilling indexes: {}", indexes);
898
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
899
            FeatureIndex index = (FeatureIndex) iterator.next();
900
            if (index instanceof FeatureIndexProviderServices) {
901
                FeatureIndexProviderServices indexServices =
902
                    (FeatureIndexProviderServices) index;
903
                indexServices.fill(true, null);
904
            }
905
        }
906
    }
907

    
908
    private void waitForIndexes() {
909
        FeatureIndexes indexes = getIndexes();
910
        LOG.debug("Waiting for indexes to finish filling: {}", indexes);
911
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
912
            FeatureIndex index = (FeatureIndex) iterator.next();
913
            if (index instanceof FeatureIndexProviderServices) {
914
                FeatureIndexProviderServices indexServices =
915
                    (FeatureIndexProviderServices) index;
916
                indexServices.waitForIndex();
917
            }
918
        }
919
    }
920

    
921
    private void disposeIndexes() {
922
        FeatureIndexes indexes = getIndexes();
923
        LOG.debug("Disposing indexes: {}", indexes);
924
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
925
            FeatureIndex index = (FeatureIndex) iterator.next();
926
            if (index instanceof FeatureIndexProviderServices) {
927
                FeatureIndexProviderServices indexServices =
928
                    (FeatureIndexProviderServices) index;
929
                indexServices.dispose();
930
            }
931
        }
932
    }
933

    
934
    public boolean isEditing() {
935
        return mode == MODE_FULLEDIT;
936
    }
937

    
938
    public boolean isAppending() {
939
        return mode == MODE_APPEND;
940
    }
941

    
942
    synchronized public void update(EditableFeatureType type)
943
        throws DataException {
944
        try {
945
            checkInEditingMode();
946
            if (type == null) {
947
                throw new NullFeatureTypeException(getName());
948
            }
949
            // FIXME: Comprobar que es un featureType aceptable.
950
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
951
            newVersionOfUpdate();
952

    
953
            FeatureType oldt = type.getSource().getCopy();
954
            FeatureType newt = type.getNotEditableCopy();
955
            commands.update(newt, oldt);
956

    
957
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
958
                hasStrongChanges = true;
959
            }
960
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
961
        } catch (Exception e) {
962
            throw new StoreUpdateFeatureTypeException(e, this.getName());
963
        }
964
    }
965

    
966
    synchronized public void delete(Feature feature) throws DataException {
967
        try {
968
            checkInEditingMode();
969
            checkIsOwnFeature(feature);
970
            if (feature instanceof EditableFeature) {
971
                throw new StoreDeleteEditableFeatureException(getName());
972
            }
973
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
974
            this.commands.delete(feature);
975
            newVersionOfUpdate();
976
            hasStrongChanges = true;
977
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
978
        } catch (Exception e) {
979
            throw new StoreDeleteFeatureException(e, this.getName());
980
        }
981
    }
982

    
983
    private static EditableFeature lastChangedFeature = null;
984

    
985
    synchronized public void insert(EditableFeature feature)
986
        throws DataException {
987
        LOG.debug("In editing mode {}, insert feature: {}", new Integer(mode),
988
            feature);
989
        try {
990
            switch (mode) {
991
            case MODE_QUERY:
992
                throw new NeedEditingModeException(this.getName());
993

    
994
            case MODE_APPEND:
995
                checkIsOwnFeature(feature);
996
                if (feature.getSource() != null) {
997
                    throw new NoNewFeatureInsertException(this.getName());
998
                }
999
                this.featureCount = null;
1000
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1001
                feature.validate(Feature.UPDATE);
1002
                provider.append(((DefaultEditableFeature) feature).getData());
1003
                hasStrongChanges = true;
1004
                hasInserts = true;
1005
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1006
                break;
1007

    
1008
            case MODE_FULLEDIT:
1009
                checkIsOwnFeature(feature);
1010
                if (feature.getSource() != null) {
1011
                    throw new NoNewFeatureInsertException(this.getName());
1012
                }
1013

    
1014
                waitForIndexes();
1015

    
1016
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1017
                newVersionOfUpdate();
1018
                if ((lastChangedFeature == null)
1019
                    || (lastChangedFeature.getSource() != feature.getSource())) {
1020
                    lastChangedFeature = feature;
1021
                    feature.validate(Feature.UPDATE);
1022
                    lastChangedFeature = null;
1023
                }
1024
                commands.insert(feature.getNotEditableCopy());
1025
                hasStrongChanges = true;
1026
                hasInserts = true;
1027
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1028
                break;
1029
            }
1030
        } catch (Exception e) {
1031
            throw new StoreInsertFeatureException(e, this.getName());
1032
        }
1033
    }
1034

    
1035
    synchronized public void update(EditableFeature feature)
1036
        throws DataException {
1037
        try {
1038
            if ((feature).getSource() == null) {
1039
                insert(feature);
1040
                return;
1041
            }
1042
            checkInEditingMode();
1043
            checkIsOwnFeature(feature);
1044
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1045
            newVersionOfUpdate();
1046
            if ((lastChangedFeature == null)
1047
                || (lastChangedFeature.getSource() != feature.getSource())) {
1048
                lastChangedFeature = feature;
1049
                feature.validate(Feature.UPDATE);
1050
                lastChangedFeature = null;
1051
            }
1052

    
1053
            Feature oldf = feature.getSource();
1054
            Feature newf = feature.getNotEditableCopy();
1055
            commands.update(newf, oldf);
1056

    
1057
            hasStrongChanges = true;
1058
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1059
        } catch (Exception e) {
1060
            throw new StoreUpdateFeatureException(e, this.getName());
1061
        }
1062
    }
1063

    
1064
    synchronized public void redo() throws RedoException {
1065
        Command redo = commands.getNextRedoCommand();
1066
        try {
1067
            checkInEditingMode();
1068
        } catch (NeedEditingModeException ex) {
1069
            throw new RedoException(redo, ex);
1070
        }
1071
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1072
        newVersionOfUpdate();
1073
        commands.redo();
1074
        hasStrongChanges = true;
1075
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1076
    }
1077

    
1078
    synchronized public void undo() throws UndoException {
1079
        Command undo = commands.getNextUndoCommand();
1080
        try {
1081
            checkInEditingMode();
1082
        } catch (NeedEditingModeException ex) {
1083
            throw new UndoException(undo, ex);
1084
        }
1085
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1086
        newVersionOfUpdate();
1087
        commands.undo();
1088
        hasStrongChanges = true;
1089
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1090
    }
1091

    
1092
    public List getRedoInfos() {
1093
        if (isEditing() && (commands != null)) {
1094
            return commands.getRedoInfos();
1095
        } else {
1096
            return null;
1097
        }
1098
    }
1099

    
1100
    public List getUndoInfos() {
1101
        if (isEditing() && (commands != null)) {
1102
            return commands.getUndoInfos();
1103
        } else {
1104
            return null;
1105
        }
1106
    }
1107

    
1108
    public synchronized FeatureCommandsStack getCommandsStack()
1109
        throws DataException {
1110
        checkInEditingMode();
1111
        return commands;
1112
    }
1113

    
1114
    synchronized public void cancelEditing() throws DataException {
1115
        spatialManager.cancelModifies();
1116
        try {
1117
            checkInEditingMode();
1118

    
1119
            boolean clearSelection = this.hasStrongChanges;
1120
            if (this.selection instanceof FeatureReferenceSelection) {
1121
                clearSelection = this.hasInserts;
1122
            }
1123
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1124
            exitEditingMode();
1125
            if (clearSelection) {
1126
                ((FeatureSelection) this.getSelection()).deselectAll();
1127
            }
1128
            updateIndexes();
1129
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1130
        } catch (Exception e) {
1131
            throw new StoreCancelEditingException(e, this.getName());
1132
        }
1133
    }
1134

    
1135
    synchronized public void finishEditing() throws DataException {
1136
        LOG.debug("finish editing of mode: {}", new Integer(mode));
1137
        try {
1138
            switch (mode) {
1139
            case MODE_QUERY:
1140
                throw new NeedEditingModeException(this.getName());
1141

    
1142
            case MODE_APPEND:
1143
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1144
                provider.endAppend();
1145
                exitEditingMode();
1146
                updateIndexes();
1147
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1148
                break;
1149

    
1150
            case MODE_FULLEDIT:
1151
                if (hasStrongChanges && !this.allowWrite()) {
1152
                    throw new WriteNotAllowedException(getName());
1153
                }
1154
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1155
                if (hasStrongChanges) {
1156
                    validateFeatures(Feature.FINISH_EDITING);
1157
                    provider.performChanges(featureManager.getDeleted(),
1158
                        featureManager.getInserted(),
1159
                        featureManager.getUpdated(),
1160
                        featureTypeManager.getFeatureTypesChanged());
1161
                }
1162
                exitEditingMode();
1163
                updateIndexes();
1164
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1165
                break;
1166
            }
1167
        } catch (Exception e) {
1168
            throw new FinishEditingException(e);
1169
        }
1170
    }
1171

    
1172
    public void beginEditingGroup(String description)
1173
        throws NeedEditingModeException {
1174
        checkInEditingMode();
1175
        commands.startComplex(description);
1176
    }
1177

    
1178
    public void endEditingGroup() throws NeedEditingModeException {
1179
        checkInEditingMode();
1180
        commands.endComplex();
1181
    }
1182

    
1183
    public boolean isAppendModeSupported() {
1184
        return this.provider.supportsAppendMode();
1185
    }
1186

    
1187
    public void export(DataServerExplorer explorer, String provider,
1188
        NewFeatureStoreParameters params) throws DataException {
1189

    
1190
        if (this.getFeatureTypes().size() != 1) {
1191
            throw new NotYetImplemented(
1192
                "export whith more than one type not yet implemented");
1193
        }
1194
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1195
        FeatureStore target = null;
1196
        FeatureSet features = null;
1197
        DisposableIterator iterator = null;
1198
        try {
1199
            FeatureType type = this.getDefaultFeatureType();
1200
            if ((params.getDefaultFeatureType() == null)
1201
                || (params.getDefaultFeatureType().size() == 0)) {
1202
                params.setDefaultFeatureType(type.getEditable());
1203

    
1204
            }
1205
            explorer.add(provider, params, true);
1206

    
1207
            DataManager manager = DALLocator.getDataManager();
1208
            target = (FeatureStore) manager.openStore(provider, params);
1209
            FeatureType targetType = target.getDefaultFeatureType();
1210

    
1211
            target.edit(MODE_APPEND);
1212
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1213
            if (featureSelection.getSize() > 0) {
1214
                features = this.getFeatureSelection();
1215
            } else {
1216
                if ((pk != null) && (pk.length > 0)) {
1217
                    FeatureQuery query = createFeatureQuery();
1218
                    for (int i = 0; i < pk.length; i++) {
1219
                        query.getOrder().add(pk[i].getName(), true);
1220
                    }
1221
                    features = this.getFeatureSet(query);
1222
                } else {
1223
                    features = this.getFeatureSet();
1224
                }
1225
            }
1226
            iterator = features.fastIterator();
1227
            while (iterator.hasNext()) {
1228
                DefaultFeature feature = (DefaultFeature) iterator.next();
1229
                target.insert(target.createNewFeature(targetType, feature));
1230
            }
1231
            target.finishEditing();
1232
            target.dispose();
1233
        } catch (Exception e) {
1234
            throw new DataExportException(e, params.toString());
1235
        } finally {
1236
            dispose(iterator);
1237
            dispose(features);
1238
            dispose(target);
1239
        }
1240
    }
1241

    
1242
    //
1243
    // ====================================================================
1244
    // Obtencion de datos
1245
    // getDataCollection, getFeatureCollection
1246
    //
1247

    
1248
    public DataSet getDataSet() throws DataException {
1249
        checkNotInAppendMode();
1250
        FeatureQuery query =
1251
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1252
        return new DefaultFeatureSet(this, query);
1253
    }
1254

    
1255
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1256
        checkNotInAppendMode();
1257
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1258
    }
1259

    
1260
    public void getDataSet(Observer observer) throws DataException {
1261
        checkNotInAppendMode();
1262
        this.getFeatureSet(null, observer);
1263
    }
1264

    
1265
    public void getDataSet(DataQuery dataQuery, Observer observer)
1266
        throws DataException {
1267
        checkNotInAppendMode();
1268
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1269
    }
1270

    
1271
    public FeatureSet getFeatureSet() throws DataException {
1272
        checkNotInAppendMode();
1273
        FeatureQuery query =
1274
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1275
        return new DefaultFeatureSet(this, query);
1276
    }
1277

    
1278
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1279
        throws DataException {
1280
        checkNotInAppendMode();
1281
        return new DefaultFeatureSet(this, featureQuery);
1282
    }
1283

    
1284
    public void accept(Visitor visitor) throws BaseException {
1285
        FeatureSet set = getFeatureSet();
1286
        try {
1287
            set.accept(visitor);
1288
        } finally {
1289
            set.dispose();
1290
        }
1291
    }
1292

    
1293
    public void accept(Visitor visitor, DataQuery dataQuery)
1294
        throws BaseException {
1295
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1296
        try {
1297
            set.accept(visitor);
1298
        } finally {
1299
            set.dispose();
1300
        }
1301
    }
1302

    
1303
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1304
        throws DataException {
1305
        DefaultFeatureType fType =
1306
            (DefaultFeatureType) this.getFeatureType(featureQuery
1307
                .getFeatureTypeId());
1308
        if ((featureQuery.getAttributeNames() != null)
1309
            && (featureQuery.getAttributeNames().length > 0)) {
1310
            return fType.getSubtype(featureQuery.getAttributeNames());
1311
        }
1312
        return fType;
1313
    }
1314

    
1315
    public void getFeatureSet(Observer observer) throws DataException {
1316
        checkNotInAppendMode();
1317
        this.getFeatureSet(null, observer);
1318
    }
1319

    
1320
    public void getFeatureSet(FeatureQuery query, Observer observer)
1321
        throws DataException {
1322
        class LoadInBackGround implements Runnable {
1323

    
1324
            private FeatureStore store;
1325
            private FeatureQuery query;
1326
            private Observer observer;
1327

    
1328
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1329
                Observer observer) {
1330
                this.store = store;
1331
                this.query = query;
1332
                this.observer = observer;
1333
            }
1334

    
1335
            void notify(FeatureStoreNotification theNotification) {
1336
                observer.update(store, theNotification);
1337
                return;
1338
            }
1339

    
1340
            public void run() {
1341
                FeatureSet set = null;
1342
                try {
1343
                    set = store.getFeatureSet(query);
1344
                    notify(new DefaultFeatureStoreNotification(store,
1345
                        FeatureStoreNotification.LOAD_FINISHED, set));
1346
                } catch (Exception e) {
1347
                    notify(new DefaultFeatureStoreNotification(store,
1348
                        FeatureStoreNotification.LOAD_FINISHED, e));
1349
                } finally {
1350
                    dispose(set);
1351
                }
1352
            }
1353
        }
1354

    
1355
        checkNotInAppendMode();
1356
        if (query == null) {
1357
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1358
        }
1359
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1360
        Thread thread = new Thread(task, "Load Feature Set in background");
1361
        thread.start();
1362
    }
1363

    
1364
    public Feature getFeatureByReference(FeatureReference reference)
1365
        throws DataException {
1366
        checkNotInAppendMode();
1367
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1368
        FeatureType featureType;
1369
        if (ref.getFeatureTypeId() == null) {
1370
            featureType = this.getDefaultFeatureType();
1371
        } else {
1372
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1373
        }
1374
        return this.getFeatureByReference(reference, featureType);
1375
    }
1376

    
1377
    public Feature getFeatureByReference(FeatureReference reference,
1378
        FeatureType featureType) throws DataException {
1379
        checkNotInAppendMode();
1380
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1381
        if (!this.transforms.isEmpty()) {
1382

    
1383
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1384

    
1385
        }
1386
        // TODO comprobar que el id es de este store
1387

    
1388
        if (this.mode == MODE_FULLEDIT) {
1389
            Feature f = featureManager.get(reference, this, featureType);
1390
            if (f != null) {
1391
                return f;
1392
            }
1393
        }
1394
        DefaultFeature feature =
1395
            new DefaultFeature(this,
1396
                this.provider.getFeatureProviderByReference(
1397
                    (FeatureReferenceProviderServices) reference, featureType));
1398

    
1399
        if (!this.transforms.isEmpty()) {
1400
            return this.transforms.applyTransform(feature, featureType);
1401
        }
1402
        return feature;
1403
    }
1404

    
1405
    //
1406
    // ====================================================================
1407
    // Gestion de features
1408
    //
1409

    
1410
    private FeatureType fixFeatureType(DefaultFeatureType type)
1411
        throws DataException {
1412
        FeatureType original = this.getDefaultFeatureType();
1413

    
1414
        if ((type == null) || type.equals(original)) {
1415
            return original;
1416
        } else {
1417
            if (!type.isSubtypeOf(original)) {
1418
                Iterator iter = this.getFeatureTypes().iterator();
1419
                FeatureType tmpType;
1420
                boolean found = false;
1421
                while (iter.hasNext()) {
1422
                    tmpType = (FeatureType) iter.next();
1423
                    if (type.equals(tmpType)) {
1424
                        return type;
1425

    
1426
                    } else
1427
                        if (type.isSubtypeOf(tmpType)) {
1428
                            found = true;
1429
                            original = tmpType;
1430
                            break;
1431
                        }
1432

    
1433
                }
1434
                if (!found) {
1435
                    throw new IllegalFeatureTypeException(getName());
1436
                }
1437
            }
1438
        }
1439

    
1440
        // Checks that type has all fields of pk
1441
        // else add the missing attributes at the end.
1442
        if (!original.hasOID()) {
1443
            // Gets original pk attributes
1444
            DefaultEditableFeatureType edOriginal =
1445
                (DefaultEditableFeatureType) original.getEditable();
1446
            FeatureAttributeDescriptor orgAttr;
1447
            Iterator edOriginalIter = edOriginal.iterator();
1448
            while (edOriginalIter.hasNext()) {
1449
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1450
                if (!orgAttr.isPrimaryKey()) {
1451
                    edOriginalIter.remove();
1452
                }
1453
            }
1454

    
1455
            // Checks if all pk attributes are in type
1456
            Iterator typeIterator;
1457
            edOriginalIter = edOriginal.iterator();
1458
            FeatureAttributeDescriptor attr;
1459
            while (edOriginalIter.hasNext()) {
1460
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1461
                typeIterator = type.iterator();
1462
                while (typeIterator.hasNext()) {
1463
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1464
                    if (attr.getName().equals(orgAttr.getName())) {
1465
                        edOriginalIter.remove();
1466
                        break;
1467
                    }
1468
                }
1469
            }
1470

    
1471
            // add missing pk attributes if any
1472
            if (edOriginal.size() > 0) {
1473
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1474
                DefaultEditableFeatureType edType =
1475
                    (DefaultEditableFeatureType) original.getEditable();
1476
                edType.clear();
1477
                edType.addAll(type);
1478
                edType.addAll(edOriginal);
1479
                if (!isEditable) {
1480
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1481
                }
1482
            }
1483

    
1484
        }
1485

    
1486
        return type;
1487
    }
1488

    
1489
    public void validateFeatures(int mode) throws DataException {
1490
        FeatureSet collection = null;
1491
        DisposableIterator iter = null;
1492
        try {
1493
            checkNotInAppendMode();
1494
            collection = this.getFeatureSet();
1495
            iter = collection.fastIterator();
1496
            long previousVersionOfUpdate = currentVersionOfUpdate();
1497
            while (iter.hasNext()) {
1498
                ((DefaultFeature) iter.next()).validate(mode);
1499
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1500
                    throw new ConcurrentDataModificationException(getName());
1501
                }
1502
            }
1503
        } catch (Exception e) {
1504
            throw new ValidateFeaturesException(e, getName());
1505
        } finally {
1506
            dispose(iter);
1507
            dispose(collection);
1508
        }
1509
    }
1510

    
1511
    public FeatureType getDefaultFeatureType() throws DataException {
1512
        try {
1513
            if (isEditing()) {
1514
                FeatureType auxFeatureType =
1515
                    featureTypeManager.getType(defaultFeatureType.getId());
1516
                if (auxFeatureType != null) {
1517
                    return auxFeatureType;
1518
                }
1519
            }
1520
            FeatureType type = this.transforms.getDefaultFeatureType();
1521
            if (type != null) {
1522
                return type;
1523
            }
1524
            return defaultFeatureType;
1525
        } catch (Exception e) {
1526
            throw new GetFeatureTypeException(e, getName());
1527
        }
1528
    }
1529

    
1530
    public FeatureType getFeatureType(String featureTypeId)
1531
        throws DataException {
1532
        if (featureTypeId == null) {
1533
            return this.getDefaultFeatureType();
1534
        }
1535
        try {
1536
            if (isEditing()) {
1537
                FeatureType auxFeatureType =
1538
                    featureTypeManager.getType(featureTypeId);
1539
                if (auxFeatureType != null) {
1540
                    return auxFeatureType;
1541
                }
1542
            }
1543
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1544
            if (type != null) {
1545
                return type;
1546
            }
1547
            Iterator iter = this.featureTypes.iterator();
1548
            while (iter.hasNext()) {
1549
                type = (FeatureType) iter.next();
1550
                if (type.getId().equals(featureTypeId)) {
1551
                    return type;
1552
                }
1553
            }
1554
            return null;
1555
        } catch (Exception e) {
1556
            throw new GetFeatureTypeException(e, getName());
1557
        }
1558
    }
1559

    
1560
    public FeatureType getProviderDefaultFeatureType() {
1561
        return defaultFeatureType;
1562
    }
1563

    
1564
    public List getFeatureTypes() throws DataException {
1565
        try {
1566
            List types;
1567
            if (isEditing()) {
1568
                types = new ArrayList();
1569
                Iterator it = featureTypes.iterator();
1570
                while (it.hasNext()) {
1571
                    FeatureType type = (FeatureType) it.next();
1572
                    FeatureType typeaux =
1573
                        featureTypeManager.getType(type.getId());
1574
                    if (typeaux != null) {
1575
                        types.add(typeaux);
1576
                    } else {
1577
                        types.add(type);
1578
                    }
1579
                }
1580
                it = featureTypeManager.newsIterator();
1581
                while (it.hasNext()) {
1582
                    FeatureType type = (FeatureType) it.next();
1583
                    types.add(type);
1584
                }
1585
            } else {
1586
                types = this.transforms.getFeatureTypes();
1587
                if (types == null) {
1588
                    types = featureTypes;
1589
                }
1590
            }
1591
            return Collections.unmodifiableList(types);
1592
        } catch (Exception e) {
1593
            throw new GetFeatureTypeException(e, getName());
1594
        }
1595
    }
1596

    
1597
    public List getProviderFeatureTypes() throws DataException {
1598
        return Collections.unmodifiableList(this.featureTypes);
1599
    }
1600

    
1601
    public Feature createFeature(FeatureProvider data) throws DataException {
1602
        DefaultFeature feature = new DefaultFeature(this, data);
1603
        return feature;
1604
    }
1605

    
1606
    public Feature createFeature(FeatureProvider data, FeatureType type)
1607
        throws DataException {
1608
        // FIXME: falta por implementar
1609
        // Comprobar si es un subtipo del feature de data
1610
        // y construir un feature usando el subtipo.
1611
        // Probablemente requiera generar una copia del data.
1612
        throw new NotYetImplemented();
1613
    }
1614

    
1615
    public EditableFeature createNewFeature(FeatureType type,
1616
        Feature defaultValues) throws DataException {
1617
        try {
1618
            FeatureProvider data = createNewFeatureProvider(type);
1619
            DefaultEditableFeature feature =
1620
                new DefaultEditableFeature(this, data);
1621
            feature.initializeValues(defaultValues);
1622
            return feature;
1623
        } catch (Exception e) {
1624
            throw new CreateFeatureException(e, getName());
1625
        }
1626
    }
1627

    
1628
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1629
        throws DataException {
1630
        type = this.fixFeatureType((DefaultFeatureType) type);
1631
        FeatureProvider data = this.provider.createFeatureProvider(type);
1632
        data.setNew(true);
1633
        if (type.hasOID() && (data.getOID() == null)) {
1634
            data.setOID(this.provider.createNewOID());
1635
        } else {
1636
            data.setOID(this.getTemporalOID());
1637
        }
1638
        return data;
1639

    
1640
    }
1641

    
1642
    public EditableFeature createNewFeature(FeatureType type,
1643
        boolean defaultValues) throws DataException {
1644
        try {
1645
            FeatureProvider data = createNewFeatureProvider(type);
1646
            DefaultEditableFeature feature =
1647
                new DefaultEditableFeature(this, data);
1648
            if (defaultValues) {
1649
                feature.initializeValues();
1650
            }
1651
            return feature;
1652
        } catch (Exception e) {
1653
            throw new CreateFeatureException(e, getName());
1654
        }
1655
    }
1656

    
1657
    public EditableFeature createNewFeature(boolean defaultValues)
1658
        throws DataException {
1659
        return this.createNewFeature(this.getDefaultFeatureType(),
1660
            defaultValues);
1661
    }
1662

    
1663
    public EditableFeature createNewFeature() throws DataException {
1664
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1665
    }
1666

    
1667
    public EditableFeatureType createFeatureType() {
1668
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1669
        return ftype;
1670
    }
1671

    
1672
    public EditableFeatureType createFeatureType(String id) {
1673
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1674
        return ftype;
1675
    }
1676

    
1677
    //
1678
    // ====================================================================
1679
    // Index related methods
1680
    //
1681

    
1682
    public FeatureIndexes getIndexes() {
1683
        return this.indexes;
1684
    }
1685

    
1686
    public FeatureIndex createIndex(FeatureType featureType,
1687
        String attributeName, String indexName) throws DataException {
1688
        return createIndex(null, featureType, attributeName, indexName);
1689
    }
1690

    
1691
    public FeatureIndex createIndex(String indexTypeName,
1692
        FeatureType featureType, String attributeName, String indexName)
1693
        throws DataException {
1694

    
1695
        return createIndex(indexTypeName, featureType, attributeName,
1696
            indexName, false, null);
1697
    }
1698

    
1699
    public FeatureIndex createIndex(FeatureType featureType,
1700
        String attributeName, String indexName, Observer observer)
1701
        throws DataException {
1702
        return createIndex(null, featureType, attributeName, indexName,
1703
            observer);
1704
    }
1705

    
1706
    public FeatureIndex createIndex(String indexTypeName,
1707
        FeatureType featureType, String attributeName, String indexName,
1708
        final Observer observer) throws DataException {
1709

    
1710
        return createIndex(indexTypeName, featureType, attributeName,
1711
            indexName, true, observer);
1712
    }
1713

    
1714
    private FeatureIndex createIndex(String indexTypeName,
1715
        FeatureType featureType, String attributeName, String indexName,
1716
        boolean background, final Observer observer) throws DataException {
1717

    
1718
        checkNotInAppendMode();
1719
        FeatureIndexProviderServices index = null;
1720
        index =
1721
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1722
                featureType, indexName,
1723
                featureType.getAttributeDescriptor(attributeName));
1724

    
1725
        try {
1726
            index.fill(background, observer);
1727
        } catch (FeatureIndexException e) {
1728
            throw new InitializeException(index.getName(), e);
1729
        }
1730

    
1731
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1732
        return index;
1733
    }
1734

    
1735
    //
1736
    // ====================================================================
1737
    // Transforms related methods
1738
    //
1739

    
1740
    public FeatureStoreTransforms getTransforms() {
1741
        return this.transforms;
1742
    }
1743

    
1744
    public FeatureQuery createFeatureQuery() {
1745
        return new DefaultFeatureQuery();
1746
    }
1747

    
1748
    public DataQuery createQuery() {
1749
        return createFeatureQuery();
1750
    }
1751

    
1752
    //
1753
    // ====================================================================
1754
    // UndoRedo related methods
1755
    //
1756

    
1757
    public boolean canRedo() {
1758
        return commands.canRedo();
1759
    }
1760

    
1761
    public boolean canUndo() {
1762
        return commands.canUndo();
1763
    }
1764

    
1765
    public void redo(int num) throws RedoException {
1766
        commands.redo(num);
1767
    }
1768

    
1769
    public void undo(int num) throws UndoException {
1770
        commands.undo(num);
1771
    }
1772

    
1773
    //
1774
    // ====================================================================
1775
    // Metadata related methods
1776
    //
1777

    
1778
    public Object getMetadataID() {
1779
        return this.provider.getSourceId();
1780
    }
1781

    
1782
    public void delegate(DynObject dynObject) {
1783
        this.metadata.delegate(dynObject);
1784
    }
1785

    
1786
    public DynClass getDynClass() {
1787
        return this.metadata.getDynClass();
1788
    }
1789

    
1790
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1791
                if( this.transforms.hasDynValue(name) ) {
1792
                        return this.transforms.getDynValue(name);
1793
                }
1794
                if (this.metadata.hasDynValue(name)) {
1795
                        return this.metadata.getDynValue(name);
1796
                }
1797
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1798
                        return this.provider.getProviderName();
1799
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1800
                        return this.provider.getSourceId();
1801
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1802
                        try {
1803
                                return this.getDefaultFeatureType();
1804
                        } catch (DataException e) {
1805
                                return null;
1806
                        }
1807
                }
1808
                return this.metadata.getDynValue(name);
1809
        }
1810

    
1811
    public boolean hasDynValue(String name) {
1812
                if( this.transforms.hasDynValue(name) ) {
1813
                        return true;
1814
                }
1815
        return this.metadata.hasDynValue(name);
1816
    }
1817

    
1818
    public void implement(DynClass dynClass) {
1819
        this.metadata.implement(dynClass);
1820
    }
1821

    
1822
    public Object invokeDynMethod(String name, DynObject context)
1823
        throws DynMethodException {
1824
        return this.metadata.invokeDynMethod(this, name, context);
1825
    }
1826

    
1827
    public Object invokeDynMethod(int code, DynObject context)
1828
        throws DynMethodException {
1829
        return this.metadata.invokeDynMethod(this, code, context);
1830
    }
1831

    
1832
    public void setDynValue(String name, Object value)
1833
        throws DynFieldNotFoundException {
1834
                if( this.transforms.hasDynValue(name) ) {
1835
                        this.transforms.setDynValue(name, value);
1836
                        return;
1837
                }
1838
        this.metadata.setDynValue(name, value);
1839

    
1840
    }
1841

    
1842
    /*
1843
     * (non-Javadoc)
1844
     * 
1845
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1846
     */
1847
    public Set getMetadataChildren() {
1848
        return this.metadataChildren;
1849
    }
1850

    
1851
    /*
1852
     * (non-Javadoc)
1853
     * 
1854
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1855
     */
1856
    public String getMetadataName() {
1857
        return this.provider.getProviderName();
1858
    }
1859

    
1860
    public FeatureTypeManager getFeatureTypeManager() {
1861
        return this.featureTypeManager;
1862
    }
1863

    
1864
    public long getFeatureCount() throws DataException {
1865
        if (featureCount == null) {
1866
            featureCount = new Long(this.provider.getFeatureCount());
1867
        }
1868
        if (this.isEditing() && !this.isAppending()) {
1869
            return featureCount.longValue()
1870
                - this.featureManager.getDeltaSize();
1871
        }
1872
        return featureCount.longValue();
1873
    }
1874

    
1875
    private Long getTemporalOID() {
1876
        return new Long(this.temporalOid++);
1877
    }
1878

    
1879
    public FeatureType getProviderFeatureType(String featureTypeId) {
1880
        if (featureTypeId == null) {
1881
            return this.defaultFeatureType;
1882
        }
1883
        FeatureType type;
1884
        Iterator iter = this.featureTypes.iterator();
1885
        while (iter.hasNext()) {
1886
            type = (FeatureType) iter.next();
1887
            if (type.getId().equals(featureTypeId)) {
1888
                return type;
1889
            }
1890
        }
1891
        return null;
1892
    }
1893

    
1894
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1895
        return ((DefaultFeature) feature).getData();
1896
    }
1897

    
1898
    public DataStore getStore() {
1899
        return this;
1900
    }
1901

    
1902
    public FeatureStore getFeatureStore() {
1903
        return this;
1904
    }
1905

    
1906
    public void createCache(String name, DynObject parameters)
1907
        throws DataException {
1908
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1909
        if (cache == null) {
1910
            throw new CreateException("FeaureCacheProvider", null);
1911
        }
1912
        cache.apply(this, provider);
1913
        provider = cache;
1914

    
1915
        featureCount = null;
1916
    }
1917

    
1918
    public FeatureCache getCache() {
1919
        return cache;
1920
    }
1921

    
1922
    public void clear() {
1923
        if (metadata != null) {
1924
            metadata.clear();
1925
        }
1926
    }
1927

    
1928
    public String getName() {
1929
        return this.provider.getName();
1930
    }
1931

    
1932
    public String getFullName() {
1933
        return this.provider.getFullName();
1934
    }
1935

    
1936
    public String getProviderName() {
1937
        return this.provider.getProviderName();
1938
    }
1939

    
1940
    public boolean isKnownEnvelope() {
1941
        return this.provider.isKnownEnvelope();
1942
    }
1943

    
1944
    public boolean hasRetrievedFeaturesLimit() {
1945
        return this.provider.hasRetrievedFeaturesLimit();
1946
    }
1947

    
1948
    public int getRetrievedFeaturesLimit() {
1949
        return this.provider.getRetrievedFeaturesLimit();
1950
    }
1951

    
1952
    public Interval getInterval() {  
1953
        return this.provider.getInterval();
1954
    }
1955

    
1956
    public Collection getTimes() {      
1957
        return this.provider.getTimes();
1958
    }
1959

    
1960
    public Collection getTimes(Interval interval) {       
1961
        return this.provider.getTimes(interval);
1962
    }
1963
}