Statistics
| Revision:

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

History | View | Annotate | Download (63 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

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

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

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

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

    
151
public final class DefaultFeatureStore extends AbstractDisposable implements
152
DataStoreImplementation, FeatureStoreProviderServices, FeatureStore,
153
Observer {
154

    
155
    final static private Logger logger = LoggerFactory
156
    .getLogger(DefaultFeatureStore.class);
157

    
158
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
159

    
160
    private DataStoreParameters parameters = null;
161
    private FeatureSelection selection;
162
    private FeatureLocks locks;
163

    
164
    private DelegateWeakReferencingObservable delegateObservable = new DelegateWeakReferencingObservable(this);
165

    
166
    private FeatureCommandsStack commands;
167
    private FeatureTypeManager featureTypeManager;
168
    private FeatureManager featureManager;
169
    private SpatialManager spatialManager;
170

    
171
    private FeatureType defaultFeatureType = null;
172
    private List featureTypes = new ArrayList();
173

    
174
    private int mode = MODE_QUERY;
175
    private long versionOfUpdate = 0;
176
    private boolean hasStrongChanges = true;
177
    private boolean hasInserts = true;
178

    
179
    private DefaultDataManager dataManager = null;
180

    
181
    private FeatureStoreProvider provider = null;
182

    
183
    private DefaultFeatureIndexes indexes;
184

    
185
    private DefaultFeatureStoreTransforms transforms;
186

    
187
    private DelegatedDynObject metadata;
188
    private Set metadataChildren;
189

    
190
    private Long featureCount = null;
191

    
192
    private long temporalOid = 0;
193

    
194
    private FeatureCacheProvider cache;
195

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

    
205
    public DefaultFeatureStore() {
206

    
207
    }
208

    
209
    public void intializePhase1(DefaultDataManager dataManager,
210
        DataStoreParameters parameters) throws InitializeException {
211

    
212
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
213

    
214
        this.metadata = (DelegatedDynObject) dynManager
215
        .createDynObject(
216
            METADATA_DEFINITION_NAME,
217
            MetadataManager.METADATA_NAMESPACE
218
        );
219

    
220

    
221
        this.dataManager = dataManager;
222

    
223
        this.parameters = parameters;
224
        this.transforms = new DefaultFeatureStoreTransforms(this);
225
        try {
226
            indexes = new DefaultFeatureIndexes(this);
227
        } catch (DataException e) {
228
            throw new InitializeException(e);
229
        }
230

    
231
    }
232

    
233
    public void intializePhase2(DataStoreProvider provider) {
234
        this.provider = (FeatureStoreProvider) provider;
235
        this.delegate(provider);
236
        this.metadataChildren = new HashSet();
237
        this.metadataChildren.add(provider);
238
    }
239

    
240
    public DataStoreParameters getParameters() {
241
        return parameters;
242
    }
243

    
244
    public int getMode() {
245
        return this.mode;
246
    }
247

    
248
    public DataManager getManager() {
249
        return this.dataManager;
250
    }
251

    
252
    public Iterator getChildren() {
253
        return this.provider.getChilds();
254
    }
255

    
256
    public FeatureStoreProvider getProvider() {
257
        return this.provider;
258
    }
259

    
260
    public FeatureManager getFeatureManager() {
261
        return this.featureManager;
262
    }
263

    
264
    public void setFeatureTypes(List types, FeatureType defaultType) {
265
        this.featureTypes = types;
266
        this.defaultFeatureType = defaultType;
267
    }
268

    
269
    public void open() throws OpenException {
270
        // TODO: Se puede hacer un open estando en edicion ?
271
        this.notifyChange(FeatureStoreNotification.BEFORE_OPEN);
272
        this.provider.open();
273
        this.notifyChange(FeatureStoreNotification.AFTER_OPEN);
274
    }
275

    
276
    public void refresh() throws OpenException, InitializeException {
277
        if (this.mode != MODE_QUERY) {
278
            throw new IllegalStateException();
279
        }
280
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
281
        this.featureCount = null;
282
        this.provider.refresh();
283
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
284
    }
285

    
286
    public void close() throws CloseException {
287
        // TODO: Se puede hacer un close estando en edicion ?
288
        this.notifyChange(FeatureStoreNotification.BEFORE_CLOSE);
289
        this.featureCount = null;
290
        this.provider.close();
291
        this.notifyChange(FeatureStoreNotification.AFTER_CLOSE);
292
    }
293

    
294
    protected void doDispose() throws BaseException {
295
        this.notifyChange(FeatureStoreNotification.BEFORE_DISPOSE);
296
        this.provider.dispose();
297
        if (this.selection != null) {
298
            this.selection.dispose();
299
            this.selection = null;
300
        }
301
        this.commands = null;
302
        this.featureCount = null;
303
        if (this.locks != null) {
304
            //this.locks.dispose();
305
            this.locks = null;
306
        }
307

    
308
        if (this.featureTypeManager != null) {
309
            this.featureTypeManager.dispose();
310
            this.featureTypeManager = null;
311
        }
312

    
313
        this.featureManager = null;
314
        this.spatialManager = null;
315

    
316
        this.parameters = null;
317
        this.notifyChange(FeatureStoreNotification.AFTER_DISPOSE);
318
        if (delegateObservable != null) {
319
            this.delegateObservable.deleteObservers();
320
            this.delegateObservable = null;
321
        }
322
    }
323

    
324
    public boolean allowWrite() {
325
        return this.provider.allowWrite();
326
    }
327

    
328
    public boolean canWriteGeometry(int geometryType) throws DataException {
329
        return this.provider.canWriteGeometry(geometryType, 0);
330
    }
331

    
332
    public DataServerExplorer getExplorer() throws ReadException,
333
    ValidateDataParametersException {
334
        return this.provider.getExplorer();
335
    }
336

    
337
    /*
338
        public Metadata getMetadata() throws MetadataNotFoundException {
339
                // TODO:
340
                // Si el provider devuelbe null habria que ver de construir aqui
341
                // los metadatos basicos, como el Envelope y el SRS.
342

343
                // TODO: Estando en edicion el Envelope deberia de
344
                // actualizarse usando el spatialManager
345
                return this.provider.getMetadata();
346
        }
347
     */
348

    
349
    public Envelope getEnvelope() throws DataException {
350
        if (this.mode == MODE_FULLEDIT) {
351
            return this.spatialManager.getEnvelope();
352
        }
353
        return this.provider.getEnvelope();
354
    }
355

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

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

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

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

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

    
433
        try {
434

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

    
471
                }
472

    
473

    
474
            }
475

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

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

    
488

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

    
495
    }
