Statistics
| Revision:

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

History | View | Annotate | Download (68.1 KB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
175
    private DefaultDataManager dataManager = null;
176

    
177
    private FeatureStoreProvider provider = null;
178

    
179
    private DefaultFeatureIndexes indexes;
180

    
181
    private DefaultFeatureStoreTransforms transforms;
182

    
183
    DelegatedDynObject metadata;
184
    
185
    private Set metadataChildren;
186

    
187
    private Long featureCount = null;
188

    
189
    private long temporalOid = 0;
190

    
191
    private FeatureCacheProvider cache;
192

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

    
202
    public DefaultFeatureStore() {
203

    
204
    }
205

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

    
209
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
210

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

    
215
        this.dataManager = (DefaultDataManager) dataManager;
216

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

    
225
    }
226

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
412
        }
413

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

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

    
421
    }
422

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

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

    
435
        try {
436

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

    
476
                }
477

    
478
            }
479

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

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

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

    
499
    }
500

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
647
    }
648

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

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

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

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

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

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

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

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

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

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

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

    
710
    }
711

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

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

    
719
    }
720

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

    
724
    }
725

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

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

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

    
741
    }
742

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

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

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

    
766
                }
767

    
768
            }
769
    }
770

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

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

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

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

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

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

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

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

    
816
        }
817

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

    
822
        featureCount = null;
823

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
998
    private static EditableFeature lastChangedFeature = null;
