Statistics
| Revision:

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

History | View | Annotate | Download (64.7 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.Collections;
32
import java.util.HashMap;
33
import java.util.HashSet;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Map.Entry;
38
import java.util.Set;
39

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

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

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

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

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

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

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

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

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

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

    
173
    private DefaultDataManager dataManager = null;
174

    
175
    private FeatureStoreProvider provider = null;
176

    
177
    private DefaultFeatureIndexes indexes;
178

    
179
    private DefaultFeatureStoreTransforms transforms;
180

    
181
    private DelegatedDynObject metadata;
182
    private Set metadataChildren;
183

    
184
    private Long featureCount = null;
185

    
186
    private long temporalOid = 0;
187

    
188
    private FeatureCacheProvider cache;
189

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

    
199
    public DefaultFeatureStore() {
200

    
201
    }
202

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

    
206
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
207

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

    
212
        this.dataManager = (DefaultDataManager) dataManager;
213

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

    
222
    }
223

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

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

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

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

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

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

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

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

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

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

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

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

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

    
304
        this.featureManager = null;
305
        this.spatialManager = null;
306

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

    
315
    public boolean allowWrite() {
316
        return this.provider.allowWrite();
317
    }
318

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

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

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

    
340
    public Envelope getEnvelope() throws DataException {
341
        if (this.mode == MODE_FULLEDIT) {
342
            return this.spatialManager.getEnvelope();
343
        }
344
        return this.provider.getEnvelope();
345
    }
346

    
347
    /**
348
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
349
     */
350
    public IProjection getSRSDefaultGeometry() throws DataException {
351
        return this.getDefaultFeatureType().getDefaultSRS();
352
    }
353

    
354
    public FeatureSelection createDefaultFeatureSelection()
355
        throws DataException {
356
        return new DefaultFeatureSelection(this);
357
    }
358

    
359
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
360
        throws DataException {
361
        if (type.hasOID()) {
362
            return new DefaultFeatureProvider(type,
363
                this.provider.createNewOID());
364
        }
365
        return new DefaultFeatureProvider(type);
366
    }
367

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

    
402
        }
403

    
404
        if (evaluatedAttr.isEmpty()) {
405
            evaluatedAttr = null;
406
        }
407

    
408
        state.set("evaluatedAttributes", evaluatedAttr);
409
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
410

    
411
    }
412

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

    
422
        DataStoreParameters params =
423
            (DataStoreParameters) state.get("parameters");
424

    
425
        try {
426

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

    
466
                }
467

    
468
            }
469

    
470
            String defFTypeid = state.getString("defaultFeatureTypeId");
471
            FeatureType ftype = null;
472
            if (!this.defaultFeatureType.getId().equals(
473
                state.getString("defaultFeatureTypeId"))) {
474

    
475
                ftype = getFeatureType(defFTypeid);
476
                if (ftype == null) {
477
                    throw new PersistenceCantFindDefaultFeatureTypeException(
478
                        this.getName(), defFTypeid);
479
                }
480
                this.defaultFeatureType = ftype;
481
            }
482

    
483
        } catch (InitializeException e) {
484
            throw new PersistenceException(e);
485
        } catch (DataException e) {
486
            throw new PersistenceException(e);
487
        }
488

    
489
    }
490

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

    
501
            definition.addDynFieldObject("parameters")
502
                .setClassOfValue(DynObject.class).setMandatory(true)
503
                .setPersistent(true);
504

    
505
            definition.addDynFieldObject("selection")
506
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
507
                .setPersistent(true);
508

    
509
            definition.addDynFieldObject("transforms")
510
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
511
                .setMandatory(true).setPersistent(true);
512

    
513
            definition.addDynFieldMap("evaluatedAttributes")
514
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
515
                .setMandatory(false).setPersistent(true);
516

    
517
            definition.addDynFieldString("defaultFeatureTypeId")
518
                .setMandatory(true).setPersistent(true);
519
        }
520
    }
521

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

    
532
    //
533
    // ====================================================================
534
    // Gestion de la seleccion
535
    //
536

    
537
    public void setSelection(DataSet selection) throws DataException {
538
        this.setSelection((FeatureSet) selection);
539
    }
540

    
541
    public DataSet createSelection() throws DataException {
542
        return createFeatureSelection();
543
    }
544

    
545
    public DataSet getSelection() throws DataException {
546
        return this.getFeatureSelection();
547
    }
548

    
549
    public void setSelection(FeatureSet selection) throws DataException {
550
        setSelection(selection, true);
551
    }
552

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

    
565
        } else {
566
            if (selection.equals(this.selection)) {
567
                return;
568
            }
569
            if (!selection.isFromStore(this)) {
570
                throw new SelectionNotAllowedException(getName());
571
            }
572
        }
573

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

    
612
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
613
    }
614

    
615
    public FeatureSelection createFeatureSelection() throws DataException {
616
        return this.provider.createFeatureSelection();
617
    }
618

    
619
    public FeatureSelection getFeatureSelection() throws DataException {
620
        if (selection == null) {
621
            this.selection = createFeatureSelection();
622
            this.selection.addObserver(this);
623
        }
624
        return selection;
625
    }
626

    
627
    //
628
    // ====================================================================
629
    // Gestion de notificaciones
630
    //
631

    
632
    public void notifyChange(String notification) {
633
        if (delegateObservable != null) {
634
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
635
        }
636

    
637
    }
638

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

    
648
    public void notifyChange(String notification, Feature feature) {
649
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
650
            feature));