496

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

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

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

    
521
            definition.addDynFieldObject("transforms")
522
            .setClassOfValue(DefaultFeatureStoreTransforms.class)
523
            .setMandatory(true)
524
            .setPersistent(true);
525

    
526
            definition.addDynFieldMap("evaluatedAttributes")
527
            .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
528
            .setMandatory(false)
529
            .setPersistent(true);
530

    
531
            definition.addDynFieldString("defaultFeatureTypeId")
532
            .setMandatory(true)
533
            .setPersistent(true);
534
        }
535
    }
536

    
537
    public static void registerMetadataDefinition() throws MetadataException {
538
        MetadataManager manager = MetadataLocator.getMetadataManager();
539
        if( manager.getDefinition(METADATA_DEFINITION_NAME)==null ) {
540
            DynStruct metadataDefinition = manager.addDefinition(
541
                METADATA_DEFINITION_NAME,
542
                null
543
            );
544
            metadataDefinition.extend(
545
                manager.getDefinition(
546
                    DataStore.METADATA_DEFINITION_NAME
547
                )
548
            );
549
        }
550
    }
551

    
552
    //
553
    // ====================================================================
554
    // Gestion de la seleccion
555
    //
556

    
557
    public void setSelection(DataSet selection)
558
    throws DataException {
559
        this.setSelection((FeatureSet) selection);
560
    }
561

    
562
    public DataSet createSelection() throws DataException {
563
        return createFeatureSelection();
564
    }
565

    
566
    public DataSet getSelection() throws DataException {
567
        return this.getFeatureSelection();
568
    }
569

    
570
    public void setSelection(FeatureSet selection) throws DataException {
571
        setSelection(selection, true);
572
    }
573

    
574
    /**
575
     * @see #setSelection(FeatureSet)
576
     * @param undoable
577
     *            if the action must be undoable
578
     */
579
    public void setSelection(FeatureSet selection, boolean undoable)
580
    throws DataException {
581
        if (selection == null) {
582
            if (undoable) {
583
                throw new SelectionNotAllowedException(getName());
584
            }
585

    
586
        } else {
587
            if (selection.equals(this.selection)) {
588
                return;
589
            }
590
            if (!selection.isFromStore(this)) {
591
                throw new SelectionNotAllowedException(getName());
592
            }
593
        }
594

    
595
        if (this.selection != null) {
596
            this.selection.deleteObserver(this);
597
        }
598
        if (selection == null) {
599
            if (this.selection != null) {
600
                this.selection.dispose();
601
            }
602
            this.selection = null;
603
            return;
604
        }
605
        if (selection instanceof FeatureSelection) {
606
            if (undoable && isEditing()) {
607
                commands.selectionSet(this, this.selection,
608
                    (FeatureSelection) selection);
609
            }
610
            if (this.selection != null) {
611
                this.selection.dispose();
612
            }
613
            this.selection = (FeatureSelection) selection;
614
        } else {
615
            if (undoable && isEditing()) {
616
                commands.startComplex("_selectionSet");
617
            }
618
            if (selection instanceof DefaultFeatureSelection) {
619
                DefaultFeatureSelection defSelection = (DefaultFeatureSelection) selection;
620
                defSelection.deselectAll(undoable);
621
                defSelection.select(selection, undoable);
622
            } else {
623
                this.selection.deselectAll();
624
                this.selection.select(selection);
625
            }
626
            if (undoable && isEditing()) {
627
                commands.endComplex();
628
            }
629
        }
630
        this.selection.addObserver(this);
631

    
632
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
633
    }