999

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

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

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

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

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

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

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

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

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

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

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

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

    
1167
    synchronized public void finishEditing() throws DataException {
1168
        LOG.debug("finish editing of mode: {}", new Integer(mode));
1169
        try {
1170
            switch (mode) {
1171
            case MODE_QUERY:
1172
                throw new NeedEditingModeException(this.getName());
1173

    
1174
            case MODE_APPEND:
1175
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1176
                provider.endAppend();
1177
                exitEditingMode();
1178
                updateIndexes();
1179
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1180
                break;
1181

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

    
1204
    public void beginEditingGroup(String description)
1205
        throws NeedEditingModeException {
1206
        checkInEditingMode();
1207
        commands.startComplex(description);
1208
    }
1209

    
1210
    public void endEditingGroup() throws NeedEditingModeException {
1211
        checkInEditingMode();
1212
        commands.endComplex();
1213
    }
1214

    
1215
    public boolean isAppendModeSupported() {
1216
        return this.provider.supportsAppendMode();
1217
    }
1218

    
1219
    public void export(DataServerExplorer explorer, String provider,
1220
        NewFeatureStoreParameters params) throws DataException {
1221

    
1222
        if (this.getFeatureTypes().size() != 1) {
1223
            throw new NotYetImplemented(
1224
                "export whith more than one type not yet implemented");
1225
        }
1226
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1227
        FeatureStore target = null;
1228
        FeatureSet features = null;
1229
        DisposableIterator iterator = null;
1230
        try {
1231
            FeatureType type = this.getDefaultFeatureType();
1232
            if ((params.getDefaultFeatureType() == null)
1233
                || (params.getDefaultFeatureType().size() == 0)) {
1234
                params.setDefaultFeatureType(type.getEditable());
1235

    
1236
            }
1237
            explorer.add(provider, params, true);
1238

    
1239
            DataManager manager = DALLocator.getDataManager();
1240
            target = (FeatureStore) manager.openStore(provider, params);
1241
            FeatureType targetType = target.getDefaultFeatureType();
1242

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

    
1274
    //
1275
    // ====================================================================
1276
    // Obtencion de datos
1277
    // getDataCollection, getFeatureCollection
1278
    //
1279

    
1280
    public DataSet getDataSet() throws DataException {
1281
        checkNotInAppendMode();
1282
        FeatureQuery query =
1283
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1284
        return new DefaultFeatureSet(this, query);
1285
    }
1286

    
1287
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1288
        checkNotInAppendMode();
1289
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1290
    }
1291

    
1292
    public void getDataSet(Observer observer) throws DataException {
1293
        checkNotInAppendMode();
1294
        this.getFeatureSet(null, observer);
1295
    }
1296

    
1297
    public void getDataSet(DataQuery dataQuery, Observer observer)
1298
        throws DataException {
1299
        checkNotInAppendMode();
1300
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1301
    }
1302

    
1303
    public FeatureSet getFeatureSet() throws DataException {
1304
        checkNotInAppendMode();
1305
        FeatureQuery query =
1306
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1307
        return new DefaultFeatureSet(this, query);
1308
    }
1309

    
1310
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1311
        throws DataException {
1312
        checkNotInAppendMode();
1313
        return new DefaultFeatureSet(this, featureQuery);
1314
    }
1315

    
1316
    public void accept(Visitor visitor) throws BaseException {
1317
        FeatureSet set = getFeatureSet();
1318
        try {
1319
            set.accept(visitor);
1320
        } finally {
1321
            set.dispose();
1322
        }
1323
    }
1324

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

    
1335
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1336
        throws DataException {
1337
        DefaultFeatureType fType =
1338
            (DefaultFeatureType) this.getFeatureType(featureQuery
1339
                .getFeatureTypeId());
1340
        if ((featureQuery.getAttributeNames() != null)
1341
            && (featureQuery.getAttributeNames().length > 0)) {
1342
            return fType.getSubtype(featureQuery.getAttributeNames());
1343
        }
1344
        return fType;
1345
    }
1346

    
1347
    public void getFeatureSet(Observer observer) throws DataException {
1348
        checkNotInAppendMode();
1349
        this.getFeatureSet(null, observer);
1350
    }
1351

    
1352
    public void getFeatureSet(FeatureQuery query, Observer observer)
1353
        throws DataException {
1354
        class LoadInBackGround implements Runnable {
1355

    
1356
            private FeatureStore store;
1357
            private FeatureQuery query;
1358
            private Observer observer;
1359

    
1360
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1361
                Observer observer) {
1362
                this.store = store;
1363
                this.query = query;
1364
                this.observer = observer;
1365
            }
1366

    
1367
            void notify(FeatureStoreNotification theNotification) {
1368
                observer.update(store, theNotification);
1369
                return;
1370
            }
1371

    
1372
            public void run() {
1373
                FeatureSet set = null;
1374
                try {
1375
                    set = store.getFeatureSet(query);
1376
                    notify(new DefaultFeatureStoreNotification(store,
1377
                        FeatureStoreNotification.LOAD_FINISHED, set));
1378
                } catch (Exception e) {
1379
                    notify(new DefaultFeatureStoreNotification(store,
1380
                        FeatureStoreNotification.LOAD_FINISHED, e));
1381
                } finally {
1382
                    dispose(set);
1383
                }
1384
            }
1385
        }
1386

    
1387
        checkNotInAppendMode();
1388
        if (query == null) {
1389
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1390
        }
1391
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1392
        Thread thread = new Thread(task, "Load Feature Set in background");
1393
        thread.start();
1394
    }
1395

    
1396
    public Feature getFeatureByReference(FeatureReference reference)
1397
        throws DataException {
1398
        checkNotInAppendMode();
1399
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1400
        FeatureType featureType;
1401
        if (ref.getFeatureTypeId() == null) {
1402
            featureType = this.getDefaultFeatureType();
1403
        } else {
1404
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1405
        }
1406
        return this.getFeatureByReference(reference, featureType);
1407
    }
1408

    
1409
    public Feature getFeatureByReference(FeatureReference reference,
1410
        FeatureType featureType) throws DataException {
1411
        checkNotInAppendMode();
1412
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1413
        if (!this.transforms.isEmpty()) {
1414

    
1415
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1416

    
1417
        }
1418
        // TODO comprobar que el id es de este store
1419

    
1420
        if (this.mode == MODE_FULLEDIT) {
1421
            Feature f = featureManager.get(reference, this, featureType);
1422
            if (f != null) {
1423
                return f;
1424
            }
1425
        }
1426
    
1427
        
1428
        DefaultFeature feature =
1429
            new DefaultFeature(this,
1430
                this.provider.getFeatureProviderByReference(
1431
                    (FeatureReferenceProviderServices) reference, featureType));
1432

    
1433
        if (!this.transforms.isEmpty()) {
1434
            return this.transforms.applyTransform(feature, featureType);
1435
        }
1436
        return feature;
1437
    }
1438

    
1439
    //
1440
    // ====================================================================
1441
    // Gestion de features
1442
    //
1443

    
1444
    private FeatureType fixFeatureType(DefaultFeatureType type)
1445
        throws DataException {
1446
        FeatureType original = this.getDefaultFeatureType();
1447

    
1448
        if ((type == null) || type.equals(original)) {
1449
            return original;
1450
        } else {
1451
            if (!type.isSubtypeOf(original)) {
1452
                Iterator iter = this.getFeatureTypes().iterator();
1453
                FeatureType tmpType;
1454
                boolean found = false;
1455
                while (iter.hasNext()) {
1456
                    tmpType = (FeatureType) iter.next();
1457
                    if (type.equals(tmpType)) {
1458
                        return type;
1459

    
1460
                    } else
1461
                        if (type.isSubtypeOf(tmpType)) {
1462
                            found = true;
1463
                            original = tmpType;
1464
                            break;
1465
                        }
1466

    
1467
                }
1468
                if (!found) {
1469
                    throw new IllegalFeatureTypeException(getName());
1470
                }
1471
            }
1472
        }
1473

    
1474
        // Checks that type has all fields of pk
1475
        // else add the missing attributes at the end.
1476
        if (!original.hasOID()) {
1477
            // Gets original pk attributes
1478
            DefaultEditableFeatureType edOriginal =
1479
                (DefaultEditableFeatureType) original.getEditable();
1480
            FeatureAttributeDescriptor orgAttr;
1481
            Iterator edOriginalIter = edOriginal.iterator();
1482
            while (edOriginalIter.hasNext()) {
1483
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1484
                if (!orgAttr.isPrimaryKey()) {
1485
                    edOriginalIter.remove();
1486
                }
1487
            }
1488

    
1489
            // Checks if all pk attributes are in type
1490
            Iterator typeIterator;
1491
            edOriginalIter = edOriginal.iterator();
1492
            FeatureAttributeDescriptor attr;
1493
            while (edOriginalIter.hasNext()) {
1494
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1495
                typeIterator = type.iterator();
1496
                while (typeIterator.hasNext()) {
1497
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1498
                    if (attr.getName().equals(orgAttr.getName())) {
1499
                        edOriginalIter.remove();
1500
                        break;
1501
                    }
1502
                }
1503
            }
1504

    
1505
            // add missing pk attributes if any
1506
            if (edOriginal.size() > 0) {
1507
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1508
                DefaultEditableFeatureType edType =
1509
                    (DefaultEditableFeatureType) original.getEditable();
1510
                edType.clear();
1511
                edType.addAll(type);
1512
                edType.addAll(edOriginal);
1513
                if (!isEditable) {
1514
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1515
                }
1516
            }
1517

    
1518
        }
1519

    
1520
        return type;
1521
    }
1522

    
1523
    public void validateFeatures(int mode) throws DataException {
1524
        FeatureSet collection = null;
1525
        DisposableIterator iter = null;
1526
        try {
1527
            checkNotInAppendMode();
1528
            collection = this.getFeatureSet();
1529
            iter = collection.fastIterator();
1530
            long previousVersionOfUpdate = currentVersionOfUpdate();
1531
            while (iter.hasNext()) {
1532
                ((DefaultFeature) iter.next()).validate(mode);
1533
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1534
                    throw new ConcurrentDataModificationException(getName());
1535
                }
1536
            }
1537
        } catch (Exception e) {
1538
            throw new ValidateFeaturesException(e, getName());
1539
        } finally {
1540
            dispose(iter);
1541
            dispose(collection);
1542
        }
1543
    }
1544

    
1545
    public FeatureType getDefaultFeatureType() throws DataException {
1546
        try {
1547
            if (isEditing()) {
1548
                FeatureType auxFeatureType =
1549
                    featureTypeManager.getType(defaultFeatureType.getId());
1550
                if (auxFeatureType != null) {
1551
                    return auxFeatureType;
1552
                }
1553
            }
1554
            FeatureType type = this.transforms.getDefaultFeatureType();
1555
            if (type != null) {
1556
                return type;
1557
            }
1558
            return defaultFeatureType;
1559
        } catch (Exception e) {
1560
            throw new GetFeatureTypeException(e, getName());
1561
        }
1562
    }
1563

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

    
1594
    public FeatureType getProviderDefaultFeatureType() {
1595
        return defaultFeatureType;
1596
    }
1597

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

    
1631
    public List getProviderFeatureTypes() throws DataException {
1632
        return Collections.unmodifiableList(this.featureTypes);
1633
    }
1634

    
1635
    public Feature createFeature(FeatureProvider data) throws DataException {
1636
        DefaultFeature feature = new DefaultFeature(this, data);
1637
        return feature;
1638
    }
1639

    
1640
    public Feature createFeature(FeatureProvider data, FeatureType type)
1641
        throws DataException {
1642
        // FIXME: falta por implementar
1643
        // Comprobar si es un subtipo del feature de data
1644
        // y construir un feature usando el subtipo.
1645
        // Probablemente requiera generar una copia del data.
1646
        throw new NotYetImplemented();
1647
    }
1648

    
1649
    public EditableFeature createNewFeature(FeatureType type,
1650
        Feature defaultValues) throws DataException {
1651
        try {
1652
            FeatureProvider data = createNewFeatureProvider(type);
1653
            DefaultEditableFeature feature =
1654
                new DefaultEditableFeature(this, data);
1655
            feature.initializeValues(defaultValues);
1656
            data.setNew(true);
1657
            
1658
            return feature;
1659
        } catch (Exception e) {
1660
            throw new CreateFeatureException(e, getName());
1661
        }
1662
    }
1663

    
1664
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1665
        throws DataException {
1666
        type = this.fixFeatureType((DefaultFeatureType) type);
1667
        FeatureProvider data = this.provider.createFeatureProvider(type);
1668
        data.setNew(true);
1669
        if (type.hasOID() && (data.getOID() == null)) {
1670
            data.setOID(this.provider.createNewOID());
1671
        } else {
1672
            data.setOID(this.getTemporalOID());
1673
        }
1674
        return data;
1675

    
1676
    }
1677

    
1678
    public EditableFeature createNewFeature(FeatureType type,
1679
        boolean defaultValues) throws DataException {
1680
        try {
1681
            FeatureProvider data = createNewFeatureProvider(type);
1682
            DefaultEditableFeature feature =
1683
                new DefaultEditableFeature(this, data);
1684
            if (defaultValues) {
1685
                feature.initializeValues();
1686
            }
1687
            return feature;
1688
        } catch (Exception e) {
1689
            throw new CreateFeatureException(e, getName());
1690
        }
1691
    }
1692

    
1693
    public EditableFeature createNewFeature(boolean defaultValues)
1694
        throws DataException {
1695
        return this.createNewFeature(this.getDefaultFeatureType(),
1696
            defaultValues);
1697
    }
1698

    
1699
    public EditableFeature createNewFeature() throws DataException {
1700
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1701
    }
1702

    
1703
    public EditableFeatureType createFeatureType() {
1704
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1705
        return ftype;
1706
    }
1707

    
1708
    public EditableFeatureType createFeatureType(String id) {
1709
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1710
        return ftype;
1711
    }
1712

    
1713
    //
1714
    // ====================================================================
1715
    // Index related methods
1716
    //
1717

    
1718
    public FeatureIndexes getIndexes() {
1719
        return this.indexes;
1720
    }
1721

    
1722
    public FeatureIndex createIndex(FeatureType featureType,
1723
        String attributeName, String indexName) throws DataException {
1724
        return createIndex(null, featureType, attributeName, indexName);
1725
    }
1726

    
1727
    public FeatureIndex createIndex(String indexTypeName,
1728
        FeatureType featureType, String attributeName, String indexName)
1729
        throws DataException {
1730

    
1731
        return createIndex(indexTypeName, featureType, attributeName,
1732
            indexName, false, null);
1733
    }
1734

    
1735
    public FeatureIndex createIndex(FeatureType featureType,
1736
        String attributeName, String indexName, Observer observer)
1737
        throws DataException {
1738
        return createIndex(null, featureType, attributeName, indexName,
1739
            observer);
1740
    }
1741

    
1742
    public FeatureIndex createIndex(String indexTypeName,
1743
        FeatureType featureType, String attributeName, String indexName,
1744
        final Observer observer) throws DataException {
1745

    
1746
        return createIndex(indexTypeName, featureType, attributeName,
1747
            indexName, true, observer);
1748
    }
1749

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

    
1754
        checkNotInAppendMode();
1755
        FeatureIndexProviderServices index = null;
1756
        index =
1757
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1758
                featureType, indexName,
1759
                featureType.getAttributeDescriptor(attributeName));
1760

    
1761
        try {
1762
            index.fill(background, observer);
1763
        } catch (FeatureIndexException e) {
1764
            throw new InitializeException(index.getName(), e);
1765
        }
1766

    
1767
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1768
        return index;
1769
    }