651
    }
652

    
653
    public void notifyChange(String notification, Command command) {
654
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
655
            command));
656
    }
657

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

    
663
    public void notifyChange(FeatureStoreNotification storeNotification) {
664
        delegateObservable.notifyObservers(storeNotification);
665
    }
666

    
667
    public void notifyChange(String notification, Resource resource) {
668
        notifyChange(new DefaultFeatureStoreNotification(this,
669
            DataStoreNotification.RESOURCE_CHANGED));
670
    }
671

    
672
    //
673
    // ====================================================================
674
    // Gestion de bloqueos
675
    //
676

    
677
    public boolean isLocksSupported() {
678
        return this.provider.isLocksSupported();
679
    }
680

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

    
692
    //
693
    // ====================================================================
694
    // Interface Observable
695
    //
696

    
697
    public void disableNotifications() {
698
        this.delegateObservable.disableNotifications();
699

    
700
    }
701

    
702
    public void enableNotifications() {
703
        this.delegateObservable.enableNotifications();
704
    }
705

    
706
    public void beginComplexNotification() {
707
        this.delegateObservable.beginComplexNotification();
708

    
709
    }
710

    
711
    public void endComplexNotification() {
712
        this.delegateObservable.endComplexNotification();
713

    
714
    }
715

    
716
    public void addObserver(Observer observer) {
717
        this.delegateObservable.addObserver(observer);
718

    
719
    }
720

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

    
727
    public void deleteObservers() {
728
        this.delegateObservable.deleteObservers();
729

    
730
    }
731

    
732
    //
733
    // ====================================================================
734
    // Interface Observer
735
    //
736
    // Usado para observar:
737
    // - su seleccion
738
    // - sus bloqueos
739
    // - sus recursos
740
    //
741

    
742
    public void update(Observable observable, Object notification) {
743
        if (observable instanceof FeatureSet) {
744
            if (observable == this.selection) {
745
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
746
            } else
747
                if (observable == this.locks) {
748
                    this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
749
                }
750

    
751
        } else
752
            if (observable instanceof FeatureStoreProvider) {
753
                if (observable == this.provider) {
754

    
755
                }
756

    
757
            }
758
    }
759

    
760
    //
761
    // ====================================================================
762
    // Edicion
763
    //
764

    
765
    private void newVersionOfUpdate() {
766
        this.versionOfUpdate++;
767
    }
768

    
769
    private long currentVersionOfUpdate() {
770
        return this.versionOfUpdate;
771
    }
772

    
773
    private void checkInEditingMode() throws NeedEditingModeException {
774
        if (mode != MODE_FULLEDIT) {
775
            throw new NeedEditingModeException(this.getName());
776
        }
777
    }
778

    
779
    private void checkNotInAppendMode() throws IllegalStateException {
780
        if (mode == MODE_APPEND) {
781
            throw new IllegalStateException(this.getName());
782
        }
783
    }
784

    
785
    private void checkIsOwnFeature(Feature feature)
786
        throws IllegalFeatureException {
787
        if (((DefaultFeature) feature).getStore() != this) {
788
            throw new IllegalFeatureException(this.getName());
789
        }
790
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
791
        // fixFeatureType((DefaultFeatureType) feature.getType());
792
    }
793

    
794
    private void exitEditingMode() {
795
        if (commands != null) {
796
            commands.clear();
797
            commands = null;
798
        }
799

    
800
        if (featureTypeManager != null) {
801
            featureTypeManager.dispose();
802
            featureTypeManager = null;
803

    
804
        }
805

    
806
        // TODO implementar un dispose para estos dos
807
        featureManager = null;
808
        spatialManager = null;
809

    
810
        featureCount = null;
811

    
812
        mode = MODE_QUERY;
813
        hasStrongChanges = true; // Lo deja a true por si las moscas
814
        hasInserts = true;
815
    }
816

    
817
    synchronized public void edit() throws DataException {
818
        edit(MODE_FULLEDIT);
819
    }