634

    
635
    public FeatureSelection createFeatureSelection() throws DataException {
636
        return this.provider.createFeatureSelection();
637
    }
638

    
639
    public FeatureSelection getFeatureSelection() throws DataException {
640
        if (selection == null) {
641
            this.selection = createFeatureSelection();
642
            this.selection.addObserver(this);
643
        }
644
        return selection;
645
    }
646

    
647
    //
648
    // ====================================================================
649
    // Gestion de notificaciones
650
    //
651

    
652
    public void notifyChange(String notification) {
653
        if (delegateObservable != null) {
654
                        notifyChange(new DefaultFeatureStoreNotification(
655
                this, notification));
656
        }
657

    
658
    }
659

    
660
        public void notifyChange(String notification, FeatureProvider data) {
661
                try {
662
                        notifyChange(notification, createFeature(data));
663
                } catch (DataException ex) {
664
                        logger.error("Error notifying about the notification: "
665
                                        + notification + ", with the data: " + data, ex);
666
                }
667
        }
668

    
669
    public void notifyChange(String notification, Feature feature) {
670
                notifyChange(new DefaultFeatureStoreNotification(
671
            this, notification, feature));
672
    }
673

    
674
    public void notifyChange(String notification, Command command) {
675
                notifyChange(new DefaultFeatureStoreNotification(
676
            this, notification, command));
677
    }
678

    
679
    public void notifyChange(String notification, EditableFeatureType type) {
680
                notifyChange(new DefaultFeatureStoreNotification(this,
681
            notification, type));
682
    }
683

    
684
        public void notifyChange(FeatureStoreNotification storeNotification) {
685
                delegateObservable.notifyObservers(storeNotification);
686
        }
687

    
688
    public void notifyChange(String notification, Resource resource) {
689
                notifyChange(new DefaultFeatureStoreNotification(this,
690
            FeatureStoreNotification.RESOURCE_CHANGED));
691
    }
692

    
693

    
694
    //
695
    // ====================================================================
696
    // Gestion de bloqueos
697
    //
698

    
699
    public boolean isLocksSupported() {
700
        return this.provider.isLocksSupported();
701
    }
702

    
703
    public FeatureLocks getLocks() throws DataException {
704
        if (!this.provider.isLocksSupported()) {
705
            logger.warn("Locks not supporteds");
706
            return null;
707
        }
708
        if (locks == null) {
709
            this.locks = this.provider.createFeatureLocks();
710
        }
711
        return locks;
712
    }
713

    
714
    //
715
    // ====================================================================
716
    // Interface Observable
717
    //
718

    
719
    public void disableNotifications() {
720
        this.delegateObservable.disableNotifications();
721

    
722
    }
723

    
724
    public void enableNotifications() {
725
        this.delegateObservable.enableNotifications();
726
    }
727

    
728
    public void beginComplexNotification() {
729
        this.delegateObservable.beginComplexNotification();
730

    
731
    }
732

    
733
    public void endComplexNotification() {
734
        this.delegateObservable.endComplexNotification();
735

    
736
    }
737

    
738
    public void addObserver(Observer observer) {
739
        this.delegateObservable.addObserver(observer);
740

    
741
    }
742

    
743
    public void deleteObserver(Observer observer) {
744
        if (delegateObservable != null) {
745
            this.delegateObservable.deleteObserver(observer);
746
        }
747
    }
748

    
749
    public void deleteObservers() {
750
        this.delegateObservable.deleteObservers();
751

    
752
    }
753

    
754
    //
755
    // ====================================================================
756
    // Interface Observer
757
    //
758
    // Usado para observar:
759
    // - su seleccion
760
    // - sus bloqueos
761
    // - sus recursos
762
    //
763

    
764
    public void update(Observable observable, Object notification) {
765
        if (observable instanceof FeatureSet) {
766
            if (observable == this.selection) {
767
                this.notifyChange(FeatureStoreNotification.SELECTION_CHANGE);
768
            } else if (observable == this.locks) {
769
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
770
            }
771

    
772
        } else if (observable instanceof FeatureStoreProvider) {
773
            if (observable == this.provider) {
774

    
775
            }
776

    
777
        }
778
    }
779

    
780
    //
781
    // ====================================================================
782
    // Edicion
783
    //
784

    
785
    private void newVersionOfUpdate() {
786
        this.versionOfUpdate++;
787
    }
