Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 37595

History | View | Annotate | Download (67.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.Map.Entry;
39
import java.util.Set;
40

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

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

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

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

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

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

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

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

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

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

    
175
    private DefaultDataManager dataManager = null;
176

    
177
    private FeatureStoreProvider provider = null;
178

    
179
    private DefaultFeatureIndexes indexes;
180

    
181
    private DefaultFeatureStoreTransforms transforms;
182

    
183
    DelegatedDynObject metadata;
184
    
185
    private Set metadataChildren;
186

    
187
    private Long featureCount = null;
188

    
189
    private long temporalOid = 0;
190

    
191
    private FeatureCacheProvider cache;
192

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

    
202
    public DefaultFeatureStore() {
203

    
204
    }
205

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

    
209
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
210

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

    
215
        this.dataManager = (DefaultDataManager) dataManager;
216

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

    
225
    }
226

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
344
    public Envelope getEnvelope() throws DataException {
345
        if (this.mode == MODE_FULLEDIT) {
346
            return this.spatialManager.getEnvelope();
347
        }
348
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
349
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
350
        }
351
        return this.provider.getEnvelope();
352
    }
353

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

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

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

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

    
409
        }
410

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

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

    
418
    }
419

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

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

    
432
        try {
433

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

    
473
                }
474

    
475
            }
476

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

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

    
490
        } catch (InitializeException e) {
491
            throw new PersistenceException(e);
492
        } catch (DataException e) {
493
            throw new PersistenceException(e);
494
        }
495

    
496
    }
497

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

    
508
            definition.addDynFieldObject("parameters")
509
                .setClassOfValue(DynObject.class).setMandatory(true)
510
                .setPersistent(true);
511

    
512
            definition.addDynFieldObject("selection")
513
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
514
                .setPersistent(true);
515

    
516
            definition.addDynFieldObject("transforms")
517
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
518
                .setMandatory(true).setPersistent(true);
519

    
520
            definition.addDynFieldMap("evaluatedAttributes")
521
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
522
                .setMandatory(false).setPersistent(true);
523

    
524
            definition.addDynFieldString("defaultFeatureTypeId")
525
                .setMandatory(true).setPersistent(true);
526
        }
527
    }
528

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

    
539
    //
540
    // ====================================================================
541
    // Gestion de la seleccion
542
    //
543

    
544
    public void setSelection(DataSet selection) throws DataException {
545
        this.setSelection((FeatureSet) selection);
546
    }
547

    
548
    public DataSet createSelection() throws DataException {
549
        return createFeatureSelection();
550
    }
551

    
552
    public DataSet getSelection() throws DataException {
553
        return this.getFeatureSelection();
554
    }
555

    
556
    public void setSelection(FeatureSet selection) throws DataException {
557
        setSelection(selection, true);
558
    }
559

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

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

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

    
619
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
620
    }
621

    
622
    public FeatureSelection createFeatureSelection() throws DataException {
623
        return this.provider.createFeatureSelection();
624
    }
625

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

    
634
    //
635
    // ====================================================================
636
    // Gestion de notificaciones
637
    //
638

    
639
    public void notifyChange(String notification) {
640
        if (delegateObservable != null) {
641
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
642
        }
643

    
644
    }
645

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

    
655
    public void notifyChange(String notification, Feature feature) {
656
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
657
            feature));
658
    }
659

    
660
    public void notifyChange(String notification, Command command) {
661
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
662
            command));
663
    }
664

    
665
    public void notifyChange(String notification, EditableFeatureType type) {
666
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
667
            type));
668
    }
669

    
670
    public void notifyChange(FeatureStoreNotification storeNotification) {
671
        delegateObservable.notifyObservers(storeNotification);
672
    }
673

    
674
    public void notifyChange(String notification, Resource resource) {
675
        notifyChange(new DefaultFeatureStoreNotification(this,
676
            DataStoreNotification.RESOURCE_CHANGED));
677
    }
678

    
679
    //
680
    // ====================================================================
681
    // Gestion de bloqueos
682
    //
683

    
684
    public boolean isLocksSupported() {
685
        return this.provider.isLocksSupported();
686
    }
687

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

    
699
    //
700
    // ====================================================================
701
    // Interface Observable
702
    //
703

    
704
    public void disableNotifications() {
705
        this.delegateObservable.disableNotifications();
706

    
707
    }
708

    
709
    public void enableNotifications() {
710
        this.delegateObservable.enableNotifications();
711
    }
712

    
713
    public void beginComplexNotification() {
714
        this.delegateObservable.beginComplexNotification();
715

    
716
    }