820

    
821
    synchronized public void edit(int mode) throws DataException {
822
        try {
823
            if (this.mode != MODE_QUERY) {
824
                throw new AlreadyEditingException(this.getName());
825
            }
826
            if (!this.provider.supportsAppendMode()) {
827
                mode = MODE_FULLEDIT;
828
            }
829
            switch (mode) {
830
            case MODE_QUERY:
831
                throw new IllegalStateException(this.getName());
832

    
833
            case MODE_FULLEDIT:
834
                if (!this.transforms.isEmpty()) {
835
                    throw new IllegalStateException(this.getName());
836
                }
837
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
838
                invalidateIndexes();
839
                featureManager =
840
                    new FeatureManager(new MemoryExpansionAdapter());
841
                featureTypeManager =
842
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
843
                spatialManager =
844
                    new SpatialManager(this, provider.getEnvelope());
845

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

    
871
    private void invalidateIndexes() {
872
        setIndexesValidStatus(false);
873
    }
874

    
875
    private void setIndexesValidStatus(boolean valid) {
876
        FeatureIndexes indexes = getIndexes();
877
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
878
            FeatureIndex index = (FeatureIndex) iterator.next();
879
            if (index instanceof DefaultFeatureIndex) {
880
                ((DefaultFeatureIndex) index).setValid(valid);
881
            }
882
        }
883
    }
884

    
885
    private void updateIndexes() throws FeatureIndexException {
886
        FeatureIndexes indexes = getIndexes();
887
        for (Iterator iterator = indexes.iterator(); iterator.hasNext();) {
888
            FeatureIndex index = (FeatureIndex) iterator.next();
889
            if (index instanceof FeatureIndexProviderServices) {
890
                FeatureIndexProviderServices indexServices =
891
                    (FeatureIndexProviderServices) index;
892
                indexServices.fill(true, null);
893
            }
894
        }
895
    }
896

    
897
    public boolean isEditing() {
898
        return mode == MODE_FULLEDIT;
899
    }
900

    
901
    public boolean isAppending() {
902
        return mode == MODE_APPEND;
903
    }
904

    
905
    synchronized public void update(EditableFeatureType type)
906
        throws DataException {
907
        try {
908
            checkInEditingMode();
909
            if (type == null) {
910
                throw new NullFeatureTypeException(getName());
911
            }
912
            // FIXME: Comprobar que es un featureType aceptable.
913
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
914
            newVersionOfUpdate();
915

    
916
            FeatureType oldt = type.getSource().getCopy();
917
            FeatureType newt = type.getNotEditableCopy();
918
            commands.update(newt, oldt);
919

    
920
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
921
                hasStrongChanges = true;
922
            }
923
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
924
        } catch (Exception e) {
925
            throw new StoreUpdateFeatureTypeException(e, this.getName());
926
        }
927
    }
928

    
929
    synchronized public void delete(Feature feature) throws DataException {
930
        try {
931
            checkInEditingMode();
932
            checkIsOwnFeature(feature);
933
            if (feature instanceof EditableFeature) {
934
                throw new StoreDeleteEditableFeatureException(getName());
935
            }
936
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
937
            this.commands.delete(feature);
938
            newVersionOfUpdate();
939
            hasStrongChanges = true;
940
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
941
        } catch (Exception e) {
942
            throw new StoreDeleteFeatureException(e, this.getName());
943
        }
944
    }
945

    
946
    private static EditableFeature lastChangedFeature = null;
947

    
948
    synchronized public void insert(EditableFeature feature)
949
        throws DataException {
950
        try {
951
            switch (mode) {
952
            case MODE_QUERY:
953
                throw new NeedEditingModeException(this.getName());
954

    
955
            case MODE_APPEND:
956
                checkIsOwnFeature(feature);
957
                if (feature.getSource() != null) {
958
                    throw new NoNewFeatureInsertException(this.getName());
959
                }
960
                this.featureCount = null;
961
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
962
                feature.validate(Feature.UPDATE);
963
                provider.append(((DefaultEditableFeature) feature).getData());
964
                hasStrongChanges = true;
965
                hasInserts = true;
966
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
967
                break;
968

    
969
            case MODE_FULLEDIT:
970
                checkIsOwnFeature(feature);
971
                if (feature.getSource() != null) {
972
                    throw new NoNewFeatureInsertException(this.getName());
973
                }
974
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
975
                newVersionOfUpdate();
976
                if ((lastChangedFeature == null)
977
                    || (lastChangedFeature.getSource() != feature.getSource())) {
978
                    lastChangedFeature = feature;
979
                    feature.validate(Feature.UPDATE);
980
                    lastChangedFeature = null;
981
                }
982
                commands.insert(feature.getNotEditableCopy());
983
                hasStrongChanges = true;
984
                hasInserts = true;
985
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
986
                break;
987
            }
988
        } catch (Exception e) {
989
            throw new StoreInsertFeatureException(e, this.getName());
990
        }
991
    }
992

    
993
    synchronized public void update(EditableFeature feature)
994
        throws DataException {
995
        try {
996
            if ((feature).getSource() == null) {
997
                insert(feature);
998
                return;
999
            }
1000
            checkInEditingMode();
1001
            checkIsOwnFeature(feature);
1002
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1003
            newVersionOfUpdate();
1004
            if ((lastChangedFeature == null)
1005
                || (lastChangedFeature.getSource() != feature.getSource())) {
1006
                lastChangedFeature = feature;
1007
                feature.validate(Feature.UPDATE);
1008
                lastChangedFeature = null;
1009
            }
1010

    
1011
            Feature oldf = feature.getSource();
1012
            Feature newf = feature.getNotEditableCopy();
1013
            commands.update(newf, oldf);
1014

    
1015
            hasStrongChanges = true;
1016
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1017
        } catch (Exception e) {
1018
            throw new StoreUpdateFeatureException(e, this.getName());
1019
        }
1020
    }
1021

    
1022
    synchronized public void redo() throws RedoException {
1023
        Command redo = commands.getNextRedoCommand();
1024
        try {
1025
            checkInEditingMode();
1026
        } catch (NeedEditingModeException ex) {
1027
            throw new RedoException(redo, ex);
1028
        }
1029
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1030
        newVersionOfUpdate();
1031
        commands.redo();
1032
        hasStrongChanges = true;
1033
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1034
    }
1035

    
1036
    synchronized public void undo() throws UndoException {
1037
        Command undo = commands.getNextUndoCommand();
1038
        try {
1039
            checkInEditingMode();
1040
        } catch (NeedEditingModeException ex) {
1041
            throw new UndoException(undo, ex);
1042
        }
1043
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1044
        newVersionOfUpdate();
1045
        commands.undo();
1046
        hasStrongChanges = true;
1047
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1048
    }
1049

    
1050
    public List getRedoInfos() {
1051
        if (isEditing() && (commands != null)) {
1052
            return commands.getRedoInfos();
1053
        } else {
1054
            return null;
1055
        }
1056
    }
1057

    
1058
    public List getUndoInfos() {
1059
        if (isEditing() && (commands != null)) {
1060
            return commands.getUndoInfos();
1061
        } else {
1062
            return null;
1063
        }
1064
    }
1065

    
1066
    public synchronized FeatureCommandsStack getCommandsStack()
1067
        throws DataException {
1068
        checkInEditingMode();
1069
        return commands;
1070
    }
1071

    
1072
    synchronized public void cancelEditing() throws DataException {
1073
        spatialManager.cancelModifies();
1074
        try {
1075
            checkInEditingMode();
1076

    
1077
            boolean clearSelection = this.hasStrongChanges;
1078
            if (this.selection instanceof FeatureReferenceSelection) {
1079
                clearSelection = this.hasInserts;
1080
            }
1081
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1082
            exitEditingMode();
1083
            if (clearSelection) {
1084
                ((FeatureSelection) this.getSelection()).deselectAll();
1085
            }
1086
            updateIndexes();
1087
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1088
        } catch (Exception e) {
1089
            throw new StoreCancelEditingException(e, this.getName());
1090
        }
1091
    }
1092

    
1093
    synchronized public void finishEditing() throws DataException {
1094
        try {
1095
            switch (mode) {
1096
            case MODE_QUERY:
1097
                throw new NeedEditingModeException(this.getName());
1098

    
1099
            case MODE_APPEND:
1100
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1101
                provider.endAppend();
1102
                exitEditingMode();
1103
                updateIndexes();
1104
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1105
                break;
1106

    
1107
            case MODE_FULLEDIT:
1108
                if (hasStrongChanges && !this.allowWrite()) {
1109
                    throw new WriteNotAllowedException(getName());
1110
                }
1111

    
1112
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1113
                if (hasStrongChanges) {
1114
                    validateFeatures(Feature.FINISH_EDITING);
1115
                    provider.performChanges(featureManager.getDeleted(),
1116
                        featureManager.getInserted(),
1117
                        featureManager.getUpdated(),
1118
                        featureTypeManager.getFeatureTypesChanged());
1119
                }
1120
                exitEditingMode();
1121
                updateIndexes();
1122
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1123
                break;
1124
            }
1125
        } catch (Exception e) {
1126
            throw new FinishEditingException(e);
1127
        }
1128
    }
1129

    
1130
    public void beginEditingGroup(String description)
1131
        throws NeedEditingModeException {
1132
        checkInEditingMode();
1133
        commands.startComplex(description);
1134
    }
1135

    
1136
    public void endEditingGroup() throws NeedEditingModeException {
1137
        checkInEditingMode();
1138
        commands.endComplex();
1139
    }
1140

    
1141
    public boolean isAppendModeSupported() {
1142
        return this.provider.supportsAppendMode();
1143
    }
1144

    
1145
    public void export(DataServerExplorer explorer, String provider,
1146
        NewFeatureStoreParameters params) throws DataException {
1147

    
1148
        if (this.getFeatureTypes().size() != 1) {
1149
            throw new NotYetImplemented(
1150
                "export whith more than one type not yet implemented");
1151
        }
1152
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1153
        FeatureStore target = null;
1154
        FeatureSet features = null;
1155
        DisposableIterator iterator = null;
1156
        try {
1157
            FeatureType type = this.getDefaultFeatureType();
1158
            if ((params.getDefaultFeatureType() == null)
1159
                || (params.getDefaultFeatureType().size() == 0)) {
1160
                params.setDefaultFeatureType(type.getEditable());
1161

    
1162
            }
1163
            explorer.add(provider, params, true);
1164

    
1165
            DataManager manager = DALLocator.getDataManager();
1166
            target = (FeatureStore) manager.openStore(provider, params);
1167
            FeatureType targetType = target.getDefaultFeatureType();
1168

    
1169
            target.edit(MODE_APPEND);
1170
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1171
            if (featureSelection.getSize() > 0) {
1172
                features = this.getFeatureSelection();
1173
            } else {
1174
                if ((pk != null) && (pk.length > 0)) {
1175
                    FeatureQuery query = createFeatureQuery();
1176
                    for (int i = 0; i < pk.length; i++) {
1177
                        query.getOrder().add(pk[i].getName(), true);
1178
                    }
1179
                    features = this.getFeatureSet(query);
1180
                } else {
1181
                    features = this.getFeatureSet();
1182
                }
1183
            }
1184
            iterator = features.fastIterator();
1185
            while (iterator.hasNext()) {
1186
                DefaultFeature feature = (DefaultFeature) iterator.next();
1187
                target.insert(target.createNewFeature(targetType, feature));
1188
            }
1189
            target.finishEditing();
1190
            target.dispose();
1191
        } catch (Exception e) {
1192
            throw new DataExportException(e, params.toString());
1193
        } finally {
1194
            dispose(iterator);
1195
            dispose(features);
1196
            dispose(target);
1197
        }
1198
    }
1199

    
1200
    //
1201
    // ====================================================================
1202
    // Obtencion de datos
1203
    // getDataCollection, getFeatureCollection
1204
    //
1205

    
1206
    public DataSet getDataSet() throws DataException {
1207
        checkNotInAppendMode();
1208
        FeatureQuery query =
1209
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1210
        return new DefaultFeatureSet(this, query);
1211
    }
1212

    
1213
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1214
        checkNotInAppendMode();
1215
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1216
    }