788

    
789
    private long currentVersionOfUpdate() {
790
        return this.versionOfUpdate;
791
    }
792

    
793
    private void checkInEditingMode()
794
    throws NeedEditingModeException {
795
        if (mode != MODE_FULLEDIT) {
796
            throw new NeedEditingModeException(this.getName());
797
        }
798
    }
799

    
800
    private void checkNotInAppendMode() throws IllegalStateException {
801
        if (mode == MODE_APPEND) {
802
            throw new IllegalStateException(this.getName());
803
        }
804
    }
805

    
806
    private void checkIsOwnFeature(Feature feature)
807
    throws IllegalFeatureException {
808
        if (((DefaultFeature) feature).getStore() != this) {
809
            throw new IllegalFeatureException(this.getName());
810
        }
811
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
812
        // fixFeatureType((DefaultFeatureType) feature.getType());
813
    }
814

    
815
    private void exitEditingMode() {
816
        if (commands != null) {
817
            commands.clear();
818
            commands = null;
819
        }
820

    
821
        if (featureTypeManager != null) {
822
            featureTypeManager.dispose();
823
            featureTypeManager = null;
824

    
825
        }
826

    
827
        // TODO implementar un dispose para estos dos
828
        featureManager = null;
829
        spatialManager = null;
830

    
831
        featureCount = null;
832

    
833
        mode = MODE_QUERY;
834
        hasStrongChanges = true; // Lo deja a true por si las moscas
835
        hasInserts = true;
836
    }
837

    
838
    synchronized public void edit() throws DataException {
839
        edit(MODE_FULLEDIT);
840
    }