717

    
718
    public void endComplexNotification() {
719
        this.delegateObservable.endComplexNotification();
720

    
721
    }
722

    
723
    public void addObserver(Observer observer) {
724
        if (delegateObservable != null) {
725
            this.delegateObservable.addObserver(observer);
726
        }
727
    }
728

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

    
735
    public void deleteObservers() {
736
        this.delegateObservable.deleteObservers();
737

    
738
    }
739

    
740
    //
741
    // ====================================================================
742
    // Interface Observer
743
    //
744
    // Usado para observar:
745
    // - su seleccion
746
    // - sus bloqueos
747
    // - sus recursos
748
    //
749

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

    
759
        } else
760
            if (observable instanceof FeatureStoreProvider) {
761
                if (observable == this.provider) {
762

    
763
                }
764

    
765
            }
766
    }
767

    
768
    //
769
    // ====================================================================
770
    // Edicion
771
    //
772

    
773
    private void newVersionOfUpdate() {
774
        this.versionOfUpdate++;
775
    }
776

    
777
    private long currentVersionOfUpdate() {
778
        return this.versionOfUpdate;
779
    }
780

    
781
    private void checkInEditingMode() throws NeedEditingModeException {
782
        if (mode != MODE_FULLEDIT) {
783
            throw new NeedEditingModeException(this.getName());
784
        }
785
    }
786

    
787
    private void checkNotInAppendMode() throws IllegalStateException {
788
        if (mode == MODE_APPEND) {
789
            throw new IllegalStateException(this.getName());
790
        }
791
    }
792

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

    
802
    private void exitEditingMode() {
803
        if (commands != null) {
804
            commands.clear();
805
            commands = null;
806
        }
807

    
808
        if (featureTypeManager != null) {
809
            featureTypeManager.dispose();
810
            featureTypeManager = null;
811

    
812
        }
813

    
814
        // TODO implementar un dispose para estos dos
815
        featureManager = null;
816
        spatialManager = null;
817

    
818
        featureCount = null;
819

    
820
        mode = MODE_QUERY;
821
        hasStrongChanges = true; // Lo deja a true por si las moscas
822
        hasInserts = true;
823
    }
824

    
825
    synchronized public void edit() throws DataException {
826
        edit(MODE_FULLEDIT);
827
    }
828

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

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

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

    
880
    private void invalidateIndexes() {
881
        setIndexesValidStatus(false);
882
    }
883

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

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

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

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

    
937
    public boolean isEditing() {
938
        return mode == MODE_FULLEDIT;
939
    }
940

    
941
    public boolean isAppending() {
942
        return mode == MODE_APPEND;
943
    }
944

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

    
956
            FeatureType oldt = type.getSource().getCopy();
957
            FeatureType newt = type.getNotEditableCopy();
958
            commands.update(newt, oldt);
959

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

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

    
994
    private static EditableFeature lastChangedFeature = null;
995

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

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

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

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

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

    
1089
    synchronized public void redo() throws RedoException {
1090
        Command redo = commands.getNextRedoCommand();
1091
        try {
1092
            checkInEditingMode();
1093
        } catch (NeedEditingModeException ex) {
1094
            throw new RedoException(redo, ex);
1095
        }
1096
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1097
        newVersionOfUpdate();
1098
        commands.redo();
1099
        hasStrongChanges = true;
1100
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1101
    }
1102

    
1103
    synchronized public void undo() throws UndoException {
1104
        Command undo = commands.getNextUndoCommand();
1105
        try {
1106
            checkInEditingMode();
1107
        } catch (NeedEditingModeException ex) {
1108
            throw new UndoException(undo, ex);
1109
        }
1110
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1111
        newVersionOfUpdate();
1112
        commands.undo();
1113
        hasStrongChanges = true;
1114
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1115
    }
1116

    
1117
    public List getRedoInfos() {
1118
        if (isEditing() && (commands != null)) {
1119
            return commands.getRedoInfos();
1120
        } else {
1121
            return null;
1122
        }
1123
    }
1124

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

    
1133
    public synchronized FeatureCommandsStack getCommandsStack()
1134
        throws DataException {
1135
        checkInEditingMode();
1136
        return commands;
1137
    }