1770

    
1771
    //
1772
    // ====================================================================
1773
    // Transforms related methods
1774
    //
1775

    
1776
    public FeatureStoreTransforms getTransforms() {
1777
        return this.transforms;
1778
    }
1779

    
1780
    public FeatureQuery createFeatureQuery() {
1781
        return new DefaultFeatureQuery();
1782
    }
1783

    
1784
    public DataQuery createQuery() {
1785
        return createFeatureQuery();
1786
    }
1787

    
1788
    //
1789
    // ====================================================================
1790
    // UndoRedo related methods
1791
    //
1792

    
1793
    public boolean canRedo() {
1794
        return commands.canRedo();
1795
    }
1796

    
1797
    public boolean canUndo() {
1798
        return commands.canUndo();
1799
    }
1800

    
1801
    public void redo(int num) throws RedoException {
1802
        for (int i = 0; i < num; i++) {
1803
            redo();
1804
        }
1805
    }
1806

    
1807
    public void undo(int num) throws UndoException {
1808
        for (int i = 0; i < num; i++) {
1809
            undo();
1810
        }
1811
    }
1812

    
1813
    //
1814
    // ====================================================================
1815
    // Metadata related methods
1816
    //
1817

    
1818
    public Object getMetadataID() {
1819
        return this.provider.getSourceId();
1820
    }