841

    
842
    synchronized public void edit(int mode) throws DataException {
843
        try {
844
            if ( this.mode != MODE_QUERY ) {
845
                throw new AlreadyEditingException(this.getName());
846
            }
847
            if (!this.provider.supportsAppendMode()) {
848
                mode = MODE_FULLEDIT;
849
            }
850
            switch (mode) {
851
            case MODE_QUERY:
852
                throw new IllegalStateException(this.getName());
853

    
854
            case MODE_FULLEDIT:
855
                if (!this.transforms.isEmpty()) {
856
                    throw new IllegalStateException(this.getName());
857
                }
858
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
859
                featureManager = new FeatureManager(new MemoryExpansionAdapter());
860
                featureTypeManager = new FeatureTypeManager(this,
861
                    new MemoryExpansionAdapter());
862
                spatialManager = new SpatialManager(this, provider
863
                    .getEnvelope());
864

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

    
888
    public boolean isEditing() {
889
        return mode == MODE_FULLEDIT;
890
    }
891

    
892
    public boolean isAppending() {
893
        return mode == MODE_APPEND;
894
    }
895

    
896
    synchronized public void update(EditableFeatureType type)
897
    throws DataException {
898
        try {
899
            checkInEditingMode();
900
            if (type == null) {
901
                throw new NullFeatureTypeException(getName());
902
            }
903
            // FIXME: Comprobar que es un featureType aceptable.
904
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
905
            newVersionOfUpdate();
906

    
907
            FeatureType oldt = type.getSource().getCopy();
908
            FeatureType newt = type.getNotEditableCopy();
909
            commands.update(newt, oldt);
910

    
911
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
912
                hasStrongChanges = true;
913
            }
914
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
915
        } catch (Exception e) {
916
            throw new StoreUpdateFeatureTypeException(e, this.getName());
917
        }
918
    }
919

    
920
    synchronized public void delete(Feature feature) throws DataException {
921
        try {
922
            checkInEditingMode();
923
            checkIsOwnFeature(feature);
924
            if (feature instanceof EditableFeature) {
925
                throw new StoreDeleteEditableFeatureException(getName());
926
            }
927
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
928
            this.commands.delete(feature);
929
            newVersionOfUpdate();
930
            hasStrongChanges = true;
931
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
932
        } catch (Exception e) {
933
            throw new StoreDeleteFeatureException(e, this.getName());
934
        }
935
    }
936

    
937
    private static EditableFeature lastChangedFeature = null;
938

    
939
    synchronized public void insert(EditableFeature feature)
940
    throws DataException {
941
        try {
942
            switch (mode) {
943
            case MODE_QUERY:
944
                throw new NeedEditingModeException(this.getName());
945

    
946
            case MODE_APPEND:
947
                checkIsOwnFeature(feature);
948
                if (feature.getSource() != null) {
949
                    throw new NoNewFeatureInsertException(this.getName());
950
                }
951
                this.featureCount = null;
952
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
953
                feature.validate(Feature.UPDATE);
954
                provider.append(((DefaultEditableFeature) feature).getData());
955
                hasStrongChanges = true;
956
                hasInserts = true;
957
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
958
                break;
959

    
960
            case MODE_FULLEDIT:
961
                checkIsOwnFeature(feature);
962
                if (feature.getSource() != null) {
963
                    throw new NoNewFeatureInsertException(this.getName());
964
                }
965
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
966
                newVersionOfUpdate();
967
                if (lastChangedFeature ==null || lastChangedFeature.getSource() != feature.getSource()) {
968
                    lastChangedFeature = feature;
969
                    feature.validate(Feature.UPDATE);
970
                    lastChangedFeature = null;
971
                }
972
                commands.insert(feature.getNotEditableCopy());
973
                hasStrongChanges = true;
974
                hasInserts = true;
975
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
976
                break;
977
            }
978
        } catch (Exception e) {
979
            throw new StoreInsertFeatureException(e, this.getName());
980
        }
981
    }
982

    
983
    synchronized public void update(EditableFeature feature)
984
    throws DataException {
985
        try {
986
            if ((feature).getSource() == null) {
987
                insert(feature);
988
                return;
989
            }
990
            checkInEditingMode();
991
            checkIsOwnFeature(feature);
992
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
993
            newVersionOfUpdate();
994
            if (lastChangedFeature==null || lastChangedFeature.getSource() != feature.getSource()) {
995
                lastChangedFeature = feature;
996
                feature.validate(Feature.UPDATE);
997
                lastChangedFeature = null;
998
            }
999

    
1000
            Feature oldf = feature.getSource();
1001
            Feature newf = feature.getNotEditableCopy();
1002
            commands.update(newf, oldf);
1003

    
1004
            hasStrongChanges = true;
1005
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1006
        } catch (Exception e) {
1007
            throw new StoreUpdateFeatureException(e, this.getName());
1008
        }
1009
    }
1010

    
1011
    synchronized public void redo() throws RedoException {
1012
        Command redo = commands.getNextRedoCommand();
1013
        try {
1014
            checkInEditingMode();
1015
        } catch (NeedEditingModeException ex) {
1016
            throw new RedoException(redo, ex);
1017
        }
1018
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1019
        newVersionOfUpdate();
1020
        commands.redo();
1021
        hasStrongChanges = true;
1022
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1023
    }
1024

    
1025
    synchronized public void undo() throws UndoException {
1026
        Command undo = commands.getNextUndoCommand();
1027
        try {
1028
            checkInEditingMode();
1029
        } catch (NeedEditingModeException ex) {
1030
            throw new UndoException(undo, ex);
1031
        }
1032
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1033
        newVersionOfUpdate();
1034
        commands.undo();
1035
        hasStrongChanges = true;
1036
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1037
    }
1038

    
1039
    public List getRedoInfos() {
1040
        if (isEditing() && commands != null) {
1041
            return commands.getRedoInfos();
1042
        } else {
1043
            return null;
1044
        }
1045
    }
1046

    
1047
    public List getUndoInfos() {
1048
        if (isEditing() && commands != null) {
1049
            return commands.getUndoInfos();
1050
        } else {
1051
            return null;
1052
        }
1053
    }
1054

    
1055
    public synchronized FeatureCommandsStack getCommandsStack()
1056
    throws DataException {
1057
        checkInEditingMode();
1058
        return commands;
1059
    }
1060

    
1061
    synchronized public void cancelEditing() throws DataException {
1062
        spatialManager.cancelModifies();
1063
        try {
1064
            checkInEditingMode();
1065

    
1066
            boolean clearSelection = this.hasStrongChanges;
1067
            if (this.selection instanceof FeatureReferenceSelection) {
1068
                clearSelection = this.hasInserts;
1069
            }
1070
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1071
            exitEditingMode();
1072
            if (clearSelection) {
1073
                ((FeatureSelection) this.getSelection()).deselectAll();
1074
            }
1075
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1076
        } catch (Exception e) {
1077
            throw new StoreCancelEditingException(e, this.getName());
1078
        }
1079
    }
1080

    
1081
    synchronized public void finishEditing() throws DataException {
1082
        try {
1083
            switch (mode) {
1084
            case MODE_QUERY:
1085
                throw new NeedEditingModeException(this.getName());
1086

    
1087
            case MODE_APPEND:
1088
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1089
                provider.endAppend();
1090
                exitEditingMode();
1091
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1092
                break;
1093

    
1094
            case MODE_FULLEDIT:
1095
                if (hasStrongChanges && !this.allowWrite()) {
1096
                    throw new WriteNotAllowedException(getName());
1097
                }
1098

    
1099
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1100
                if (hasStrongChanges) {
1101
                    validateFeatures(Feature.FINISH_EDITING);
1102
                    provider.performChanges(featureManager.getDeleted(),
1103
                        featureManager.getInserted(), featureManager
1104
                        .getUpdated(), featureTypeManager
1105
                        .getFeatureTypesChanged());
1106
                }
1107
                exitEditingMode();
1108
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1109
                break;
1110
            }
1111
        } catch (Exception e) {
1112
            throw new FinishEditingException(e);
1113
        }
1114
    }
1115

    
1116
    public void beginEditingGroup(String description)
1117
    throws NeedEditingModeException {
1118
        checkInEditingMode();
1119
        commands.startComplex(description);
1120
    }
1121

    
1122
    public void endEditingGroup() throws NeedEditingModeException {
1123
        checkInEditingMode();
1124
        commands.endComplex();
1125
    }
1126

    
1127
    public boolean isAppendModeSupported() {
1128
        return this.provider.supportsAppendMode();
1129
    }
1130

    
1131

    
1132
    public void export(DataServerExplorer explorer, String provider, NewFeatureStoreParameters params)
1133
    throws DataException {
1134

    
1135
        if (this.getFeatureTypes().size() != 1) {
1136
            throw new NotYetImplemented(
1137
            "export whith more than one type not yet implemented");
1138
        }
1139
        FeatureSelection featureSelection=(FeatureSelection)getSelection();
1140
        FeatureStore target = null;
1141
        FeatureSet features = null;
1142
        DisposableIterator iterator = null;
1143
        try {
1144
            FeatureType type = this.getDefaultFeatureType();
1145
            if (params.getDefaultFeatureType() == null
1146
                || params.getDefaultFeatureType().size() == 0) {
1147
                params.setDefaultFeatureType(type.getEditable());
1148

    
1149
            }
1150
            explorer.add(provider, params, true);
1151

    
1152
            DataManager manager = DALLocator.getDataManager();
1153
            target = (FeatureStore) manager.openStore(provider, params);
1154
            FeatureType targetType = target.getDefaultFeatureType();
1155

    
1156
            target.edit(MODE_APPEND);
1157
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1158
            if (featureSelection.getSize()>0){
1159
                features = this.getFeatureSelection();
1160
            }else{
1161
                if (pk != null && pk.length > 0){
1162
                    FeatureQuery query = createFeatureQuery();
1163
                    for (int i = 0; i < pk.length; i++) {
1164
                        query.getOrder().add(pk[i].getName(), true);
1165
                    }
1166
                    features = this.getFeatureSet(query);
1167
                } else {
1168
                    features = this.getFeatureSet();
1169
                }
1170
            }
1171
            iterator = features.iterator();
1172
            while (iterator.hasNext()) {
1173
                DefaultFeature feature = (DefaultFeature) iterator.next();
1174
                target.insert(target.createNewFeature(targetType, feature));
1175
            }
1176
            target.finishEditing();
1177
            target.dispose();
1178
        } catch (Exception e) {
1179
            throw new DataExportException(e, params.toString());
1180
        } finally {
1181
            dispose(iterator);
1182
            dispose(features);
1183
            dispose(target);
1184
        }
1185
    }
1186

    
1187
    //
1188
    // ====================================================================
1189
    // Obtencion de datos
1190
    // getDataCollection, getFeatureCollection
1191
    //
1192

    
1193
    public DataSet getDataSet() throws DataException {
1194
        checkNotInAppendMode();
1195
        FeatureQuery query = new DefaultFeatureQuery(this
1196
            .getDefaultFeatureType());
1197
        return new DefaultFeatureSet(this, query);
1198
    }
1199

    
1200
    public DataSet getDataSet(DataQuery dataQuery)
1201
    throws DataException {
1202
        checkNotInAppendMode();
1203
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1204
    }
1205

    
1206
    public void getDataSet(Observer observer) throws DataException {
1207
        checkNotInAppendMode();
1208
        this.getFeatureSet(null, observer);
1209
    }
1210

    
1211
    public void getDataSet(DataQuery dataQuery, Observer observer)
1212
    throws DataException {
1213
        checkNotInAppendMode();
1214
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1215
    }
1216

    
1217
    public FeatureSet getFeatureSet() throws DataException {
1218
        checkNotInAppendMode();
1219
        FeatureQuery query = new DefaultFeatureQuery(this
1220
            .getDefaultFeatureType());
1221
        return new DefaultFeatureSet(this, query);
1222
    }
1223

    
1224
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1225
    throws DataException {
1226
        checkNotInAppendMode();
1227
        return new DefaultFeatureSet(this, featureQuery);
1228
    }
1229

    
1230
    public void accept(Visitor visitor) throws BaseException {
1231
        FeatureSet set = getFeatureSet();
1232
        try {
1233
            set.accept(visitor);
1234
        } finally {
1235
            set.dispose();
1236
        }
1237
    }
1238

    
1239
    public void accept(Visitor visitor, DataQuery dataQuery)
1240
    throws BaseException {
1241
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1242
        try {
1243
            set.accept(visitor);
1244
        } finally {
1245
            set.dispose();
1246
        }
1247
    }
1248

    
1249
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1250
    throws DataException {
1251
        DefaultFeatureType fType = (DefaultFeatureType) this
1252
        .getFeatureType(featureQuery.getFeatureTypeId());
1253
        if (featureQuery.getAttributeNames() != null){
1254
            return fType.getSubtype(featureQuery.getAttributeNames());
1255
        }
1256
        return fType;
1257
    }
1258

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

    
1265
    public void getFeatureSet(FeatureQuery query, Observer observer)
1266
    throws DataException {
1267
        class LoadInBackGround implements Runnable {
1268
            private FeatureStore store;
1269
            private FeatureQuery query;
1270
            private Observer observer;
1271
            private Executor executor;
1272
            private FeatureStoreNotification notification;
1273

    
1274
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1275
                Observer observer, Executor executor) {
1276
                this.store = store;
1277
                this.query = query;
1278
                this.observer = observer;
1279
                this.executor = executor;
1280
            }
1281

    
1282
            void notify(FeatureStoreNotification theNotification) {
1283
                if (executor == null) {
1284
                    observer.update(store, theNotification);
1285
                    return;
1286
                }
1287
                this.notification = theNotification;
1288
                executor.execute(new Runnable() {
1289
                    public void run() {
1290
                        observer.update(store, notification);
1291
                    }
1292
                });
1293

    
1294
            }
1295

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

    
1311
        checkNotInAppendMode();
1312
        if (query == null) {
1313
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1314
        }
1315
        Executor executor = ToolsLocator.getTaskManager().getExecutor();
1316
        LoadInBackGround task = new LoadInBackGround(this, query, observer,
1317
            executor);
1318
        Thread thread = new Thread(task);
1319
        thread.run();
1320
    }
1321

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

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

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

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

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

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

    
1365
    //
1366
    // ====================================================================
1367
    // Gestion de features
1368
    //
1369

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

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

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

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

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

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

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

    
1443
        }
1444

    
1445

    
1446
        return type;
1447
    }