1138

    
1139
    synchronized public void cancelEditing() throws DataException {
1140
        spatialManager.cancelModifies();
1141
        try {
1142
            checkInEditingMode();
1143

    
1144
            boolean clearSelection = this.hasStrongChanges;
1145
            if (this.selection instanceof FeatureReferenceSelection) {
1146
                clearSelection = this.hasInserts;
1147
            }
1148
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1149
            exitEditingMode();
1150
            if (clearSelection) {
1151
                ((FeatureSelection) this.getSelection()).deselectAll();
1152
            }
1153
            updateIndexes();
1154
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1155
        } catch (Exception e) {
1156
            throw new StoreCancelEditingException(e, this.getName());
1157
        }
1158
    }
1159

    
1160
    synchronized public void finishEditing() throws DataException {
1161
        LOG.debug("finish editing of mode: {}", new Integer(mode));
1162
        try {
1163
            switch (mode) {
1164
            case MODE_QUERY:
1165
                throw new NeedEditingModeException(this.getName());
1166

    
1167
            case MODE_APPEND:
1168
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1169
                provider.endAppend();
1170
                exitEditingMode();
1171
                updateIndexes();
1172
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1173
                break;
1174

    
1175
            case MODE_FULLEDIT:
1176
                if (hasStrongChanges && !this.allowWrite()) {
1177
                    throw new WriteNotAllowedException(getName());
1178
                }
1179
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1180
                if (hasStrongChanges) {
1181
                    validateFeatures(Feature.FINISH_EDITING);
1182
                    provider.performChanges(featureManager.getDeleted(),
1183
                        featureManager.getInserted(),
1184
                        featureManager.getUpdated(),
1185
                        featureTypeManager.getFeatureTypesChanged());
1186
                }
1187
                exitEditingMode();
1188
                updateIndexes();
1189
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1190
                break;
1191
            }
1192
        } catch (Exception e) {
1193
            throw new FinishEditingException(e);
1194
        }
1195
    }
1196

    
1197
    public void beginEditingGroup(String description)
1198
        throws NeedEditingModeException {
1199
        checkInEditingMode();
1200
        commands.startComplex(description);
1201
    }
1202

    
1203
    public void endEditingGroup() throws NeedEditingModeException {
1204
        checkInEditingMode();
1205
        commands.endComplex();
1206
    }
1207

    
1208
    public boolean isAppendModeSupported() {
1209
        return this.provider.supportsAppendMode();
1210
    }
1211

    
1212
    public void export(DataServerExplorer explorer, String provider,
1213
        NewFeatureStoreParameters params) throws DataException {
1214

    
1215
        if (this.getFeatureTypes().size() != 1) {
1216
            throw new NotYetImplemented(
1217
                "export whith more than one type not yet implemented");
1218
        }
1219
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1220
        FeatureStore target = null;
1221
        FeatureSet features = null;
1222
        DisposableIterator iterator = null;
1223
        try {
1224
            FeatureType type = this.getDefaultFeatureType();
1225
            if ((params.getDefaultFeatureType() == null)
1226
                || (params.getDefaultFeatureType().size() == 0)) {
1227
                params.setDefaultFeatureType(type.getEditable());
1228

    
1229
            }
1230
            explorer.add(provider, params, true);
1231

    
1232
            DataManager manager = DALLocator.getDataManager();
1233
            target = (FeatureStore) manager.openStore(provider, params);
1234
            FeatureType targetType = target.getDefaultFeatureType();
1235

    
1236
            target.edit(MODE_APPEND);
1237
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1238
            if (featureSelection.getSize() > 0) {
1239
                features = this.getFeatureSelection();
1240
            } else {
1241
                if ((pk != null) && (pk.length > 0)) {
1242
                    FeatureQuery query = createFeatureQuery();
1243
                    for (int i = 0; i < pk.length; i++) {
1244
                        query.getOrder().add(pk[i].getName(), true);
1245
                    }
1246
                    features = this.getFeatureSet(query);
1247
                } else {
1248
                    features = this.getFeatureSet();
1249
                }
1250
            }
1251
            iterator = features.fastIterator();
1252
            while (iterator.hasNext()) {
1253
                DefaultFeature feature = (DefaultFeature) iterator.next();
1254
                target.insert(target.createNewFeature(targetType, feature));
1255
            }
1256
            target.finishEditing();
1257
            target.dispose();
1258
        } catch (Exception e) {
1259
            throw new DataExportException(e, params.toString());
1260
        } finally {
1261
            dispose(iterator);
1262
            dispose(features);
1263
            dispose(target);
1264
        }
1265
    }
1266

    
1267
    //
1268
    // ====================================================================
1269
    // Obtencion de datos
1270
    // getDataCollection, getFeatureCollection
1271
    //