1821

    
1822
    public void delegate(DynObject dynObject) {
1823
        this.metadata.delegate(dynObject);
1824
    }
1825

    
1826
    public DynClass getDynClass() {
1827
        return this.metadata.getDynClass();
1828
    }
1829

    
1830
        public Object getDynValue(String name) throws DynFieldNotFoundException {
1831
                if( this.transforms.hasDynValue(name) ) {
1832
                        return this.transforms.getDynValue(name);
1833
                }
1834
                if (this.metadata.hasDynValue(name)) {
1835
                        return this.metadata.getDynValue(name);
1836
                }
1837
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1838
                        return this.provider.getProviderName();
1839
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1840
                        return this.provider.getSourceId();
1841
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1842
                        try {
1843
                                return this.getDefaultFeatureType();
1844
                        } catch (DataException e) {
1845
                                return null;
1846
                        }
1847
                }
1848
                return this.metadata.getDynValue(name);
1849
        }
1850

    
1851
    public boolean hasDynValue(String name) {
1852
                if( this.transforms.hasDynValue(name) ) {
1853
                        return true;
1854
                }
1855
        return this.metadata.hasDynValue(name);
1856
    }
1857

    
1858
    public void implement(DynClass dynClass) {
1859
        this.metadata.implement(dynClass);
1860
    }