1217

    
1218
    public void getDataSet(Observer observer) throws DataException {
1219
        checkNotInAppendMode();
1220
        this.getFeatureSet(null, observer);
1221
    }
1222

    
1223
    public void getDataSet(DataQuery dataQuery, Observer observer)
1224
        throws DataException {
1225
        checkNotInAppendMode();
1226
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1227
    }
1228

    
1229
    public FeatureSet getFeatureSet() throws DataException {
1230
        checkNotInAppendMode();
1231
        FeatureQuery query =
1232
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1233
        return new DefaultFeatureSet(this, query);
1234
    }
1235

    
1236
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1237
        throws DataException {
1238
        checkNotInAppendMode();
1239
        return new DefaultFeatureSet(this, featureQuery);
1240
    }
1241

    
1242
    public void accept(Visitor visitor) throws BaseException {
1243
        FeatureSet set = getFeatureSet();
1244
        try {
1245
            set.accept(visitor);
1246
        } finally {
1247
            set.dispose();
1248
        }
1249
    }
1250

    
1251
    public void accept(Visitor visitor, DataQuery dataQuery)
1252
        throws BaseException {
1253
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1254
        try {
1255
            set.accept(visitor);
1256
        } finally {
1257
            set.dispose();
1258
        }
1259
    }