1272

    
1273
    public DataSet getDataSet() throws DataException {
1274
        checkNotInAppendMode();
1275
        FeatureQuery query =
1276
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1277
        return new DefaultFeatureSet(this, query);
1278
    }
1279

    
1280
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1281
        checkNotInAppendMode();
1282
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1283
    }
1284

    
1285
    public void getDataSet(Observer observer) throws DataException {
1286
        checkNotInAppendMode();
1287
        this.getFeatureSet(null, observer);
1288
    }
1289

    
1290
    public void getDataSet(DataQuery dataQuery, Observer observer)
1291
        throws DataException {
1292
        checkNotInAppendMode();
1293
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1294
    }
1295

    
1296
    public FeatureSet getFeatureSet() throws DataException {
1297
        checkNotInAppendMode();
1298
        FeatureQuery query =
1299
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1300
        return new DefaultFeatureSet(this, query);
1301
    }
1302

    
1303
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1304
        throws DataException {
1305
        checkNotInAppendMode();
1306
        return new DefaultFeatureSet(this, featureQuery);
1307
    }
1308

    
1309
    public void accept(Visitor visitor) throws BaseException {
1310
        FeatureSet set = getFeatureSet();
1311
        try {
1312
            set.accept(visitor);
1313
        } finally {
1314
            set.dispose();
1315
        }
1316
    }
1317

    
1318
    public void accept(Visitor visitor, DataQuery dataQuery)
1319
        throws BaseException {
1320
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1321
        try {
1322
            set.accept(visitor);
1323
        } finally {
1324
            set.dispose();
1325
        }
1326
    }
1327

    
1328
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1329
        throws DataException {
1330
        DefaultFeatureType fType =
1331
            (DefaultFeatureType) this.getFeatureType(featureQuery
1332
                .getFeatureTypeId());
1333
        if ((featureQuery.getAttributeNames() != null)
1334
            && (featureQuery.getAttributeNames().length > 0)) {
1335
            return fType.getSubtype(featureQuery.getAttributeNames());
1336
        }
1337
        return fType;
1338
    }
1339

    
1340
    public void getFeatureSet(Observer observer) throws DataException {
1341
        checkNotInAppendMode();
1342
        this.getFeatureSet(null, observer);
1343
    }
1344

    
1345
    public void getFeatureSet(FeatureQuery query, Observer observer)
1346
        throws DataException {
1347
        class LoadInBackGround implements Runnable {
1348

    
1349
            private FeatureStore store;
1350
            private FeatureQuery query;
1351
            private Observer observer;
1352

    
1353
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1354
                Observer observer) {
1355
                this.store = store;
1356
                this.query = query;
1357
                this.observer = observer;
1358
            }
1359

    
1360
            void notify(FeatureStoreNotification theNotification) {
1361
                observer.update(store, theNotification);
1362
                return;
1363
            }
1364

    
1365
            public void run() {
1366
                FeatureSet set = null;
1367
                try {
1368
                    set = store.getFeatureSet(query);
1369
                    notify(new DefaultFeatureStoreNotification(store,
1370
                        FeatureStoreNotification.LOAD_FINISHED, set));
1371
                } catch (Exception e) {
1372
                    notify(new DefaultFeatureStoreNotification(store,
1373
                        FeatureStoreNotification.LOAD_FINISHED, e));
1374
                } finally {
1375
                    dispose(set);
1376
                }
1377
            }
1378
        }
1379

    
1380
        checkNotInAppendMode();
1381
        if (query == null) {
1382
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1383
        }
1384
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1385
        Thread thread = new Thread(task, "Load Feature Set in background");
1386
        thread.start();
1387
    }
1388

    
1389
    public Feature getFeatureByReference(FeatureReference reference)
1390
        throws DataException {
1391
        checkNotInAppendMode();
1392
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1393
        FeatureType featureType;
1394
        if (ref.getFeatureTypeId() == null) {
1395
            featureType = this.getDefaultFeatureType();
1396
        } else {
1397
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1398
        }
1399
        return this.getFeatureByReference(reference, featureType);
1400
    }
1401

    
1402
    public Feature getFeatureByReference(FeatureReference reference,
1403
        FeatureType featureType) throws DataException {
1404
        checkNotInAppendMode();
1405
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1406
        if (!this.transforms.isEmpty()) {
1407

    
1408
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1409

    
1410
        }
1411
        // TODO comprobar que el id es de este store
1412

    
1413
        if (this.mode == MODE_FULLEDIT) {
1414
            Feature f = featureManager.get(reference, this, featureType);
1415
            if (f != null) {
1416
                return f;
1417
            }
1418
        }
1419
        DefaultFeature feature =
1420
            new DefaultFeature(this,
1421
                this.provider.getFeatureProviderByReference(
1422
                    (FeatureReferenceProviderServices) reference, featureType));
1423

    
1424
        if (!this.transforms.isEmpty()) {
1425
            return this.transforms.applyTransform(feature, featureType);
1426
        }
1427
        return feature;
1428
    }