1861

    
1862
    public Object invokeDynMethod(String name, DynObject context)
1863
        throws DynMethodException {
1864
        return this.metadata.invokeDynMethod(this, name, context);
1865
    }
1866

    
1867
    public Object invokeDynMethod(int code, DynObject context)
1868
        throws DynMethodException {
1869
        return this.metadata.invokeDynMethod(this, code, context);
1870
    }
1871

    
1872
    public void setDynValue(String name, Object value)
1873
        throws DynFieldNotFoundException {
1874
                if( this.transforms.hasDynValue(name) ) {
1875
                        this.transforms.setDynValue(name, value);
1876
                        return;
1877
                }
1878
        this.metadata.setDynValue(name, value);
1879

    
1880
    }
1881

    
1882
    /*
1883
     * (non-Javadoc)
1884
     * 
1885
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1886
     */
1887
    public Set getMetadataChildren() {
1888
        return this.metadataChildren;
1889
    }
1890

    
1891
    /*
1892
     * (non-Javadoc)
1893
     * 
1894
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1895
     */
1896
    public String getMetadataName() {
1897
        return this.provider.getProviderName();
1898
    }
1899

    
1900
    public FeatureTypeManager getFeatureTypeManager() {
1901
        return this.featureTypeManager;
1902
    }