1260

    
1261
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1262
        throws DataException {
1263
        DefaultFeatureType fType =
1264
            (DefaultFeatureType) this.getFeatureType(featureQuery
1265
                .getFeatureTypeId());
1266
        if ((featureQuery.getAttributeNames() != null)
1267
            && (featureQuery.getAttributeNames().length > 0)) {
1268
            return fType.getSubtype(featureQuery.getAttributeNames());
1269
        }
1270
        return fType;
1271
    }
1272

    
1273
    public void getFeatureSet(Observer observer) throws DataException {
1274
        checkNotInAppendMode();
1275
        this.getFeatureSet(null, observer);
1276
    }
1277

    
1278
    public void getFeatureSet(FeatureQuery query, Observer observer)
1279
        throws DataException {
1280
        class LoadInBackGround implements Runnable {
1281

    
1282
            private FeatureStore store;
1283
            private FeatureQuery query;
1284
            private Observer observer;
1285

    
1286
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1287
                Observer observer) {
1288
                this.store = store;
1289
                this.query = query;
1290
                this.observer = observer;
1291
            }
1292

    
1293
            void notify(FeatureStoreNotification theNotification) {
1294
                observer.update(store, theNotification);
1295
                return;
1296
            }
1297

    
1298
            public void run() {
1299
                FeatureSet set = null;
1300
                try {
1301
                    set = store.getFeatureSet(query);
1302
                    notify(new DefaultFeatureStoreNotification(store,
1303
                        FeatureStoreNotification.LOAD_FINISHED, set));
1304
                } catch (Exception e) {
1305
                    notify(new DefaultFeatureStoreNotification(store,
1306
                        FeatureStoreNotification.LOAD_FINISHED, e));
1307
                } finally {
1308
                    dispose(set);
1309
                }
1310
            }
1311
        }
1312

    
1313
        checkNotInAppendMode();
1314
        if (query == null) {
1315
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1316
        }
1317
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1318
        Thread thread = new Thread(task, "Load Feature Set in background");
1319
        thread.start();
1320
    }
1321

    
1322
    public Feature getFeatureByReference(FeatureReference reference)
1323
        throws DataException {
1324
        checkNotInAppendMode();
1325
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1326
        FeatureType featureType;
1327
        if (ref.getFeatureTypeId() == null) {
1328
            featureType = this.getDefaultFeatureType();
1329
        } else {
1330
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1331
        }
1332
        return this.getFeatureByReference(reference, featureType);
1333
    }
1334

    
1335
    public Feature getFeatureByReference(FeatureReference reference,
1336
        FeatureType featureType) throws DataException {
1337
        checkNotInAppendMode();
1338
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1339
        if (!this.transforms.isEmpty()) {
1340

    
1341
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1342

    
1343
        }
1344
        // TODO comprobar que el id es de este store
1345

    
1346
        if (this.mode == MODE_FULLEDIT) {
1347
            Feature f = featureManager.get(reference, this, featureType);
1348
            if (f != null) {
1349
                return f;
1350
            }
1351
        }
1352
        DefaultFeature feature =
1353
            new DefaultFeature(this,
1354
                this.provider.getFeatureProviderByReference(
1355
                    (FeatureReferenceProviderServices) reference, featureType));
1356

    
1357
        if (!this.transforms.isEmpty()) {
1358
            return this.transforms.applyTransform(feature, featureType);
1359
        }
1360
        return feature;
1361
    }
1362

    
1363
    //
1364
    // ====================================================================
1365
    // Gestion de features
1366
    //
1367

    
1368
    private FeatureType fixFeatureType(DefaultFeatureType type)