1429

    
1430
    //
1431
    // ====================================================================
1432
    // Gestion de features
1433
    //
1434

    
1435
    private FeatureType fixFeatureType(DefaultFeatureType type)
1436
        throws DataException {
1437
        FeatureType original = this.getDefaultFeatureType();
1438

    
1439
        if ((type == null) || type.equals(original)) {
1440
            return original;
1441
        } else {
1442
            if (!type.isSubtypeOf(original)) {
1443
                Iterator iter = this.getFeatureTypes().iterator();
1444
                FeatureType tmpType;
1445
                boolean found = false;
1446
                while (iter.hasNext()) {
1447
                    tmpType = (FeatureType) iter.next();
1448
                    if (type.equals(tmpType)) {
1449
                        return type;
1450

    
1451
                    } else
1452
                        if (type.isSubtypeOf(tmpType)) {
1453
                            found = true;
1454
                            original = tmpType;
1455
                            break;
1456
                        }
1457

    
1458
                }
1459
                if (!found) {
1460
                    throw new IllegalFeatureTypeException(getName());
1461
                }
1462
            }
1463
        }
1464

    
1465
        // Checks that type has all fields of pk
1466
        // else add the missing attributes at the end.
1467
        if (!original.hasOID()) {
1468
            // Gets original pk attributes
1469
            DefaultEditableFeatureType edOriginal =
1470
                (DefaultEditableFeatureType) original.getEditable();
1471
            FeatureAttributeDescriptor orgAttr;
1472
            Iterator edOriginalIter = edOriginal.iterator();
1473
            while (edOriginalIter.hasNext()) {
1474
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1475
                if (!orgAttr.isPrimaryKey()) {
1476
                    edOriginalIter.remove();
1477
                }
1478
            }
1479

    
1480
            // Checks if all pk attributes are in type
1481
            Iterator typeIterator;
1482
            edOriginalIter = edOriginal.iterator();
1483
            FeatureAttributeDescriptor attr;
1484
            while (edOriginalIter.hasNext()) {
1485
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1486
                typeIterator = type.iterator();
1487
                while (typeIterator.hasNext()) {
1488
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1489
                    if (attr.getName().equals(orgAttr.getName())) {
1490
                        edOriginalIter.remove();
1491
                        break;
1492
                    }
1493
                }
1494
            }
1495

    
1496
            // add missing pk attributes if any
1497
            if (edOriginal.size() > 0) {
1498
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1499
                DefaultEditableFeatureType edType =
1500
                    (DefaultEditableFeatureType) original.getEditable();
1501
                edType.clear();
1502
                edType.addAll(type);
1503
                edType.addAll(edOriginal);
1504
                if (!isEditable) {
1505
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1506
                }
1507
            }
1508

    
1509
        }
1510

    
1511
        return type;
1512
    }
1513

    
1514
    public void validateFeatures(int mode) throws DataException {
1515
        FeatureSet collection = null;
1516
        DisposableIterator iter = null;
1517
        try {
1518
            checkNotInAppendMode();
1519
            collection = this.getFeatureSet();
1520
            iter = collection.fastIterator();
1521
            long previousVersionOfUpdate = currentVersionOfUpdate();
1522
            while (iter.hasNext()) {
1523
                ((DefaultFeature) iter.next()).validate(mode);
1524
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1525
                    throw new ConcurrentDataModificationException(getName());
1526
                }
1527
            }
1528
        } catch (Exception e) {
1529
            throw new ValidateFeaturesException(e, getName());
1530
        } finally {
1531
            dispose(iter);
1532
            dispose(collection);
1533
        }
1534
    }
1535

    
1536
    public FeatureType getDefaultFeatureType() throws DataException {
1537
        try {
1538
            if (isEditing()) {
1539
                FeatureType auxFeatureType =
1540
                    featureTypeManager.getType(defaultFeatureType.getId());
1541
                if (auxFeatureType != null) {
1542
                    return auxFeatureType;
1543
                }
1544
            }
1545
            FeatureType type = this.transforms.getDefaultFeatureType();
1546
            if (type != null) {
1547
                return type;
1548
            }
1549
            return defaultFeatureType;
1550
        } catch (Exception e) {
1551
            throw new GetFeatureTypeException(e, getName());
1552
        }
1553
    }