1448

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

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

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

    
1519

    
1520
    public FeatureType getProviderDefaultFeatureType() {
1521
        return defaultFeatureType;
1522
    }
1523

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

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

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

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

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

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

    
1600
    }
1601

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

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

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

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

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

    
1636

    
1637
    //
1638
    // ====================================================================
1639
    // Index related methods
1640
    //
1641

    
1642
    public FeatureIndexes getIndexes() {
1643
        return this.indexes;
1644
    }
1645

    
1646
    public FeatureIndex createIndex(FeatureType featureType,
1647
        String attributeName, String indexName) throws ProviderNotRegisteredException, InitializeException {
1648
        checkNotInAppendMode();
1649
        FeatureIndexProviderServices index = null;
1650
        index = dataManager.createFeatureIndexProvider(null, this, featureType,
1651
            indexName, featureType.getAttributeDescriptor(attributeName));
1652
        try {
1653
            index.fill();
1654
        } catch (FeatureIndexException e) {
1655
            throw new InitializeException(index.getName(), e);
1656
        }
1657
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1658
        return index;
1659
    }
1660

    
1661
    public FeatureIndex createIndex(FeatureType featureType,
1662
        String attributeName, String indexName, Observer observer) {
1663
        // TODO Implement observer interaction
1664
        throw new UnsupportedOperationException();
1665
    }