1369
        throws DataException {
1370
        FeatureType original = this.getDefaultFeatureType();
1371

    
1372
        if ((type == null) || type.equals(original)) {
1373
            return original;
1374
        } else {
1375
            if (!type.isSubtypeOf(original)) {
1376
                Iterator iter = this.getFeatureTypes().iterator();
1377
                FeatureType tmpType;
1378
                boolean found = false;
1379
                while (iter.hasNext()) {
1380
                    tmpType = (FeatureType) iter.next();
1381
                    if (type.equals(tmpType)) {
1382
                        return type;
1383

    
1384
                    } else
1385
                        if (type.isSubtypeOf(tmpType)) {
1386
                            found = true;
1387
                            original = tmpType;
1388
                            break;
1389
                        }
1390

    
1391
                }
1392
                if (!found) {
1393
                    throw new IllegalFeatureTypeException(getName());
1394
                }
1395
            }
1396
        }
1397

    
1398
        // Checks that type has all fields of pk
1399
        // else add the missing attributes at the end.
1400
        if (!original.hasOID()) {
1401
            // Gets original pk attributes
1402
            DefaultEditableFeatureType edOriginal =
1403
                (DefaultEditableFeatureType) original.getEditable();
1404
            FeatureAttributeDescriptor orgAttr;
1405
            Iterator edOriginalIter = edOriginal.iterator();
1406
            while (edOriginalIter.hasNext()) {
1407
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1408
                if (!orgAttr.isPrimaryKey()) {
1409
                    edOriginalIter.remove();
1410
                }
1411
            }
1412

    
1413
            // Checks if all pk attributes are in type
1414
            Iterator typeIterator;
1415
            edOriginalIter = edOriginal.iterator();
1416
            FeatureAttributeDescriptor attr;
1417
            while (edOriginalIter.hasNext()) {
1418
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1419
                typeIterator = type.iterator();
1420
                while (typeIterator.hasNext()) {
1421
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1422
                    if (attr.getName().equals(orgAttr.getName())) {
1423
                        edOriginalIter.remove();
1424
                        break;
1425
                    }
1426
                }
1427
            }
1428

    
1429
            // add missing pk attributes if any
1430
            if (edOriginal.size() > 0) {
1431
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1432
                DefaultEditableFeatureType edType =
1433
                    (DefaultEditableFeatureType) original.getEditable();
1434
                edType.clear();
1435
                edType.addAll(type);
1436
                edType.addAll(edOriginal);
1437
                if (!isEditable) {
1438
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1439
                }
1440
            }
1441

    
1442
        }
1443

    
1444
        return type;
1445
    }
1446

    
1447
    public void validateFeatures(int mode) throws DataException {
1448
        FeatureSet collection = null;
1449
        DisposableIterator iter = null;
1450
        try {
1451
            checkNotInAppendMode();
1452
            collection = this.getFeatureSet();
1453
            iter = collection.fastIterator();
1454
            long previousVersionOfUpdate = currentVersionOfUpdate();
1455
            while (iter.hasNext()) {
1456
                ((DefaultFeature) iter.next()).validate(mode);
1457
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1458
                    throw new ConcurrentDataModificationException(getName());
1459
                }
1460
            }
1461
        } catch (Exception e) {
1462
            throw new ValidateFeaturesException(e, getName());
1463
        } finally {
1464
            dispose(iter);
1465
            dispose(collection);
1466
        }
1467
    }
1468

    
1469
    public FeatureType getDefaultFeatureType() throws DataException {
1470
        try {
1471
            if (isEditing()) {
1472
                FeatureType auxFeatureType =
1473
                    featureTypeManager.getType(defaultFeatureType.getId());
1474
                if (auxFeatureType != null) {
1475
                    return auxFeatureType;
1476
                }
1477
            }
1478
            FeatureType type = this.transforms.getDefaultFeatureType();
1479
            if (type != null) {
1480
                return type;
1481
            }
1482
            return defaultFeatureType;
1483
        } catch (Exception e) {
1484
            throw new GetFeatureTypeException(e, getName());
1485
        }
1486
    }
1487

    
1488
    public FeatureType getFeatureType(String featureTypeId)
1489
        throws DataException {
1490
        if (featureTypeId == null) {
1491
            return this.getDefaultFeatureType();
1492
        }
1493
        try {
1494
            if (isEditing()) {
1495
                FeatureType auxFeatureType =
1496
                    featureTypeManager.getType(featureTypeId);
1497
                if (auxFeatureType != null) {
1498
                    return auxFeatureType;
1499
                }
1500
            }
1501
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1502
            if (type != null) {
1503
                return type;
1504
            }
1505
            Iterator iter = this.featureTypes.iterator();
1506
            while (iter.hasNext()) {
1507
                type = (FeatureType) iter.next();
1508
                if (type.getId().equals(featureTypeId)) {
1509
                    return type;
1510
                }
1511
            }
1512
            return null;
1513
        } catch (Exception e) {
1514
            throw new GetFeatureTypeException(e, getName());
1515
        }
1516
    }
1517

    
1518
    public FeatureType getProviderDefaultFeatureType() {
1519
        return defaultFeatureType;
1520
    }
1521

    
1522
    public List getFeatureTypes() throws DataException {
1523
        try {
1524
            List types;
1525
            if (isEditing()) {
1526
                types = new ArrayList();
1527
                Iterator it = featureTypes.iterator();
1528
                while (it.hasNext()) {
1529
                    FeatureType type = (FeatureType) it.next();
1530
                    FeatureType typeaux =
1531
                        featureTypeManager.getType(type.getId());
1532
                    if (typeaux != null) {
1533
                        types.add(typeaux);
1534
                    } else {
1535
                        types.add(type);
1536
                    }
1537
                }
1538
                it = featureTypeManager.newsIterator();
1539
                while (it.hasNext()) {
1540
                    FeatureType type = (FeatureType) it.next();
1541
                    types.add(type);
1542
                }
1543
            } else {
1544
                types = this.transforms.getFeatureTypes();
1545
                if (types == null) {
1546
                    types = featureTypes;
1547
                }
1548
            }
1549
            return Collections.unmodifiableList(types);
1550
        } catch (Exception e) {
1551
            throw new GetFeatureTypeException(e, getName());
1552
        }
1553
    }