1554

    
1555
    public FeatureType getFeatureType(String featureTypeId)
1556
        throws DataException {
1557
        if (featureTypeId == null) {
1558
            return this.getDefaultFeatureType();
1559
        }
1560
        try {
1561
            if (isEditing()) {
1562
                FeatureType auxFeatureType =
1563
                    featureTypeManager.getType(featureTypeId);
1564
                if (auxFeatureType != null) {
1565
                    return auxFeatureType;
1566
                }
1567
            }
1568
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1569
            if (type != null) {
1570
                return type;
1571
            }
1572
            Iterator iter = this.featureTypes.iterator();
1573
            while (iter.hasNext()) {
1574
                type = (FeatureType) iter.next();
1575
                if (type.getId().equals(featureTypeId)) {
1576
                    return type;
1577
                }
1578
            }
1579
            return null;
1580
        } catch (Exception e) {
1581
            throw new GetFeatureTypeException(e, getName());
1582
        }
1583
    }
1584

    
1585
    public FeatureType getProviderDefaultFeatureType() {
1586
        return defaultFeatureType;
1587
    }
1588

    
1589
    public List getFeatureTypes() throws DataException {
1590
        try {
1591
            List types;
1592
            if (isEditing()) {
1593
                types = new ArrayList();
1594
                Iterator it = featureTypes.iterator();
1595
                while (it.hasNext()) {
1596
                    FeatureType type = (FeatureType) it.next();
1597
                    FeatureType typeaux =
1598
                        featureTypeManager.getType(type.getId());
1599
                    if (typeaux != null) {
1600
                        types.add(typeaux);
1601
                    } else {
1602
                        types.add(type);
1603
                    }
1604
                }
1605
                it = featureTypeManager.newsIterator();
1606
                while (it.hasNext()) {
1607
                    FeatureType type = (FeatureType) it.next();
1608
                    types.add(type);
1609
                }
1610
            } else {
1611
                types = this.transforms.getFeatureTypes();
1612
                if (types == null) {
1613
                    types = featureTypes;
1614
                }
1615
            }
1616
            return Collections.unmodifiableList(types);
1617
        } catch (Exception e) {
1618
            throw new GetFeatureTypeException(e, getName());
1619
        }
1620
    }
1621

    
1622
    public List getProviderFeatureTypes() throws DataException {
1623
        return Collections.unmodifiableList(this.featureTypes);
1624
    }
1625

    
1626
    public Feature createFeature(FeatureProvider data) throws DataException {
1627
        DefaultFeature feature = new DefaultFeature(this, data);
1628
        return feature;
1629
    }
1630

    
1631
    public Feature createFeature(FeatureProvider data, FeatureType type)
1632
        throws DataException {
1633
        // FIXME: falta por implementar
1634
        // Comprobar si es un subtipo del feature de data
1635
        // y construir un feature usando el subtipo.
1636
        // Probablemente requiera generar una copia del data.
1637
        throw new NotYetImplemented();
1638
    }
1639

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

    
1653
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1654
        throws DataException {
1655
        type = this.fixFeatureType((DefaultFeatureType) type);
1656
        FeatureProvider data = this.provider.createFeatureProvider(type);
1657
        data.setNew(true);
1658
        if (type.hasOID() && (data.getOID() == null)) {
1659
            data.setOID(this.provider.createNewOID());
1660
        } else {
1661
            data.setOID(this.getTemporalOID());
1662
        }
1663
        return data;
1664

    
1665
    }
1666

    
1667
    public EditableFeature createNewFeature(FeatureType type,
1668
        boolean defaultValues) throws DataException {
1669
        try {
1670
            FeatureProvider data = createNewFeatureProvider(type);
1671
            DefaultEditableFeature feature =
1672
                new DefaultEditableFeature(this, data);
1673
            if (defaultValues) {
1674
                feature.initializeValues();
1675
            }
1676
            return feature;
1677
        } catch (Exception e) {
1678
            throw new CreateFeatureException(e, getName());
1679
        }
1680
    }
1681

    
1682
    public EditableFeature createNewFeature(boolean defaultValues)
1683
        throws DataException {
1684
        return this.createNewFeature(this.getDefaultFeatureType(),
1685
            defaultValues);
1686
    }
1687

    
1688
    public EditableFeature createNewFeature() throws DataException {
1689
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1690
    }