1666

    
1667
    //
1668
    // ====================================================================
1669
    // Transforms related methods
1670
    //
1671

    
1672
    public FeatureStoreTransforms getTransforms() {
1673
        return this.transforms;
1674
    }
1675

    
1676
    public FeatureQuery createFeatureQuery() {
1677
        return new DefaultFeatureQuery();
1678
    }
1679

    
1680
    public DataQuery createQuery() {
1681
        return createFeatureQuery();
1682
    }
1683

    
1684
    //
1685
    // ====================================================================
1686
    // UndoRedo related methods
1687
    //
1688

    
1689
    public boolean canRedo() {
1690
        return commands.canRedo();
1691
    }
1692

    
1693
    public boolean canUndo() {
1694
        return commands.canUndo();
1695
    }
1696

    
1697
    public void redo(int num) throws RedoException {
1698
        commands.redo(num);
1699
    }
1700

    
1701
    public void undo(int num) throws UndoException {
1702
        commands.undo(num);
1703
    }
1704

    
1705
    //
1706
    // ====================================================================
1707
    // Metadata related methods
1708
    //
1709

    
1710
    public Object getMetadataID() {
1711
        return this.provider.getSourceId();
1712
    }
1713

    
1714
    public void delegate(DynObject dynObject) {
1715
        this.metadata.delegate(dynObject);
1716
    }
1717

    
1718
    public DynClass getDynClass() {
1719
        return this.metadata.getDynClass();
1720
    }