1554

    
1555
    public List getProviderFeatureTypes() throws DataException {
1556
        return Collections.unmodifiableList(this.featureTypes);
1557
    }
1558

    
1559
    public Feature createFeature(FeatureProvider data) throws DataException {
1560
        DefaultFeature feature = new DefaultFeature(this, data);
1561
        return feature;
1562
    }
1563

    
1564
    public Feature createFeature(FeatureProvider data, FeatureType type)
1565
        throws DataException {
1566
        // FIXME: falta por implementar
1567
        // Comprobar si es un subtipo del feature de data
1568
        // y construir un feature usando el subtipo.
1569
        // Probablemente requiera generar una copia del data.
1570
        throw new NotYetImplemented();
1571
    }
1572

    
1573
    public EditableFeature createNewFeature(FeatureType type,
1574
        Feature defaultValues) throws DataException {
1575
        try {
1576
            FeatureProvider data = createNewFeatureProvider(type);
1577
            DefaultEditableFeature feature =
1578
                new DefaultEditableFeature(this, data);
1579
            feature.initializeValues(defaultValues);
1580
            return feature;
1581
        } catch (Exception e) {
1582
            throw new CreateFeatureException(e, getName());
1583
        }
1584
    }
1585

    
1586
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1587
        throws DataException {
1588
        type = this.fixFeatureType((DefaultFeatureType) type);
1589
        FeatureProvider data = this.provider.createFeatureProvider(type);
1590
        data.setNew(true);
1591
        if (type.hasOID() && (data.getOID() == null)) {
1592
            data.setOID(this.provider.createNewOID());
1593
        } else {
1594
            data.setOID(this.getTemporalOID());
1595
        }
1596
        return data;
1597

    
1598
    }
1599

    
1600
    public EditableFeature createNewFeature(FeatureType type,
1601
        boolean defaultValues) throws DataException {
1602
        try {
1603
            FeatureProvider data = createNewFeatureProvider(type);
1604
            DefaultEditableFeature feature =
1605
                new DefaultEditableFeature(this, data);
1606
            if (defaultValues) {
1607
                feature.initializeValues();
1608
            }
1609
            return feature;
1610
        } catch (Exception e) {
1611
            throw new CreateFeatureException(e, getName());
1612
        }
1613
    }
1614

    
1615
    public EditableFeature createNewFeature(boolean defaultValues)
1616
        throws DataException {
1617
        return this.createNewFeature(this.getDefaultFeatureType(),
1618
            defaultValues);
1619
    }
1620

    
1621
    public EditableFeature createNewFeature() throws DataException {
1622
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1623
    }
1624

    
1625
    public EditableFeatureType createFeatureType() {
1626
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1627
        return ftype;
1628
    }
1629

    
1630
    public EditableFeatureType createFeatureType(String id) {
1631
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1632
        return ftype;
1633
    }
1634

    
1635
    //
1636
    // ====================================================================
1637
    // Index related methods
1638
    //
1639

    
1640
    public FeatureIndexes getIndexes() {
1641
        return this.indexes;
1642
    }
1643

    
1644
    public FeatureIndex createIndex(FeatureType featureType,
1645
        String attributeName, String indexName) throws DataException {
1646
        return createIndex(null, featureType, attributeName, indexName);
1647
    }
1648

    
1649
    public FeatureIndex createIndex(String indexTypeName,
1650
        FeatureType featureType, String attributeName, String indexName)
1651
        throws DataException {
1652

    
1653
        return createIndex(indexTypeName, featureType, attributeName,
1654
            indexName, false, null);
1655
    }
1656

    
1657
    public FeatureIndex createIndex(FeatureType featureType,
1658
        String attributeName, String indexName, Observer observer)
1659
        throws DataException {
1660
        return createIndex(null, featureType, attributeName, indexName,
1661
            observer);
1662
    }
1663

    
1664
    public FeatureIndex createIndex(String indexTypeName,
1665
        FeatureType featureType, String attributeName, String indexName,
1666
        final Observer observer) throws DataException {
1667

    
1668
        return createIndex(indexTypeName, featureType, attributeName,
1669
            indexName, true, observer);
1670
    }
1671

    
1672
    private FeatureIndex createIndex(String indexTypeName,
1673
        FeatureType featureType, String attributeName, String indexName,
1674
        boolean background, final Observer observer) throws DataException {
1675

    
1676
        checkNotInAppendMode();
1677
        FeatureIndexProviderServices index = null;
1678
        index =
1679
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1680
                featureType, indexName,
1681
                featureType.getAttributeDescriptor(attributeName));
1682

    
1683
        try {
1684
            index.fill(background, observer);
1685
        } catch (FeatureIndexException e) {
1686
            throw new InitializeException(index.getName(), e);
1687
        }
1688

    
1689
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1690
        return index;
1691
    }
1692

    
1693
    //
1694
    // ====================================================================
1695
    // Transforms related methods
1696
    //
1697

    
1698
    public FeatureStoreTransforms getTransforms() {
1699
        return this.transforms;
1700
    }
1701

    
1702
    public FeatureQuery createFeatureQuery() {
1703
        return new DefaultFeatureQuery();
1704
    }
1705

    
1706
    public DataQuery createQuery() {
1707
        return createFeatureQuery();
1708
    }
1709

    
1710
    //
1711
    // ====================================================================
1712
    // UndoRedo related methods
1713
    //