1691

    
1692
    public EditableFeatureType createFeatureType() {
1693
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1694
        return ftype;
1695
    }
1696

    
1697
    public EditableFeatureType createFeatureType(String id) {
1698
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1699
        return ftype;
1700
    }
1701

    
1702
    //
1703
    // ====================================================================
1704
    // Index related methods
1705
    //
1706

    
1707
    public FeatureIndexes getIndexes() {
1708
        return this.indexes;
1709
    }
1710

    
1711
    public FeatureIndex createIndex(FeatureType featureType,
1712
        String attributeName, String indexName) throws DataException {
1713
        return createIndex(null, featureType, attributeName, indexName);
1714
    }
1715

    
1716
    public FeatureIndex createIndex(String indexTypeName,
1717
        FeatureType featureType, String attributeName, String indexName)
1718
        throws DataException {
1719

    
1720
        return createIndex(indexTypeName, featureType, attributeName,
1721
            indexName, false, null);
1722
    }
1723

    
1724
    public FeatureIndex createIndex(FeatureType featureType,
1725
        String attributeName, String indexName, Observer observer)
1726
        throws DataException {
1727
        return createIndex(null, featureType, attributeName, indexName,
1728
            observer);
1729
    }
1730

    
1731
    public FeatureIndex createIndex(String indexTypeName,
1732
        FeatureType featureType, String attributeName, String indexName,
1733
        final Observer observer) throws DataException {
1734

    
1735
        return createIndex(indexTypeName, featureType, attributeName,
1736
            indexName, true, observer);
1737
    }
1738

    
1739
    private FeatureIndex createIndex(String indexTypeName,
1740
        FeatureType featureType, String attributeName, String indexName,
1741
        boolean background, final Observer observer) throws DataException {
1742

    
1743
        checkNotInAppendMode();
1744
        FeatureIndexProviderServices index = null;
1745
        index =
1746
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1747
                featureType, indexName,
1748
                featureType.getAttributeDescriptor(attributeName));
1749

    
1750
        try {
1751
            index.fill(background, observer);
1752
        } catch (FeatureIndexException e) {
1753
            throw new InitializeException(index.getName(), e);
1754
        }
1755

    
1756
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1757
        return index;
1758
    }
1759

    
1760
    //
1761
    // ====================================================================
1762
    // Transforms related methods
1763
    //
1764

    
1765
    public FeatureStoreTransforms getTransforms() {
1766
        return this.transforms;
1767
    }
1768

    
1769
    public FeatureQuery createFeatureQuery() {
1770
        return new DefaultFeatureQuery();
1771
    }
1772

    
1773
    public DataQuery createQuery() {
1774
        return createFeatureQuery();
1775
    }
1776

    
1777
    //
1778
    // ====================================================================
1779
    // UndoRedo related methods
1780
    //
1781

    
1782
    public boolean canRedo() {
1783
        return commands.canRedo();
1784
    }
1785

    
1786
    public boolean canUndo() {
1787
        return commands.canUndo();
1788
    }
1789

    
1790
    public void redo(int num) throws RedoException {
1791
        for (int i = 0; i < num; i++) {
1792
            redo();
1793
        }
1794
    }
1795

    
1796
    public void undo(int num) throws UndoException {
1797
        for (int i = 0; i < num; i++) {
1798
            undo();
1799
        }
1800
    }
1801

    
1802
    //
1803
    // ====================================================================
1804
    // Metadata related methods
1805
    //
1806

    
1807
    public Object getMetadataID() {
1808
        return this.provider.getSourceId();
1809
    }
1810

    
1811
    public void delegate(DynObject dynObject) {
1812
        this.metadata.delegate(dynObject);
1813
    }
1814

    
1815
    public DynClass getDynClass() {
1816
        return this.metadata.getDynClass();
1817
    }
1818

    
1819
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1820
                if( this.transforms.hasDynValue(name) ) {
1821
                        return this.transforms.getDynValue(name);
1822
                }
1823
                if (this.metadata.hasDynValue(name)) {
1824
                        return this.metadata.getDynValue(name);
1825
                }
1826
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1827
                        return this.provider.getProviderName();
1828
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1829
                        return this.provider.getSourceId();
1830
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1831
                        try {
1832
                                return this.getDefaultFeatureType();
1833
                        } catch (DataException e) {
1834
                                return null;
1835
                        }
1836
                }
1837
                return this.metadata.getDynValue(name);
1838
        }