1721

    
1722
    public Object getDynValue(String name) throws DynFieldNotFoundException {
1723
        if( this.metadata.hasDynValue(name) ) {
1724
            return this.metadata.getDynValue(name); 
1725
        }
1726
        if( METADATA_PROVIDER.equalsIgnoreCase(name) ) {
1727
            return this.provider.getProviderName();
1728
        } else if( METADATA_CONTAINERNAME.equalsIgnoreCase(name) ) {
1729
            return this.provider.getSourceId();
1730
        } else if( METADATA_FEATURETYPE.equalsIgnoreCase(name) ) {
1731
            try {
1732
                return this.getDefaultFeatureType();
1733
            } catch (DataException e) {
1734
                return null;
1735
            }
1736
        }
1737
        return this.metadata.getDynValue(name);
1738
    }
1739

    
1740
    public boolean hasDynValue(String name) {
1741
        return this.metadata.hasDynValue(name);
1742
    }
1743

    
1744
    public void implement(DynClass dynClass) {
1745
        this.metadata.implement(dynClass);
1746
    }
1747

    
1748
    public Object invokeDynMethod(String name, DynObject context)
1749
    throws DynMethodException {
1750
        return this.metadata.invokeDynMethod(this, name, context);
1751
    }
1752

    
1753
    public Object invokeDynMethod(int code, DynObject context)
1754
    throws DynMethodException {
1755
        return this.metadata.invokeDynMethod(this, code, context);
1756
    }
1757

    
1758
    public void setDynValue(String name, Object value)
1759
    throws DynFieldNotFoundException {
1760
        this.metadata.setDynValue(name, value);
1761

    
1762
    }
1763

    
1764
    /*
1765
     * (non-Javadoc)
1766
     *
1767
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1768
     */
1769
    public Set getMetadataChildren() {
1770
        return this.metadataChildren;
1771
    }
1772

    
1773
    /*
1774
     * (non-Javadoc)
1775
     *
1776
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1777
     */
1778
    public String getMetadataName() {
1779
        return this.provider.getProviderName();
1780
    }
1781

    
1782
    public FeatureTypeManager getFeatureTypeManager() {
1783
        return this.featureTypeManager;
1784
    }
1785

    
1786
    public long getFeatureCount() throws DataException {
1787
        if (featureCount == null) {
1788
            featureCount = new Long(this.provider.getFeatureCount());
1789
        }
1790
        if (this.isEditing() && !this.isAppending()) {
1791
            return featureCount.longValue()
1792
            - this.featureManager.getDeltaSize();
1793
        }
1794
        return featureCount.longValue();
1795
    }
1796

    
1797
    private Long getTemporalOID() {
1798
        return new Long(this.temporalOid++);
1799
    }
1800

    
1801
    public FeatureType getProviderFeatureType(String featureTypeId) {
1802
        if (featureTypeId == null) {
1803
            return this.defaultFeatureType;
1804
        }
1805
        FeatureType type;
1806
        Iterator iter = this.featureTypes.iterator();
1807
        while (iter.hasNext()) {
1808
            type = (FeatureType) iter.next();
1809
            if (type.getId().equals(featureTypeId)) {
1810
                return type;
1811
            }
1812
        }
1813
        return null;
1814
    }
1815

    
1816
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1817
        return ((DefaultFeature) feature).getData();
1818
    }
1819

    
1820
    public DataStore getStore() {
1821
        return this;
1822
    }
1823

    
1824
    public FeatureStore getFeatureStore() {
1825
        return this;
1826
    }
1827

    
1828
    public void createCache(String name, DynObject parameters)
1829
    throws DataException {
1830
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1831
        if (cache == null){
1832
            throw new CreateException("FeaureCacheProvider", null);
1833
        }
1834
        cache.apply(this, provider);
1835
        provider = cache;
1836

    
1837
        featureCount = null;
1838
    }
1839

    
1840
    public FeatureCache getCache() {
1841
        return cache;
1842
    }
1843

    
1844
    public void clear() {
1845
        if (metadata != null) {
1846
            metadata.clear();
1847
        }
1848
    }
1849

    
1850
    public String getName() {
1851
        return this.provider.getName();
1852
    }
1853

    
1854
    public String getFullName() {
1855
        return this.provider.getFullName();
1856
    }
1857

    
1858
    public String getProviderName() {
1859
        return this.provider.getProviderName();
1860
    }
1861

    
1862
    public boolean isKnownEnvelope() {
1863
        return this.provider.isKnownEnvelope();
1864
    }
1865

    
1866
    public boolean hasRetrievedFeaturesLimit() {
1867
        return this.provider.hasRetrievedFeaturesLimit();
1868
    }
1869

    
1870
    public int getRetrievedFeaturesLimit() {
1871
        return this.provider.getRetrievedFeaturesLimit();
1872
    }
1873

    
1874
    public Interval getInterval() {       
1875
        return provider.getInterval();
1876
    }
1877
    
1878
        public Collection getInstants() {                
1879
                return provider.getInstants();
1880
        }
1881

    
1882
        public Collection getInstants(Interval interval) {                
1883
                return provider.getInstants(interval);
1884
        }        
1885
}