1714

    
1715
    public boolean canRedo() {
1716
        return commands.canRedo();
1717
    }
1718

    
1719
    public boolean canUndo() {
1720
        return commands.canUndo();
1721
    }
1722

    
1723
    public void redo(int num) throws RedoException {
1724
        commands.redo(num);
1725
    }
1726

    
1727
    public void undo(int num) throws UndoException {
1728
        commands.undo(num);
1729
    }
1730

    
1731
    //
1732
    // ====================================================================
1733
    // Metadata related methods
1734
    //
1735

    
1736
    public Object getMetadataID() {
1737
        return this.provider.getSourceId();
1738
    }
1739

    
1740
    public void delegate(DynObject dynObject) {
1741
        this.metadata.delegate(dynObject);
1742
    }
1743

    
1744
    public DynClass getDynClass() {
1745
        return this.metadata.getDynClass();
1746
    }
1747

    
1748
    public Object getDynValue(String name) throws DynFieldNotFoundException {
1749
        if (this.metadata.hasDynValue(name)) {
1750
            return this.metadata.getDynValue(name);
1751
        }
1752
        if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1753
            return this.provider.getProviderName();
1754
        } else
1755
            if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1756
                return this.provider.getSourceId();
1757
            } else
1758
                if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1759
                    try {
1760
                        return this.getDefaultFeatureType();
1761
                    } catch (DataException e) {
1762
                        return null;
1763
                    }
1764
                }
1765
        return this.metadata.getDynValue(name);
1766
    }
1767

    
1768
    public boolean hasDynValue(String name) {
1769
        return this.metadata.hasDynValue(name);
1770
    }
1771

    
1772
    public void implement(DynClass dynClass) {
1773
        this.metadata.implement(dynClass);
1774
    }
1775

    
1776
    public Object invokeDynMethod(String name, DynObject context)
1777
        throws DynMethodException {
1778
        return this.metadata.invokeDynMethod(this, name, context);
1779
    }
1780

    
1781
    public Object invokeDynMethod(int code, DynObject context)
1782
        throws DynMethodException {
1783
        return this.metadata.invokeDynMethod(this, code, context);
1784
    }
1785

    
1786
    public void setDynValue(String name, Object value)
1787
        throws DynFieldNotFoundException {
1788
        this.metadata.setDynValue(name, value);
1789

    
1790
    }
1791

    
1792
    /*
1793
     * (non-Javadoc)
1794
     * 
1795
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1796
     */
1797
    public Set getMetadataChildren() {
1798
        return this.metadataChildren;
1799
    }
1800

    
1801
    /*
1802
     * (non-Javadoc)
1803
     * 
1804
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1805
     */
1806
    public String getMetadataName() {
1807
        return this.provider.getProviderName();
1808
    }
1809

    
1810
    public FeatureTypeManager getFeatureTypeManager() {
1811
        return this.featureTypeManager;
1812
    }
1813

    
1814
    public long getFeatureCount() throws DataException {
1815
        if (featureCount == null) {
1816
            featureCount = new Long(this.provider.getFeatureCount());
1817
        }
1818
        if (this.isEditing() && !this.isAppending()) {
1819
            return featureCount.longValue()
1820
                - this.featureManager.getDeltaSize();
1821
        }
1822
        return featureCount.longValue();
1823
    }
1824

    
1825
    private Long getTemporalOID() {
1826
        return new Long(this.temporalOid++);
1827
    }
1828

    
1829
    public FeatureType getProviderFeatureType(String featureTypeId) {
1830
        if (featureTypeId == null) {
1831
            return this.defaultFeatureType;
1832
        }
1833
        FeatureType type;
1834
        Iterator iter = this.featureTypes.iterator();
1835
        while (iter.hasNext()) {
1836
            type = (FeatureType) iter.next();
1837
            if (type.getId().equals(featureTypeId)) {
1838
                return type;
1839
            }
1840
        }
1841
        return null;
1842
    }
1843

    
1844
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1845
        return ((DefaultFeature) feature).getData();
1846
    }
1847

    
1848
    public DataStore getStore() {
1849
        return this;
1850
    }
1851

    
1852
    public FeatureStore getFeatureStore() {
1853
        return this;
1854
    }
1855

    
1856
    public void createCache(String name, DynObject parameters)
1857
        throws DataException {
1858
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1859
        if (cache == null) {
1860
            throw new CreateException("FeaureCacheProvider", null);
1861
        }
1862
        cache.apply(this, provider);
1863
        provider = cache;
1864

    
1865
        featureCount = null;
1866
    }
1867

    
1868
    public FeatureCache getCache() {
1869
        return cache;
1870
    }
1871

    
1872
    public void clear() {
1873
        if (metadata != null) {
1874
            metadata.clear();
1875
        }
1876
    }
1877

    
1878
    public String getName() {
1879
        return this.provider.getName();
1880
    }
1881

    
1882
    public String getFullName() {
1883
        return this.provider.getFullName();
1884
    }
1885

    
1886
    public String getProviderName() {
1887
        return this.provider.getProviderName();
1888
    }
1889

    
1890
    public boolean isKnownEnvelope() {
1891
        return this.provider.isKnownEnvelope();
1892
    }
1893

    
1894
    public boolean hasRetrievedFeaturesLimit() {
1895
        return this.provider.hasRetrievedFeaturesLimit();
1896
    }
1897

    
1898
    public int getRetrievedFeaturesLimit() {
1899
        return this.provider.getRetrievedFeaturesLimit();
1900
    }
1901
}