1839

    
1840
    public boolean hasDynValue(String name) {
1841
                if( this.transforms.hasDynValue(name) ) {
1842
                        return true;
1843
                }
1844
        return this.metadata.hasDynValue(name);
1845
    }
1846

    
1847
    public void implement(DynClass dynClass) {
1848
        this.metadata.implement(dynClass);
1849
    }
1850

    
1851
    public Object invokeDynMethod(String name, DynObject context)
1852
        throws DynMethodException {
1853
        return this.metadata.invokeDynMethod(this, name, context);
1854
    }
1855

    
1856
    public Object invokeDynMethod(int code, DynObject context)
1857
        throws DynMethodException {
1858
        return this.metadata.invokeDynMethod(this, code, context);
1859
    }
1860

    
1861
    public void setDynValue(String name, Object value)
1862
        throws DynFieldNotFoundException {
1863
                if( this.transforms.hasDynValue(name) ) {
1864
                        this.transforms.setDynValue(name, value);
1865
                        return;
1866
                }
1867
        this.metadata.setDynValue(name, value);
1868

    
1869
    }
1870

    
1871
    /*
1872
     * (non-Javadoc)
1873
     * 
1874
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1875
     */
1876
    public Set getMetadataChildren() {
1877
        return this.metadataChildren;
1878
    }
1879

    
1880
    /*
1881
     * (non-Javadoc)
1882
     * 
1883
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1884
     */
1885
    public String getMetadataName() {
1886
        return this.provider.getProviderName();
1887
    }
1888

    
1889
    public FeatureTypeManager getFeatureTypeManager() {
1890
        return this.featureTypeManager;
1891
    }
1892

    
1893
    public long getFeatureCount() throws DataException {
1894
        if (featureCount == null) {
1895
            featureCount = new Long(this.provider.getFeatureCount());
1896
        }
1897
        if (this.isEditing() && !this.isAppending()) {
1898
            return featureCount.longValue()
1899
                - this.featureManager.getDeltaSize();
1900
        }
1901
        return featureCount.longValue();
1902
    }
1903

    
1904
    private Long getTemporalOID() {
1905
        return new Long(this.temporalOid++);
1906
    }
1907

    
1908
    public FeatureType getProviderFeatureType(String featureTypeId) {
1909
        if (featureTypeId == null) {
1910
            return this.defaultFeatureType;
1911
        }
1912
        FeatureType type;
1913
        Iterator iter = this.featureTypes.iterator();
1914
        while (iter.hasNext()) {
1915
            type = (FeatureType) iter.next();
1916
            if (type.getId().equals(featureTypeId)) {
1917
                return type;
1918
            }
1919
        }
1920
        return null;
1921
    }
1922

    
1923
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1924
        return ((DefaultFeature) feature).getData();
1925
    }
1926

    
1927
    public DataStore getStore() {
1928
        return this;
1929
    }
1930

    
1931
    public FeatureStore getFeatureStore() {
1932
        return this;
1933
    }
1934

    
1935
    public void createCache(String name, DynObject parameters)
1936
        throws DataException {
1937
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1938
        if (cache == null) {
1939
            throw new CreateException("FeaureCacheProvider", null);
1940
        }
1941
        cache.apply(this, provider);
1942
        provider = cache;
1943

    
1944
        featureCount = null;
1945
    }
1946

    
1947
    public FeatureCache getCache() {
1948
        return cache;
1949
    }
1950

    
1951
    public void clear() {
1952
        if (metadata != null) {
1953
            metadata.clear();
1954
        }
1955
    }
1956

    
1957
    public String getName() {
1958
        return this.provider.getName();
1959
    }
1960

    
1961
    public String getFullName() {
1962
        return this.provider.getFullName();
1963
    }
1964

    
1965
    public String getProviderName() {
1966
        return this.provider.getProviderName();
1967
    }
1968

    
1969
    public boolean isKnownEnvelope() {
1970
        return this.provider.isKnownEnvelope();
1971
    }
1972

    
1973
    public boolean hasRetrievedFeaturesLimit() {
1974
        return this.provider.hasRetrievedFeaturesLimit();
1975
    }
1976

    
1977
    public int getRetrievedFeaturesLimit() {
1978
        return this.provider.getRetrievedFeaturesLimit();
1979
    }
1980

    
1981
    public Interval getInterval() {  
1982
        return this.provider.getInterval();
1983
    }
1984

    
1985
    public Collection getTimes() {      
1986
        return this.provider.getTimes();
1987
    }
1988

    
1989
    public Collection getTimes(Interval interval) {       
1990
        return this.provider.getTimes(interval);
1991
    }
1992
}