1903

    
1904
    public long getFeatureCount() throws DataException {
1905
        if (featureCount == null) {
1906
            featureCount = new Long(this.provider.getFeatureCount());
1907
        }
1908
        if (this.isEditing() && !this.isAppending()) {
1909
            return featureCount.longValue()
1910
                - this.featureManager.getDeltaSize();
1911
        }
1912
        return featureCount.longValue();
1913
    }
1914

    
1915
    private Long getTemporalOID() {
1916
        return new Long(this.temporalOid++);
1917
    }
1918

    
1919
    public FeatureType getProviderFeatureType(String featureTypeId) {
1920
        if (featureTypeId == null) {
1921
            return this.defaultFeatureType;
1922
        }
1923
        FeatureType type;
1924
        Iterator iter = this.featureTypes.iterator();
1925
        while (iter.hasNext()) {
1926
            type = (FeatureType) iter.next();
1927
            if (type.getId().equals(featureTypeId)) {
1928
                return type;
1929
            }
1930
        }
1931
        return null;
1932
    }
1933

    
1934
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1935
        return ((DefaultFeature) feature).getData();
1936
    }
1937

    
1938
    public DataStore getStore() {
1939
        return this;
1940
    }
1941

    
1942
    public FeatureStore getFeatureStore() {
1943
        return this;
1944
    }
1945

    
1946
    public void createCache(String name, DynObject parameters)
1947
        throws DataException {
1948
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1949
        if (cache == null) {
1950
            throw new CreateException("FeaureCacheProvider", null);
1951
        }
1952
        cache.apply(this, provider);
1953
        provider = cache;
1954

    
1955
        featureCount = null;
1956
    }
1957

    
1958
    public FeatureCache getCache() {
1959
        return cache;
1960
    }
1961

    
1962
    public void clear() {
1963
        if (metadata != null) {
1964
            metadata.clear();
1965
        }
1966
    }
1967

    
1968
    public String getName() {
1969
        return this.provider.getName();
1970
    }
1971

    
1972
    public String getFullName() {
1973
        return this.provider.getFullName();
1974
    }
1975

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

    
1980
    public boolean isKnownEnvelope() {
1981
        return this.provider.isKnownEnvelope();
1982
    }
1983

    
1984
    public boolean hasRetrievedFeaturesLimit() {
1985
        return this.provider.hasRetrievedFeaturesLimit();
1986
    }
1987

    
1988
    public int getRetrievedFeaturesLimit() {
1989
        return this.provider.getRetrievedFeaturesLimit();
1990
    }
1991

    
1992
    public Interval getInterval() {  
1993
        return this.provider.getInterval();
1994
    }
1995

    
1996
    public Collection getTimes() {      
1997
        return this.provider.getTimes();
1998
    }
1999

    
2000
    public Collection getTimes(Interval interval) {       
2001
        return this.provider.getTimes(interval);
2002
    }
2003
}